Stuff & Nonsense Home

Where you’ll find designer, author and speaker Andy Clarke. The bastard.

Blogging And All That Malarkey

Enable CSS pseudo-element selectors in Internet Explorer with IE-CSS3.js

A week ago I was grumbling (again) on Twitter about JavaScript selector engines and enablers for Internet Explorer.

I was looking for a plug-and-play script that enables CSS3 :nth-of-type and other CSS3 selectors in Internet Explorer. John Resig’s Sizzle is, well, incomprehensible to me (at least) and the mighty Dean Edwards’ IE7/8 scripts don’t (yet) support the CSS3 selector types I need.

Then a tweet from Keith Clark (no relation (obviously)).

@Malarkey - Andy, I’ve just finished writing a script that emulates CSS3 selector support in IE if you’re interested. #hardboiled

Interested? Do I live on an orbiting space station?

A few days of testing, recoding (to include support for @import rules), bug fixing and more testing later, Keith fired over his latest version of IE-CSS3.js. A game changer.

ie-css3.js downloads each style sheet on the page and parses it for CSS3 pseudo selectors. If a selector is found it's replaced by CSS class of a similar name. For example: div:nth-child(2) will become div._iecss-nth-child-2. Next, Robert Nyman#8217;s DOMAssistant is used to find the DOM nodes matching the original CSS3 selector and the same CSS class is applied them. Finally, the original stylesheet is replaced with the new version and any elements targeted with CSS3 selectors will be styled.

How to use IE-CSS

To use IE-CSS, include the ie-css3.js script and Robert Nyman’s DOMAssistant in the head of your document. (Your files must run on a web server because of Internet Explorer’s security policy.)

<script src="DOMAssistantCompressed-2.7.4.js" type="text/javascript"></script>
<script src="ie-css3.js" type="text/javascript"></script>

I wrap mine in Conditional Comments to serve it only to Internet Explorer versions 7 and up (I use Universal IE6 CSS for that browser).

<!--[if gte IE 7]>
<script src="DOMAssistantCompressed-2.7.4.js" type="text/javascript"></script>
<script src="ie-css3.js" type="text/javascript"></script>
<![endif]-->

Now, write your HTML as normal. As minimal and free of presentational classes and IDs as you can make it. This is the HTML from my “It’s Hardboiled” authors page.

<section class="authors">
<h1>Hardboiled authors</h1>
<div class="vcard"><!-- content --></div>
<div class="vcard"><!-- content --></div>
<div class="vcard"><!-- content --></div>
<div class="vcard"><!-- content --></div>
<div class="vcard"><!-- content --></div>
<div class="vcard"><!-- content --></div>
<div class="vcard"><!-- content --></div>
<div class="vcard"><!-- content --></div>
<div class="vcard"><!-- content --></div>
</section>

Followed by your CSS3 selector-based CSS (supported by Firefox 3.5+, Opera 10+ and Webkit).

section.authors .vcard:nth-of-type(1) 
section.authors .vcard:nth-of-type(2) 
section.authors .vcard:nth-of-type(3) 
section.authors .vcard:nth-of-type(4) 
section.authors .vcard:nth-of-type(5) 
section.authors .vcard:nth-of-type(6) 
section.authors .vcard:nth-of-type(7) 
section.authors .vcard:nth-of-type(8) 
section.authors .vcard:nth-of-type(9) 

“It’s Hardboiled” tests


“It’s Hardboiled” authors page in Safari 4


“It’s Hardboiled” authors page in Internet Explorer 8

Now it’s your turn

