Update (April 24, 2024): Yeah, this is a really old post. :first-of-type
has existed for years now. Maybe it even existed when I wrote this in 2012, but I wasn’t aware of it.
I like to think I’m a pretty adept CSS developer. I may not have written the book, but I have a solid understanding of CSS and can do some sophisticated things with it.
But one place I always get snagged with CSS is in using the :first-child
pseudoclass. The idea behind :first-child
is that you can apply different styles to the first child element inside a parent element than for the rest of the instances of that child element inside the same parent.
A way I end up wanting to use it a lot is to give the first child different margins than the rest. Maybe most of them need margin-top: 2em;
for instance, but I want the first one to be flush to the top of the parent by using margin-top: 0;
to override the default margin.
The full CSS might end up looking like this:
div>h2 { margin-top: 2em; }
div>h2:first-child { margin-top: 0; }
And then that would be put together with some HTML like this:
<div id=”content”>
<h2>First header</h2>
<p>This is the first paragraph!</p><h2>Second header</h2>
<p>And, surprise! This is the second paragraph!</p></div>
So far, so good. The problem is, what if you stick something else into the <div>
before the first <h2>
that isn’t another <h2>
? Say, something like this:
<div id=”content”>
<div class=”floating_sidebar”>This should be floating to
the right of the content.</div><h2>First header</h2>
<p>This is the first paragraph!</p><h2>Second header</h2>
<p>And, surprise! This is the second paragraph!</p></div>
You may have guessed at this point that I’m not describing a hypothetical situation here. This is a stripped-down version of exactly what I’m building right now. The problem is, now the first <h2>
is no longer the first child element of the parent <div>
overall, so the :first-child
CSS gets ignored.
True, it’s not the first child element, altogether, inside the parent. But it is the first <h2>
child inside the parent. I can understand how, in other circumstances — say, if the inserted <div>
wasn’t a float — you’d want the h2:first-child
not to apply here. But in general it seems to me that if you’re specifying a tag with your :first-child
, it should only matter that it’s the first tag of that type under the parent, even if there are other different tags before it.
I guess the real solution here would be to create another pseudo-class that does what I want. Now I just need to convince the standards folks and the browser makers to do that.
Note: The sample HTML was kind of a mess when I originally posted this. That’s what happens when you write a blog post in a hurry before rushing out the door for a meeting. It has now been corrected, and I made some other edits for clarity while I was at it.