Crazy Town Selectors

Avatar of Chris Coyier
Chris Coyier on

I recently used this selector as an example in a blog post:

.article #comments ul > li > a.button {
  /* Crazy town */
}

There was a few comments to the effect that this seemed perfectly reasonable. I think if we step through it backwards the craziness comes out more clearly.

  1. It’s an element with a class of button.
  2. But it has to be an anchor link, otherwise it won’t match.
  3. And it has to be a direct descendant of a list item. That list item better not have a paragraph tag inside of it or this won’t match.
  4. That list item has to be a direct descendant of an unordered list. It better not be an ordered list or this won’t match.
  5. That unordered list needs to be within an element that has an ID of comments. And remember this only applies if that is within an element that has a class of article or it won’t match.

So, do you have elements that are of a class of button that are direct descendants of list items that are direct descendants of unordered lists that are children of #comments that are children of .article, but that aren’t anchor links so they need to be styled differently? Crazy town.

Chances are, the selector should be:

.button {
  /* Happy town */
}

If you need to change up the button styling later, you can write selectors that are only gently more specific than that to override things.

article .button {
  /* Buttons within articles are slightly different */
}

Or add an additional class to the button to be more specific about it.

<input type="submit" class="button big-button">
<!-- I have mostly the styles of buttons but a few overrides to make me bigger -->

Very related: Shoot to kill; CSS selector intent by Harry Roberts.