I hope that you will download IE-CSS and use it on your next project (I'm already trialing it on a client project), test it to its limits and feed back reports so that Keith can make it even better. For that purpose, Keith has set up a Google Group for discussions and feedback.

Leave your comment

John Faulds

January 18 2010 @ 10:12am #

Looks very cool. Will definitely be trying it out on the next site I do.

Richard Tape

January 18 2010 @ 10:20am #

“A game changer.” — A strong statement indeed, Mr. Clarke. However, the way you describe this little gem makes me think that it’s not overstated.  If nothing else, this might, may, perhaps, please god, stop ‘certain people’ from writing comments such as:

“Yeah, this is great, but until it works in all browsers, I’m not touching it”

Things like that make me a sad panda. Things like ie-css3.js make me a happy bear!

Erwin Heiser

January 18 2010 @ 10:22am #

Nice work, but why not start checking out jQuery for these kinds of fixes?
http://api.jquery.com/nth-child-selector/

Andy Clarke

January 18 2010 @ 10:26am #

Erwin Heiser: Nice work, but why not start checking out jQuery for these kinds of fixes?

— jQuery was my first port of call, but there seems to be no jQuery to help support :nth-of-type selectors, and they are what I’m demonstrating on that page.

Julio Protzek

January 18 2010 @ 12:23pm #

jQuerys nth-child selector doesn’t help?
http://api.jquery.com/nth-child-selector/

Tony Wu

January 18 2010 @ 12:28pm #

This is brilliant! Definitely gonna have a go at it on my coming up project!

Joseph Silvashy

January 18 2010 @ 01:52pm #

Andy, jQuery has excellent support for nth-child, and more-so nth-of-type. I’d rather hack a little bit of jQuery than include another library to do something like DOM manipulation.

Thought?

Cesar

January 18 2010 @ 02:47pm #

Wicked! will result to this when the need arises.

Mathias Bynens

January 18 2010 @ 04:58pm #

@Andy,

jQuery was my first port of call, but there seems to be no jQuery to help support :nth-of-type selectors, and they are what I’m demonstrating on that page.

Erwin’s comment, to which you were replying, contained a link to http://api.jquery.com/nth-child-selector/, which proves jQuery does support :nth-of-type selectors.

Steve Clark

January 18 2010 @ 05:44pm #

Jquery is a very heavy library especially if all you are looking at is nth selectors. i think iecss.js is the way forward tiny file size.

Mathias Bynens

January 18 2010 @ 06:06pm #

Steve Clark: Agreed. But in cases where you’re using jQuery anyway, you might just as well use it to implement these selectors for IE.

Ethan

January 18 2010 @ 06:15pm #

Andy, The iecss3.js will come in useful. In this case though, I think jquery would’ve done the trick, either with :nth-child (which isn’t exactly the same as nth-of-type, but could’ve worked here) or :eq. But beyond jquery vs. iecss, I think this example might have been best solved by adding ids to your divs. It mucks up the HTML a bit, but:

1. It saves you the Javascript, which is still necessary for now and is a performance hit.
2. Using ids actually gives you more separation between content and style, since the author divs could be reordered without needing to change the CSS.
3. In this case, the structure of the page means that you don’t have to worry about needing to repeat ids, since each author is very clearly unique.
4. And, since each CSS rule is only styling one item anyway, you aren’t losing efficiency either.

Just my two cents. Thanks for the article.

Tom Davies

January 18 2010 @ 06:26pm #

I’ve been playing around with Chris Patterson’s Super selectors, which does a similar-ish thing but via jquery (which will indeed “do” nth-child selectors)

(http://skulljackpot.com/2009/04/19/super-css-selector-support-with-jquery/)

Only just started with it so can’t report on performance yet, but it is a little lighter (5.8k min) than the script you mention, once you account for the extra weight of DOMAssistant (JQuery is pretty much a given for me on most sites).

Tools like these + modernizr (+ less in my case, though it’s not for everyone) make life a heck of a lot more standable while we want n+ years for MS to get with the programme…

Chris

January 18 2010 @ 06:50pm #

Well, I really hope it’s way better than Dead Edwards’ IE7.js, because using this got me very, very much trouble and extra work.

I used IE7.js because you recommend it in your book Transcending CSS. First it looked really nice and I started to use it in all of my projects, private and commercial. Everything went fine, until I used it at a very large project. Unfortunately too late I realized that IE7.js slowed down the HTML templates so much that whenever I opened a page in IE6 there was a delay of a few seconds and even in IE7 there was a noticeable delay. And ther was NO way to stop this. So I had to do it the old fashioned way, kicked IE7.js and adapted the website as good as possible so that it also was usable in IE6.

And that got me very much extra work and the big problem was that I all had to do that in the last part of the project, where I really had time for nothing. So, I sadly have to say that IE7.js is a big shitload of crap. Dead Edwards himself seems to be too busy or whatever to respond to my emails where I confronted him with my troubles. And so I am very, very disappointed by his script and him too.

Andy Clarke

January 18 2010 @ 07:00pm #

Mathias Bynens: Erwin’s comment, to which you were replying, contained a link to http://api.jquery.com/nth-child-selector/, which proves jQuery does support :nth-of-type selectors.

—  I need :nth-of-type, not :nth-child selectors (different beasts entirely). I also don’t want to write a single $ symbol. Don’t forget, I have no clue about Javascript, not a single line the stuff.

Ethan: I think this example might have been best solved by adding ids to your divs.

— You could be right, but that’s not the point. The point is to reduce almost all the unnecessary ID and classes that we use as styling hooks and replace their use with CSS3 selectors.

Steve Clark

January 18 2010 @ 07:19pm #

@Mathias Bynens yes, If your using Jquery it would make sense to use it.

Also Keith Clark has written a really lightweight Javascript library called $DOM (http://www.keithclark.co.uk/$dom/). Its not Jquery and does not try to be but for 5k it does scrollers, accordians (Current design trends) and some pretty funky stuff.

At the end of the day I will use JQuery for most thinks as its Ajax and UI is awesome and simple, but if I dont need these things I will use Keiths ie library or $DOM if I need to do simple scrollers.

Good work guys.

Mathias Bynens

January 18 2010 @ 07:29pm #

@Andy:

I need :nth-of-type, not :nth-child selectors (different beasts entirely).

Care to explain the difference then? I’m afraid I don’t really get it :(

Btw, if you don’t wanna use $(), with jQuery, you could just use jQuery(), sayWhat(), or anything you want really.

Simon

January 18 2010 @ 07:44pm #

Andy, surely as a front-end developer you have to be expected to grasp even the basics of Javascript? I used to be like yourself but the way the industry has changed you can’t just ignore what is now an essential tool in the toolbox.

Steve Clark

January 18 2010 @ 07:53pm #

This is slowly developing into a debate about Javascript and not reflecting the true nature of the article.

Regards @Simon comments, if you are a templater who just applies design to html style templates then I would say no you dont need to know about javascript.

It depends in the way you work. I know guys who design, mock up templates and then pass that on to dev guys who add javascript and server side coding.

Keith Clark

January 18 2010 @ 08:22pm #

Hi guys,

If you use jQuery then you’ll need to write your own functions to apply any styles that are defined by unsupported selectors in IE - not all web designers are JavaScript savvy - ie-css3.js parses the style sheet and does it automatically.

I do understand the point though, if your using JQuery then it’s selector engine is loaded in memory so why download another (ie. DOMAssistant)? Well, as Andy points out, not all selectors are supported in all libraries.

I was thinking about allowing users to plug their own selector engine into ie-css3.js (allowing you to use jQuery, base2, peppy, sizzle etc.) but this would make the feature support dependent on the library used so I need to give it some more thought. I’m also seriously considering writing an IE8 only version that doesn’t use a 3rd party selector engine but a patched version of querySelectorAll() making it tiny (around 2-3k)

Ultimately, the aim of this script is to bring IE8’s CSS3 support inline with other browsers of it’s generation so we can start leveraging the power of things like ‘:nth-of-type’ now. Hopefully, when IE9 comes along with (god willing) it’s expected CSS3 support our sites should just work without modification.

Keith

trovster

January 18 2010 @ 08:24pm #

How about http://ecsstender.org ? Seems like it was built for exactly this type of use-case.

Jen

January 18 2010 @ 08:53pm #

The roles they are a-shiftin’... It seems there was a day where designers could get by without knowing JavaScript, and for those from that era who earned a quality rep, they may stay so. However, those of us who came to it a bit later must learn to understand it.

Different workflow require different tools. In one, the server-side devs write advanced js, and the client-side designer/dev writes next-to or none. In another, the server-side devs don’t do JavaScript and the front des/dev is exected to handle it. Just last week, a ruby programmer said to me that he didn’t need to learn JavaScript because of the ease of using jquery.

Now, I tend towards naïveté, but it seems to me that it is helpful if devs know JavaScript, and understand the basics of the constructs. It aids the implementation of js frameworks, it streamlines how css controls might be implemented.

JavaScript was butt ugly even just eight years ago, but it’s clearer now. It is wise to pick up a copy of [removed] The Good Parts to gain a better grasp on
this useful tech.

It looks the :nth-of-type & :nth-child selectors need some clarifying. Who’s gonna get there first? ;)

Stephen Hay

January 19 2010 @ 01:38am #

:nth-child() applies style to specific children of an arbitrary parent type. :nth-of-type() applies style to specific instances of a specific type. Thus:

p:nth-child(2) will style all paragraphs which are the second children of their parent element, and

p:nth-of-type(2) will style every second instance of ‘p’ in the document tree.

I think. :)

Stephen Hay

January 19 2010 @ 01:45am #

To correct myself:

p:nth-of-type(2) should style the second instance of ‘p’ in the document tree, not every second instance. That would presumably be p:nth-of-type(2n+1).

I think. :)

Jen

January 19 2010 @ 01:48am #

Stephen: LOL, nicely done. :) Thanks!

