No Child Left Behind

Posted at 2005-05-09 00:00:00 in technology, web

Perhaps I'm the last kid on the block to come up with this, but I thought I'd share a neat little CSS trick I stumbled upon. In various parts of this site I use padding to make sure that, for example, text inside a box is separated by half an em from the border of the box. Putting a margin on the inside element doesn't work as well because you've got to anticipate every kind of element that might go in your container and give each one its own margin. The thing about padding, though, is that it doesn't collapse like margin does, nor do padding and margin collapse with each other.

Say you've got some p tags inside a box that has a padding of 0.5em. Now, p tags normally have 1em of top- and bottom-margin, so now your paragraph will be separated from the box by 1.5em, which is too much space. But you can't just get rid of margins around all p tags in boxes— what if you had multiple p tags inside a single box? They would no longer have spacing between each other as usual. You could give the inner paragraphs zero margin and then use adjacent selectors ("p + p") for that, but what if you have a blockquote or some other random element inside the box? You'd have to code for each of them individually.

The solution I found is CSS3's ":last-child" pseudo-class: you can simply specify that whatever the last element in the box is, it should have a bottom-margin of 0. You might think you could do that with the descendant selector like so: ".box :last-child" (note the space), but there's a problem with that. As its name suggests, the descendant selector matches descendants any number of levels deep. So in our example, ".box :last-child" would match not only the last child of the box, but also the last child of every parent inside the box as well, and so on. That's not what we want, so we turn to the child selector: ".box>:last-child" does precisely what we want.

Unfortunately, this may all be a bit academic since :last-child is a feature of CSS3, and Internet Explorer doesn't even support the child selector, much less an advanced feature like :last-child. However, all of the other major browsers do support :last-child, so it can be an elegant solution if you're using a separate stylesheet for those browsers.