The CSS Corner: CSS3 Selectors

CSS3 Selectors enable complex styling of webpages using simpler CSS and less script than previously possible. As we demoed back in November, and updated in March and May with the IE9 Platform Preview Builds, IE9 includes full support for CSS3 selectors. This is a feature which web developers requested and we are excited to fulfill this need.

  • E:root
  • E:nth-child(n)
  • E:nth-last-child(n)
  • E:nth-of-type(n)
  • E:nth-last-of-type(n)
  • E:last-child
  • E:first-of-type
  • E:last-of-type
  • E:only-child
  • E:only-of-type
  • E:only-child
  • E:only-of-type
  • E:empty
  • E:target
  • E:enabled
  • E:disabled
  • E:checked
  • E:indeterminate
  • E:not(s)
  • E::selection

Our goal is to enable new selectors in your webpages in a way that lets the same markup work across browsers. A nice side effect of this work is better results in test suites that measure selectors support. IE9 now passes 100% of test cases on css3.info, 100% of the W3C CSS3 Selectors Test Suite, and Acid3 tests 34 through 37 and 39 through 44.

Nth-child and other structural pseudo-classes

Nth-child and other structural pseudo-class selectors allow you to style elements based on some structural information about how they fit in the DOM tree without requiring that you label the elements in any manner. Nth-child selectors are especially useful if you want to maintain styling even as the structure of your page changes.

One of the best use cases for nth-child selectors is to alternate the background color on table rows, for example like this:

Here is a table where the background color
of each row alternates between
light blue and
dark blue. ...

To style this table without using nth-child selectors, one common technique is to label each row in the markup and then assign a style to each class of rows:

 <table>
   <tr class=”odd”> <td>row1</td> <td></td> </tr>
   <tr class=”even”> <td>row2</td> <td></td> </tr>
   <tr class=”odd”> <td>row3</td> <td></td> </tr>
    …
</table>

Then in the CSS you have:

 .odd {background-color:lightblue;}
.even {background-color:blue;}

This markup will style the table with the desired formatting, however, this solution breaks down if the table is dynamic or interactive such that rows can be added or removed. If you insert a row at the top of the table, you now have to use script to change the class name of every row in the table.

Using an nth-child selector, you don’t need any markup on the table rows themselves. Your style sheet simply contains:

 tr:nth-child(odd) { background-color:lightblue;}
tr:nth-child(even) {background-color:blue;}

Now if you add or remove rows from the table, the styling remains correct without needing any script.

As you can see above, nth-child selectors accept the keywords ‘even’ and ‘odd’. These selectors also accept an argument of the formula an+b. The ‘a’ and ‘b’ values are constants and the ‘n’ value increments starting from 0 until there are no more elements possible to select.  For example, tr:nth-child(2n+1) would be evaluated as follows:

  • n=0, 2n+1 = 1, select the tr element which is a first child.
  • n=1, 2n+1 = 3, select the tr element which is a third child.
  • n=2, 2n+1 = 5, select the tr element which is the fifth child. 

As you follow the evaluation, you’ll notice that 2n+1 is equivalent to ‘odd’ and ‘2n’ is equivalent to even.  For simplicity, if ‘a’ is 1, you may omit ‘a’. ‘n+3’ selects every child starting from the 3rd child. If ‘a’ is 0, you may omit ‘an’.  ‘0n+6’ == ‘6’ which selects only the 6th child.  If ‘b’ is 0 you can omit ‘b’ from the formula. ‘3n’ selects every third child.

UI element state pseudo-classes

The UI element state pseudo-classes allow you to select UI elements based on their current state.You can select elements which are enabled or disabled, checked, or in an indeterminate state. This is useful, for example, if you want to remind your users to accept your EULA before downloading a trial. If the check box for your license agreement is unchecked you can add text to remind customers to check the box, and that text can be hidden when the box is already checked. It’s not that difficult to enable this scenario with script, but with UI element pseudo-classes you don’t need the complexity of script and your pages run faster.

Negation pseudo-class

The negation pseudo-class enables you to negate a simple selector. *:not(div) selects all elements except div elements, p:not(.explanation) selects all paragraphs not in the class ‘explanation’. The negation pseudo class can’t accept itself as an argument, so double negatives such as, :not(:not()), are not valid and pseudo elements are also not accepted as arguments to the ‘not’ selector.

::selection

The selection pseudo-element enables you to specify how you want content to look when users highlight text on your website. By default, when a user selects text in IE, the background color changes to blue and the text color changes to white:

a website with selected text, blue background, white text

Using the ::selection pseudo-element you can customize the selection text color and background color to fit the theme of your site. If you want to style selected text with an orange background and black text, as done at https://www.zeldman.com, you can apply the following selector:

 ::selection { 
    background-color:orange;
    color:black;
}

a website with selected text, orange background, black text.

While the selection pseudo element is an interesting scenario, allowing arbitrary styling in this selector can cause some unintended side effects.  For example, if the selection pseudo element changes the font or the text size, that will change the size of text as the user selects it, creating a confusing experience. For this reason, IE only supports the color and background-color properties in the selection pseudo-element. This is equivalent to how other browsers support this selector.

In addition to limiting the properties which can be set through the ::selection pseudo class, IE9 defines a few default values for the case that a web developer only sets color or background-color but not both:

  • If only the color property is set then the ::selection background-color defaults to transparent
  • If only the background-color property is set then the color defaults to whatever color it was before it became part of the selection.(The color does not change)
  • If only non-supported CSS properties are set in the ::selection rule then the selection rule is ignored and the default IE selection styling is applied.

Observant readers may notice that the selector pseudo-element is not included in the most current version of the CSS3 Selectors draft. We implemented ::selection in support of our goal to allow developers to write same markup because we see it in use on the web and supported in other browsers.

CSS3 selectors add a lot of power to your style sheets. We’d love to hear about interesting ways you are using these selectors on your websites and certainly if you encounter any bugs with our implementation please let us know.

Sharon Newman
Program Manager

Edit 5/14: Updated ::selection to E::selection in the list of new supported selectors.