company-logo

Hacking the :first-child pseudo-class into IE6 with jQuery and CSS

Firefox
IE6
continues to define the lowest common denominator for our JavaScript and CSS strategies. IE7 may finally have edged past its younger sibling in terms of market share, but as of late 2007, IE6 still commanded commanded close to a third of the market.

For the relaunch of Pathfinder’s website, we wanted our code to be standards-compliant and forward-looking, but we didn’t want things to fall to pieces in IE6. We therefore used a variety of strategies to achieve a high degree of visual fidelity between IE6 and newer, better browsers. When CSS hacks and filters wouldn’t provide us what we needed for IE6, we resorted to one of two strategies:

  1. Use JavaScript to create the desired visual effect so that only JavaScript-disabled IE6 users would see a less than perfect rendering.
  2. Just accept a degraded visual experience in a seven-year-old browser with declining market share.

Luckily, strategy No. 1 worked in most cases. Often, a single line of jQuery and a couple of CSS tweaks would create the desired look and feel. This was the case with one of IE6‘s most annoying shortcomings: its lack of support for CSS‘s :first-child pseudo-class.

The :first-child pseudo-class (and its sibling, :last-child) are crucial when, for example, you want to display a list of items in which a rule line appears between items rather than after each item, like this:

item
----
item
----
item
----
item

The pre-web standards way to create such a list would have been to use non-semantic paragraph and horizontal-line elements:

<p>item</p>
<hr/>
<p>item</p>
<hr/>
<p>item</p>
<hr/>
<p>item</p>

The post-web standards way is to create a ul element with a number of li children, then apply a border to the top of all but the first li:

<style type="text/css">
	ul li {
		border-top: 1px solid black;
	}
	ul li:first-child {
		border-top: 0;
	}
</style>

<ul>
<li>item</li>
<li>item</li>
<li>item</li>
<li>item</li>
</ul>

To get around IE6′s lack of support for first-child, most sites cheat by applying a class to the first li:

<style type="text/css">
ul li {
	border-top: 1px solid black;
}
ul li.first {
	border-top: none;
}
</style>

<ul>
<li class="first">item</li>
<li>item</li>
<li>item</li>
<li>item</li>
</ul>

That works well enough if you’re not too obsessed with semantic purity, but it presents a problem when you’re composing these lists on the fly out of reusable modules. If any given module may be plugged into any position within the list, hard-coding a class of “first” into the markup won’t work. What can you do?

In our case, we simply wrote a line of JavaScript code that calls on jQuery‘s selector mechanism to add a class to the first child of the node in question. Then we wrote CSS that applies the same properties to elements with our newly created class as it does to elements with a pseudo-class of :first-child.

In our real-world use case, the content in question isn’t structured as a ul, but rather as a series of divs, each of which contains an article. Still, the principle is the same.

The HTML looks like this. (The nested divs allow us to give div.article a dashed border while simulating a rule line with a separate, solid border on div.articleWrapper.)

<div id="content">
<div id="main">
<div class="articleWrapper">
<div class="article">
<h1>[headline]</h1>
<p>[article text]</p>
</div>
</div>

<div class="articleWrapper">
<div class="article">
<h1>[headline]</h1>
<p>[article text]</p>
</div>
</div>

<div class="articleWrapper">
<div class="article">
<h1>[headline]</h1>
<p>[article text]</p>
</div>
</div>

</div>
</div>

The CSS looks like this. For simplicity’s sake, we named our class .firstChild. (Note that we also had to deploy an !important attribute on the rules for the .firstChild class to overcome another bug – the one that causes IE6 to ignore all but the last class in a multi-class declaration.)

<style type="text/css">
#content #main .articleWrapper {
	border-top: 3px solid #ccc;
	}
	#content #main .articleWrapper:first-child,
	#content #main .articleWrapper.firstChild {
		border-top: none !important;
		}
		</style>

The JavaScript looks like this:

$(document).ready(function() {
	/*
		apply a class of firstChild to elements to fake
		the first-child pseudo-selector for IE6
	*/
	$('#main > .articleWrapper:first')
		.addClass('firstChild')
	;
}

In Firefox, the rendered page looks exactly like it should (see the first screenshot in this post). In IE6 with JavaScript enabled, it looks remarkably similar (see the second screenshot). The only difference is in Firefox’s and IE6‘s renderings of the dashed border around each article.

Ie6

Related Services:
Ajax Rich Internet Applications, Custom Software Development

  1. T.J. Reply

    I can’t wait for all these CSS3 (or is it CSS2?) psuedo-classes to be implemented into all browsers. No more using i%2 for table row classes or adding class=’first’ on certain elements.

  2. Ameenos Reply

    Hey developers,
    I hope it is not to late, I think you may not heard about “Dean Edward” , he invented a much better solution : a small JavaScript file included with your pages , and fix all IE6 problem , actually convert ie6 into a completely different browser , no more CSS nasty hacks , png can be fixed on the fly and the box model is much better . all what you have to do is to include this script in the header of every page in your website.

    <![endif]-

    I hope this will help anybody .

  3. Ameenos Reply

    This fix for the above comments , please follow this link to get Dean Edwards script for converting Ie6 into Ie7

    Dean Edward Ie6 Script

    http://dean.edwards.name/weblog/2008/01/ie7-2/

  4. Pingback: first child for ie6

Leave a Reply

*

captcha *