Nick Bergquist

January 19 2010 @ 02:09am #

@Stephen

or you could simplify it further with p:nth-of-type(even) to select every second one..

Stephen Hay

January 19 2010 @ 02:19am #

@Jen ;)
@Nick Yes. (even) and (odd) are acceptable shorthand for (an+0) and (an+1) respectively.

Stephen Hay

January 19 2010 @ 02:21am #

@Nick: I mean (2n+0) and (2n+1).

Nick Bergquist

January 19 2010 @ 02:22am #

@Nick

Odd… I mean p:nth-of-type(2n+1) is actually p:nth-of-type(odd) as it’s selecting the first incidence then every second.

Nick Bergquist

January 19 2010 @ 02:24am #

oOps… I don’t type quick enough.. sorry for any confusion!

Stephen Hay

January 19 2010 @ 02:26am #

@Nick I corrected myself (again). See above.

Andy Clarke

January 19 2010 @ 02:30am #

Stephen Hay: p:nth-of-type(2) should style the second instance of ‘p’ in the document tree, not every second instance. That would presumably be p:nth-of-type(2n+1).

— :nth-child is perfect when the content of your document is predictable. For example in list items (that only go inside lists) or table rows/cells that only go inside tables/rows. :nth-of-type is useful for selecting elements anywhere in a document. In my example .vcard:nth-child(x) would not work well because the first vcard is not the first element. But it is the first of its type.

