File Under: CSS

Simplify Your CSS With the ‘any()’ Selector

HTML5 adds a slew of new semantic tags to the web developer’s toolkit. Tags like section, article, aside, header and footer give your pages more semantic meaning and allow for more complex document structures.

While the new semantic tags are helpful, some of the changes that come along with them can make your code more difficult to style with CSS. One of the major structural changes in HTML5 is the ability to use more than one h1 tag per page. In HTML 4 heading tags typically define a hierarchy of importance — the main headline in an h1 tag, subhead in h2, sidebar headers in h3 and so on.

HTML5 greatly complicates that simple hierarchy by allowing for multiple h1 tags whose hierarchy is decided by nesting. For example, an h1 directly inside the body tag has more importance than an h1 inside a section tag. And, as we’ve pointed out before, if your section tags don’t have an h1 within them, then you probably shouldn’t be using section.

This structural nesting makes it considerably more complex to target groups of tags in CSS. It’s easy to end up with CSS that looks like this:

section section h1, section article h1, section aside h1, section nav h1,
article section h1, article article h1, article aside h1, article nav h1,
aside section h1, aside article h1, aside aside h1, aside nav h1,
nav section h1, nav article h1, nav aside h1, nav nav h1, {
  font-size: 20px;
}

That’s some pretty tangled code considering that all we’re trying to do here is target second tier h1 tags. It gets worse the deeper you need to go in nested tags — your CSS can become really tangled, really fast. The obvious answer is to simply assign classes to your various h1 tags. But littering your markup with class names is not ideal. To make life easier, and your CSS more readable, Mozilla proposed the -any() pseudo selector. Using -any() we could rewrite the code above like so:

-moz-any(section, article, aside, nav)
-moz-any(section, article, aside, nav) h1 {
  font-size: 20px;
}

The -any() selector neatly groups all of our top level tags — section, article, aside, nav — then does the same for the next level of tags, and then finally targets any h1 tags. Not only is it easier to read, it’s easier to write.

The catch — there’s always a catch with emerging standards — is that, thus far, the -any() selector is only supported in Firefox 4 and WebKit nightly builds (as of r81742 you can target WebKit browsers using the -webkit prefix). Still, given that Mozilla only proposed the -any() selector about a year ago, and it’s already in three major browsers, the future of :-any() looks good.

The W3C’s CSS working group, which oversees CSS 3, is even moving toward making any() an official draft spec. Once that happens the rest of the browser pack will likely add support as well. As always Internet Explorer’s slow development cycle may delay widespread adoption of the -any() selector, but if you’re serving IE separate stylesheets anyway, there’s no reason not to embrace -any() for the rest today.

CSS heart photo by Rain Rabbit/Flickr/CC

See Also: