Cascading Style Sheets: Selectors

In my experience, lots of web developers don’t know the fundamentals of CSS. If you develop websites, you really should know them!
By knowing the fundamentals, you can easily understand the quirks and bugs that real-world browsers exhibit, diagnose and fix issues, and develop much cleaner and simpler CSS. The following links are recommended reading, covering the important concepts and terms for CSS; including how CSS selectors are structured to identify groups of DOM elements. The contents of a selectors declaration block is then applied to all those DOM elements.

The first thing you need to do is read these two articles; they have been online for a long time, but are very well written and outline all the important aspects of CSS.

Thank you BrainJar, these articles are truly excellent! Have you read them fully? Have you understood and absorbed it all? The rest of this post covers an area that I want to make sure more developers understand how to utilize .

Selectors

Solid knowledge of this construction is important, especially if you are interested in my upcoming jQuery notes, as it uses this syntax extensively.

I want to note and describe an underlying pattern within CSS selector definition blocks. This basic pattern (This is my label, there is no official term) is used to identify sets of 0+ elements. Within a complete selector definition, there will be one or more instances of this basic pattern. There will be no whitespace, except insidestring literals.

type:pseudoX[attribute-Name{operator}attribute-Value] [attribute2-Name{operator}attribute2-Value]#id.class1.class2

This (verbose) syntax represents all options within a single basic pattern. Each option is summarized below. There will be (in order):

  • (0,1) type values (incl. *, the universal selector)
  • (0+) :pseudoX values
  • (0+) [attr] or [attr{operator}attribute-Value] items
  • (0,1) #id values
  • (0+) .class values

A (needlessly verbose) example:

ul:hover[type="circle"][title]#leftNavList.active.otherClass

In practice, these basic patterns are usually much shorter, using only a few options. Also of note is that if you are specifying a #id value, you are unlikely to need anything else in this basic block, as it explicitly references a single node. The only use for more specificity is if you reuse a common stylesheet on multiple pages with the same #id values all needing different styles, or if you dynamically change the specified nodes attributes/classes and want the styles to reflect the change.

Note that browsers are tolerant of sloppy coders putting duplicate IDs in the DOM, but IDs are expected to be unique for per DOM. It makes the expected behavior of JavaScript and CSS ambiguous - consider what the return value for the method Document.getElementById() should be.

You now know how to create a basic pattern to select a set of elements.

By applying relationship operations to two or more of these basic pattern blocks, you can refine the final selection set. The letters below are placeholders for any basic pattern from the simplest to the complex. The most important selector operators are:

  • E F : Fs that have ancestors in E (descendant selector)
  • E, F : Es combined with F (grouping selctor; top precedence)
  • E > F : Fs that have direct parents in E (child selector)
  • E + F : Fs that are direct and first child of Es (adjacent selector)
  • E ~ F : Fs that are siblings of E (sibling selector)

There are a few other operators in the newer CSS specifications, but browser implementations vary in specification level and completeness. The real power in these comes from smart use of multiple relationship operators to continue refining the selection set. In my experience, developers tend to under utilize these powerful relationship operators.

Proper use of these relationship operators means you need fewer class/ID tags (known as class-itis - I will cover in future posts), and your CSS will have a more semantic structure. Your CSS will actually be smarter and more reusable. Do you understand these examples?

  • ul#nav > li.active + a:hover[href]
  • #container + p:first-letter
  • div.header li a[target="_blank"]
  • .news + p:first-letter, h1 ~ p

Good understanding of this pattern allows you build much more concise, reusable CSS definitions. This post has focussed on the selector declaration only; in future posts I will talk about how to improve your declaration blocks and related markup for maximum CSS ore-some-ness.

Update:

I found this good cheat sheet online.  At 6 pages,  I think is really more of a writeup, but still very good.

http://refcardz.dzone.com/refcardz/jquery-selectors?oid=hom3088

I think that once you have the concepts,  1-2 pager cheat sheets are much more useful.  For example, this one for everything in core jQuery (including selectors!).

http://www.gscottolson.com/weblog/2008/01/11/jquery-cheat-sheet/

2 Responses to “Cascading Style Sheets: Selectors”

  1. Toolman Says:

    My jQuery talk went well, and my side-rant on progressive enhancement struck a chord:

    http://jamiedobson.co.uk/?q=node/57#comment-3042

  2. Recent URLs tagged Cascading - Urlrecorder Says:

    […] recorded first by cwarkentin on 2009-01-02→ Cascading Style Sheets: Selectors […]

Leave a Reply