Idiomdrottning’s homepage

CSS — Back to Basics

Ever see those puzzles for kids that are like a list of things on the left like “Donald, Superman, Kirk” and on the right you’ll see a list like “Spock, Daisy, Lois” and you’re supposed to draw lines between them?

Those lists are neat on their own but when you draw the lines they cross each other and look all tangled and messy.

Tangled lines connect Kirk to Spock, Donald to Daisy, and Superman to Lois

That’s the job of those lines, though. They are tangled and crossed and crooked and overlapping but they keep the lists themselves neat.

CSS basic history

We had three things:

On the one hand, the document’s semantics (section, list, paragraph, link etc).

On the other, the document’s appearance (fonts, colors, layout etc).

Between them, the CSS, where the mapping between those other two things should live.

People make themselves really unhappy, and their lives really complicated, by wanting to somehow make the mapping between the HTML and the CSS be 1:1.

To go back to the analogy earlier, they hate it when the crayon lines are crossed and crooked and messy. They want them to be straight lines across. So they introduce a new layer where the lines are straighter. Except… Now you have a new set of lines and now it’s those that are the crossed and tangled ones.

Instead, CSS is great as the layer that separates semantics and presentation so that they don’t have to be 1:1.

Using CSS classes (or custom HTML5 elems) is fine for those moments when you really need it.

Structural selectors are unfairly maligned. They are fine. Basically “anything goes” in the CSS.

Document Semantics

An HTML document is like a tree.

Don’t select a heading level because you think it looks nicer than another heading level. H6 should only be used as subsections in an h5 section, h2 only as subsections in an h1 subsection etc. Don’t skip levels.

Just put correct semantics in there. Ideally when you design your HTML you shouldn’t even get to look at the design, instead just view it in an outline viewer.

Presentation Semantics

This is fine:

i, em, cite {
	font-style: italic;

That’s an example of a mapping that’s not 1:1. Those three things have different semantics (as long as your HTML code is used for other things that just being rendered for display) but the same presentation.

The reverse, mapping one type of semantics to different styles depending on context, parents, siblings etc is also completely fine. Learn the selectors and use them.

It’s fine to style some h3s differently than others, depending on context.

This is what CSS is for.


We had two layers (semantics + presentation) and a glue layer between them (CSS). Life was simple.

But with the OOCSS model, we needed three layers. Semantic HTML, semantic CSS (“Structure” CSS), presentational CSS (“Skin” CSS)—which means two glue layers.

Going back to the crayon line analogy, the lines between the semantic HTML and the semantic CSS are straight. It moves the mess by creating this extra layer.

Arguably in the OOCSS model, the combo of semantic HTML + “Structure” CSS almost becomes like it’s own language that replaces/supersedes HTML, since there’s such a need for a tight 1:1 mapping between the HTML and the “structural” CSS.

I don’t think this is good. Since the HTML now needs to have so many classes, you’ve made its semantic model…

  1. …much more complicated
  2. …much less standard
  3. …much more tightly coupled to a specific visual design

I get that a lot of these proposals came from the age before <section>, <main>, etc. It’s even easier to go back to basics now, with them. An h2 or p in footer can be different-looking than an h2 or p in main.

Tailwind CSS?!

Tailwind CSS goes the other direction. It introduces a layer of over 20000 CSS classes that look like this:

.bg-red-100 {background-color: rgba(254, 226, 226);}

You use it like this:

<h1 class="bg-red-100">hi</h1>

and then it compiles away the ones you don’t use.

Those crayon lines are extremely straight between the properties layer to the newly introduced selector layer, but then they get super tangled up between that selector layer and the document.

How to get back to basics

Don’t introduce new “layers”

CSS’s messiness can do the work of keeping the two main layers (semantics and presentation) clean, and that’s OK.

You don’t need to add any extra layers, that make these CSS frameworks almost like learning new languages in their own right.

If you want to style things locally, just go ahead and do:

<h1 style="background-color: rgba(254, 226, 226);">

Longer? But that text is going to have to be read by the browser somewhere, if not locally, then as it reads the properties for the .bg-red-100 selector in the linked CSS file.

Redundant? If you have multiple elements with that same shade of red, style it globally instead. Go ahead and write up a selector that finds them:

h1, div a, ol li {background-color: rgba(254, 226, 226);}

Embrace many-to-many…

… and think in both directions, both backwards and forwards.

In CSS, the same selector can be assigned to multiple blocks. This is a great thing to reduce duplication. This also can also replace a lot of the use cases for “mix-ins”.

Here is an example:

a {text-decoration: none;}

h1 a {letter-spacing: 0.5em; 
      color: #b0381e;}

h1, h2 {font-size: 1em;
        font-weight: bold;
        text-transform: uppercase;}

h2 {margin-bottom: 0px;
    margin-left: 0px;}

This is many-to-many in action.

Each property-value combination is only specified once, but, it can be assigned to many selectors. And, each selactor can be assigned to many styles.

In the example, I wanted both h1 and h2 to be bold and uppercase and have a 1em size. So those properties are assigned to the h1, h2 selector combination.

I additionally wanted h2s to have no bottom margin so that they run right into the following text. I wanted links in h1 to be letter-spaced, and red, while links across the entire page get their text-decoration (the underline) removed.

Now, I’m not saying this is the easiest, comfiest way to write the CSS. If you want to consider this an, uh, a “compilation goal” and make tools to generate this kind of CSS, go ahead.

You don’t wanna be in a position where you wanna see “OK, so what styling do I have on this element” and you’re tripping yourself up because you don’t see which blocks apply to it.

But… we have good tools. There are inspectors that lets you easily see those things.

CSS does have a structure

CSS is similar to AWK:

thing you're looking for { what you wanna do with it; }

This is also why mixins a la Sass, especially if you don’t use the argument feature, are so backwards and kind of gives me a vibe of not grokking the intended semantics of CSS.

Put your styles within { these curlies } and then put what you want that style to apply to in front.

Like, I often use:

h1, h2 {text-align: center; font-style: italic;}
h2 {margin-top: 3em;}

I don’t need to repaste / mixin / partial / include the center & italic part, I can apply that to both h1 and h2, while the margin I only wanna apply to h2.

Yeah, yeah, it’s a little bit right-to-left, I get that, but that’s how it is.

selectors { properties }

This is the way.

Sass’ mixins at least does have a purpose if there’s some variable you wanna, uh, vary, but apply in different ways across different properties. But Sass’ nested selectors are just inside out. That’s not a good way to think about your style sheet; it’s the enemy of reuse and consistent style. Which, in turn, is why they have all those includes and partials and mixin to compensate. 🤦🏻‍♀️

Use classes sparingly

When the design really needs the HTML document to be marked up differently than its own natural semantics, use a class.

The CSS selector language is really powerful and often you don’t need a class, but there is one (arguably pretty common) cirumstance where you should just go ahead and use a class.

Ask yourself two questions.

  1. Are the elements you want to style arbitrary and without semantic rhyme or reason? (If not, you can use a CSS selector.)

  2. Does the style feature multiple times on the page? (If not, you can use a local style attribute on the element’s tag.)

If yes to both questions, a class is just what you need! For example, you have a list of entries and you want some arbitrary items to be green and big. You don’t wanna mark them up semantically with <b> or <strong>, and, there’s more than one so you’d want to reuse the properties so a style attribute isn’t appropriate.

If you want the green & big styling to be “invisible from Lynx”, i.e, it’s just there to make the page pop and look varied and Memphis and cool, then go ahead with the class.

If instead it’s the case that it’s a regular or logical thing, like the first paragraph on every page or every book citation or something like that—CSS can select that!

Summary of Practices