The cascade

Type, class, and ID selectors

Select elements by type, reusable class, or unique ID and choose the least specific selector that clearly expresses your intent.

A selector tells the browser which elements a rule applies to. There are three basic kinds, and you’ll use them constantly.

A type selector is just the element name. It matches every element of that type:

p {
  max-width: 65ch;
}

Every paragraph on the page now has a maximum width.

A class selector starts with a dot and matches elements that have that class:

.card {
  padding: 1rem;
}

This matches all three feature cards on our page, because they share class="card". An element can have several classes, separated by spaces in the HTML, and each one can be targeted separately.

An ID selector starts with # and matches the one element with that id:

#features {
  border-top: 1px solid;
}

An ID must be unique in the document, so this rule can only ever hit one element.

Which one to use

Classes are my default for anything that looks like a component. They can repeat, they say what the element is for, and as we’ll see in the specificity lesson they are easy to override.

Type selectors are good for broad defaults: paragraph width, heading line height, link color. Things that should apply everywhere unless a component says otherwise.

IDs are great for fragment links (href="#features"), for connecting a label to its input, and as hooks for JavaScript. For styling, I avoid them. An ID selector is very hard to override, and you’ll end up fighting it later.

Name classes after the role

A selector matches whatever carries the class. It doesn’t check that the element makes sense. If you put class="card" on a footer, the footer gets card padding.

So name classes after a stable role, not after how the thing looks today. .card and .site-header still make sense after a redesign. .blue-box turns into a lie the day the box becomes gray.

Grouping selectors

When several selectors share the same declarations, list them separated by commas:

h1,
h2,
h3 {
  line-height: 1.1;
}

This is the same as writing three separate rules. Each selector is matched on its own. Grouping saves typing, it doesn’t merge them into one stronger selector.

Try it on the course page. Add .card to the hero section, and the hero picks up the card padding. Remove the class from one of the articles, and that card goes back to plain. The rule never changed, only which elements it matched. Watch the Styles panel in DevTools while you do it and you’ll see the rule appear and disappear.

Lesson completed