trovster: How about http://ecsstender.org ? Seems like it was built for exactly this type of use-case.

— ecsstender is no doubt clever, but even hearing Aaron (its inventor) explain it last year at An Event Apart in Chicago, it far from being a plug-and-play designer tool. It may be perfect for developers who understand how to write Javascript, but it is not what I was looking for.

Simon: Andy, surely as a front-end developer you have to be expected to grasp even the basics of Javascript? I used to be like yourself but the way the industry has changed you can’t just ignore what is now an essential tool in the toolbox.

— We all have our skill sets and these cannot be confined to specific labels. As a designer (not a front-end developer), my skills are layout and typography. I also understand HTML and CSS fairly well. Some people think I have a talent for writing and teaching those topics too.

Javascript in particular and programming in general, requires a thought process that I my brain doesn’t make happen. It doesn’t do numbers either (I’m numerically dyslexic). So I think I’ll stick to what I’m good at and work with people who know far more than me on aspects of projects that don’t suit my skill set.

jen Strickland

January 19 2010 @ 04:39am #

“As a designer (not a front-end developer), my skills are layout and typography. I also understand HTML and CSS fairly well. Some people think I have a talent for writing…”

Ahhh… now this makes sense. The difference is that you provide copy for the sites, where that generally is the responsibility of someone else in the average situation (yes, nothing with Andy Clarke is ever average… we know! ;) ).  In your workflow, you handoff a lot of the development to a trusted individual that is typically expected of designers now.  Your skill at it and your earned reputation make you someone sought after for it.

It’s starting to make sense, on multiple levels.  I don’t love rewriting someone else’s copy (although that’s exactly what I’ll be doing over the next few weeks, along with design & code) but I do love code, except php & javascript, but I’m not giving up on javascript. Php, though, someone else is welcome to. :-P

Aaron Gustafson

January 19 2010 @ 09:28am #

Hey Andy, just so you’re aware, CSS3 selectors (including those you’re using) are supported with the CSS3 Selectors extension (a few tricky ones, like adjacent sibling selectors, aren’t supported yet, but I’m working on the remainder). In fact, I’m using that extension on the eCSStender site right now. You can view the compatibility test in the ZIP file.

Diego Perini

January 20 2010 @ 10:46am #

Andy,
why not a try with NWMatcher, it has support for what you need :nth-of-type, :nth-last-of-type, :first-of-type, :last-of-type , :only-of-type, those pseudos have been available/supported since Dec 2007:

  http://github.com/dperini/nwmatcher/

it has all what you need in term of CSS3 selectors it is very fast and since version 1.2.0 it allows developers to pass in a callback that will be executed for every visited (and matching) element. The functions to resolve “nth” and “-of-type” pseudos are separated so if you just need them they are just a few hundreds bytes, maybe 1Kbyte with extras ;-)

You can find a very minimal documentation on GitHub wikis too.

