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.

Comments

  • Anonymous
    January 01, 2003
    The comment has been removed

  • Anonymous
    January 01, 2003
    Thank you for sharing your article helped me a lot.

  • Anonymous
    May 13, 2010
    Stop with the "same markup" lies until you have Canvas support.

  • Anonymous
    May 13, 2010
    canvas: is your theory that if you're annoying, you'll get your way? Most kids grow out of that before their tenth birthday. Have you hit that milestone yet? sharon: thank you!

  • Anonymous
    May 13, 2010
    <canvas> or <sence> or <stage> or direct manipulation of bitmap data of <img>

  • Anonymous
    May 13, 2010
    infinite: What's up with those mysterious elements html:sence and html:stage you are referring to? I can't find them in any spec, nor searching the web. The only time i heard about them before was in the comments of another article of this blog. And i believe it was you who wrote that too, although if i am right you were a little bit less unfriendly then and perhaps a little more on topic, too.

  • Anonymous
    May 13, 2010
    @karl: The <sence> or <stage> are something that provides same function that <canvas> has but in the different interface.

  • Anonymous
    May 13, 2010
    @infinite Could you provide a link to the spec that <sence> and <stage> are contained in? I've never heard of those either.

  • Anonymous
    May 13, 2010
    The comment has been removed

  • Anonymous
    May 13, 2010
    The comment has been removed

  • Anonymous
    May 13, 2010
    Since ::selection was removed from the W3C recommendation already, wouldn't ::-ms-selection be to correct name for it? After all, it's no longer a defined pseudo-element but rather a vendor-defined one. After all, you've done the same to various CSS properties in IE 8.

  • Anonymous
    May 13, 2010
    The comment has been removed

  • Anonymous
    May 13, 2010
    The comment has been removed

  • Anonymous
    May 13, 2010
    Superb. Mucho sincere congrats! If you have a few spare cycles, could you please submit an implementation report (à la [1]) to the CSS Working Group. I know the Selectors spec is already accepted as REC by the W3C Director but still, showing IE9 passes all tests here is a very good point since former versions of IE were failing so much at the Test Suite it was pointless to have them in the Implementation Report... Thanks. [1] http://www.w3.org/Style/CSS/Test/CSS3/Selectors/20091025/reports/CR-ImpReport.html Daniel Glazman W3C CSS Working Group, Co-chairman

  • Anonymous
    May 13, 2010
    IE9 Team, you just made my day. Thank you :) S.

  • Anonymous
    May 13, 2010
    This is very exciting news!  Once IE9 ships I'm sure that developers everywhere will be excited to be able to finally use all these features seeing that IE has finally stepped up to the table with support. An interesting side-effect will take place however in that support and use of IE6 through IE8 will drop dramatically. I personally no longer support IE6 at all (not even a limited version... IE6 users are given an outdated browser warning with links to a randomized list of modern browser options (Firefox, Chrome, IE8, Safari, Opera). When IE9 ships, support for IE7 will also be dropped.  And users detected as running Vista or Win 7 will be prompted to upgrade to IE9 too. I'm so excited about all this.  Supporting the latest IE version will be sooooooooooo much more pleasant than any currently shipping IE version.

  • Anonymous
    May 13, 2010
    The comment has been removed

  • Anonymous
    May 13, 2010
    @haroldjr "Once IE9 ships I'm sure that developers everywhere will be excited to be able to finally use all these features seeing that IE has finally stepped up to the table with support. An interesting side-effect will take place however in that support and use of IE6 through IE8 will drop dramatically." That's misguided at best. As much as we'd all love to be supporting just IE9, with it's lack of support on XP and the slow take up by the masses, you're still going to be supporting IE7 and IE8 for a while, if you don't want to severely limit your / your clients target audience.

  • Anonymous
    May 13, 2010
    So if I mix inverted (white-on-black) and normal text on my site then I have to care not to make selections hardly visible? IMHO, it would be better if the default foreground font colour of selected text depended on the selection colour, ie. if the background colour is dark then the text colour defaults to white, otherwise black. The same for the default background colour, so that when only the background colour xor the font colour is set for selected text, it always stays readable.

  • Anonymous
    May 13, 2010
    The comment has been removed

  • Anonymous
    May 14, 2010
    There is one area in CSS that is in particular troublesome, form elements. Would be very interesting to hear what MS's thoughts on this is in relations to "same markup" and all these test cases submitted to make the W3C standard less ambiguous.

  • Anonymous
    May 14, 2010
    @Gryobo - thanks I updated the item to E::selection in the list at the top. @Daniel Glazman - thanks.  I will work with Sylvain to get that done. @Wurst - thanks for the thoughts.  It's an interesting idea.    

  • Anonymous
    May 14, 2010
    @hAl "Those are actually CSS2 elements and, as such, were supported in IE8 already as IE8 already  supports all elements in CSS 2.1 ." True, but the double colon notation versions of those pseudo-elements is new. While I'm pretty sure it's just a semantic change, I'd like to know if there are any function differences between single and double colon notation, which syntax is preferred for general use, whether they can be used interchangeably (the specificity of each).

  • Anonymous
    May 14, 2010
    I see this as good news overall, but... Canvas support please?

  • Anonymous
    May 14, 2010
    For everybody asking for canvas support: the chance IE9 will support canvas is near 100%. "Why?", you'll aks. Easy:

  1. Microsoft has drunk the html5 koolaid. It confirmed support for html5.
  2. Microsoft supports SVG, which is much harder to implement than canvas.
  3. The fear that Microsoft is protecting their own technologies (VML) does not apply: VML is much more like SVG than canvas. So, from this point of view, Microsoft would support canvas easier than SVG.
  • Anonymous
    May 15, 2010
    The comment has been removed

  • Anonymous
    May 15, 2010
    @Evan Byrne  I completely agree.

  • Anonymous
    May 15, 2010
    I would like to see canvas support please

  • Anonymous
    May 15, 2010
    The problem with ::selection is that it got released as a Candidate Recommendation in November 2001, however, it got dropped again in March 2010 due a number of issues, mostly in relation to nesting the element and styling. Because of this UA's currently implement the pseudo-selector in a different manner even though none (except for Firefox) require the vendor prefix. Whether they should is debatable  as the specification was published as a candidate recommendation and vendors shipped software with the feature before going back to a draft.

  • Anonymous
    May 15, 2010
    Feature request- please make it easy for users to disable ::selection.

  • Anonymous
    May 15, 2010
    Scenario: I have 5 email accounts (gmail, hotmail, yahoo, etc). When I check email, I usually check them all. I also visit multiple news sites frequently (cnn, bbc, finance.yahoo, news.google). Again, I usually open all of them at the same time. It would be great if I could fire up IE, open a few tabs, navigate to different sites in them, and then choose "Save Tabbed Session". I could then have multiple saved tab sessions (e.g., named "Email", "News", etc). The next time I start IE, I can then just choose "Load Tabbed Session", and choose one of my saved ones. Automatically, all necessary tabs would open up, with each navigating to one of the sites in the session. P.S. I couldn't figure out how to give this suggestion via Connect. It seems Connect always assumes I am filing a bug agains the IE 9 Platform Preview.

  • Anonymous
    May 15, 2010
    I was wondering if IE9 supports returning computed values for CSS in JS.

  • Anonymous
    May 15, 2010
    @Mustansir Doctor Doesn't IE8 already do that?   Add Current Tabs to Favorites once the tabs you want are open.  Then click on the arrow next to the Favorites folder that was created to open all of them later. Or do you mean something else?

  • Anonymous
    May 15, 2010
    Mozilla have taken careful measures to stop queries into browser history based on the :visited selector. Will IE9 be equally safe in this regard?