🏠 CSS Basics

By Robert Laing

Like most people, I find CSS bewildering with its huge numbers of units, properties, selectors, layouts… all of which is nearly impossible to debug since invalid rules are simply ignored by browsers.

An important tool to check if your CSS is correct is jigsaw.

My notes on selectors are in my HTML Elements since querySelector’s argument uses the same syntax. With CSS it’s important to remember selectors can be combined, turned into a list using commas, a list of children using >, any descendants using a space…

I’ve settled on only a tiny fraction of what’s available which I’ve noted down here.

html or :root?

The :root CSS pseudo-class matches the root element of a tree representing the document. In HTML, :root represents the <html> element and is identical to the selector html, except that its specificity (0-1-0) is higher than html’s (0-0-1). — MDN’s :root article

The colon prefix marks :root as a pseudo-class. I’d generally find html easier to understand, but there’s a convention to set global variables using two dashes (–) prefixes.

:root {
  --card-height: 22vh;
  --card-width: calc(var(--card-height) * (500/726) + 6px);
  --adwidth: calc(50vw - (var(--card-width) * 2.5) - 6px);
}

These variables can be accessed in any ruleset using the var() function.

The style I’ve settled on is to declare global variables in a :root ruleset and base font-size etc in an html ruleset.

Nesting landscape or portrait

Thanks to nesting at-rules, specifically @media along with orientation, global variables can be conditionally set to support either landscape (ie desktop) or portrait (mobile which nowadays makes up the bulk of visitors).

@media (orientation: landscape) {
  :root {
    --card-height: 22vh;
    --card-width: calc(var(--card-height) * (500/726) + 6px);
  }
}

@media (orientation: portrait) {
  :root {
    --card-width: 15vw;
    --card-height: calc(var(--card-width) * (726/500));
  }
}

vh vs vw

The vw value is obtained from <meta name="viewport" content="width=device-width"> as explained in the html basics article.

vh and vw are relative length units based on viewport. For landscape, height is typically what decides how to best use the available screen real estate, whereas for portrait it’s width.

Font Size

For responsive design, there’s clamp(min, preferred, max).

The preferred value is given vw units so it grows and shrinks with the size of the device. Through trial and error, I’ve found 1.2vw is about the same size as 1em on a desktop.

Lighthouse used to test Document doesn’t use legible font sizes which failed if much of the text was smaller than 12px, so that’s probably a good value for the min value. For max, I somewhat arbitrarily go for 2rem for normal text.

To start with, we set 16px as the font size on the <html> element. — CSS values and units

Whether that’s good advice or not I’m not sure. Some argue that’s unecessary because its the default anyway, and furthermore could overwrite a user’s preference for large fonts. But there does seem to be consensus that rem is the best unit.

Font Families

I thought font-family: system-ui; was good practice, but according to MDN, using it for large paragraphs of text is bad, and font-family: sans-serif; is better.

Though :root and html are nearly synonymous, I prefer to put non global-variables in a html ruleset for clarity.