Best,

Diego

Mathias Bynens

January 20 2010 @ 07:52pm #

Now, write your HTML as normal. As minimal and free of presentational classes and IDs as you can make it. This is the HTML from my “It’s Hardboiled” authors page.

I don’t mean to be nitpicky, but your example code isn’t as “minimal and free of presentational classes and IDs as you can make it”:

<section class="authors">
<h1>Hardboiled authors</h1>
<div class="vcard"><!-- content --></div>
<div class="vcard"><!-- content --></div>
<div class="vcard"><!-- content --></div>
<div class="vcard"><!-- content --></div>
<div class="vcard"><!-- content --></div>
<div class="vcard"><!-- content --></div>
<div class="vcard"><!-- content --></div>
<div class="vcard"><!-- content --></div>
<div class="vcard"><!-- content --></div>
</section>
section.authors .vcard:nth-of-type(1) { /* CSS */ }
section.authors .vcard:nth-of-type(2) { /* CSS */ }
section.authors .vcard:nth-of-type(3) { /* CSS */ }
section.authors .vcard:nth-of-type(4) { /* CSS */ }
section.authors .vcard:nth-of-type(5) { /* CSS */ }
section.authors .vcard:nth-of-type(6) { /* CSS */ }
section.authors .vcard:nth-of-type(7) { /* CSS */ }
section.authors .vcard:nth-of-type(8) { /* CSS */ }
section.authors .vcard:nth-of-type(9) { /* CSS */ }

You can omit class=“vcard” from the HTML, and section.authors could just as well be .authors in the CSS (although I think you added that last one for clarity). Here’s what I’d use:

<section class="authors">
 <h1>Hardboiled authors</h1>
 <div><!-- content --></div>
 <div><!-- content --></div>
 <div><!-- content --></div>
 <div><!-- content --></div>
 <div><!-- content --></div>
 <div><!-- content --></div>
 <div><!-- content --></div>
 <div><!-- content --></div>
 <div><!-- content --></div>
</section>
.authors div:nth-of-type(1) { /* CSS */ }
.authors div:nth-of-type(2) { /* CSS */ }
.authors div:nth-of-type(3) { /* CSS */ }
.authors div:nth-of-type(4) { /* CSS */ }
.authors div:nth-of-type(5) { /* CSS */ }
.authors div:nth-of-type(6) { /* CSS */ }
.authors div:nth-of-type(7) { /* CSS */ }
.authors div:nth-of-type(8) { /* CSS */ }
.authors div:nth-of-type(9) { /* CSS */ }

Andy Clarke

January 20 2010 @ 07:58pm #

Mathias Bynens: One word, Microformats. Have you heard of them? ;)

Mathias Bynens

January 20 2010 @ 08:24pm #

@Andy: Ba dum tsss :)

Sure, I just didn’t realize you would be using the hCard microformat for displaying fake contact info of non-existing detective agencies. I thought you were just using it as a classname. My bad!

Derek J. Kinsman

January 21 2010 @ 01:32am #

I have a question not relating to the ie-css3.js thing. Why do you have a whole stack of divs wrapped with a section tag? Why not just:

<div class=“authors section”>
<h1>Hardboiled authors</h1>
<div class=“vcard”><!—content—></div>
<div class=“vcard”><!—content—></div>
<div class=“vcard”><!—content—></div>
<div class=“vcard”><!—content—></div>
</div>

I get pushing the new HTML5 elements forward, I just (personally) find Section, Video, & Audio needless and could have been implemented in a different way.

Vladimir

January 21 2010 @ 12:56pm #

Very good work.
Thanks

Keith Clark

January 21 2010 @ 10:09pm #

@Diego:

The new version (0.9.3) will automatically detect NWMatcher (among other libraries, including jQuery and MooTools) and use it’s selector engine.

DOMAssistant still has the best selector support based on my tests. NWMatcher comes out 2nd as it has a problem with a couple of the pseudo selectors when running oth Daniel Glazman’s and the W3C CSS3 selectors test suite. jQuery has limited CSS3 selector support.

Commenting is not available in this channel entry.
Hardboiled Web Design

Hardboiled Web Design by Andy Clarke

How the latest technologies and techniques will make your websites more creative, flexible and adaptable. Get hardboiled in all formats from Five Simple Steps. Digital formats also available at Amazon.com, Amazon.co.uk and the iBooks store.

We’ve deconstructed this site to focus on content while we restyle. Expect wonkiness during the transition.