CSS offers lots of different selectors, but sometimes it’s better not to use them.
A few years ago the only reasonable way to select an element through CSS was by using classes and/or tag names. If you wanted to target a specific element, you had to select it by using its classname. Selecting elements with tag names wasn’t always practicle. For example: if you use the selector div.container div, you style all div elements inside the div.container.
Most of the time that’s not what you want. Using tag names as selectors can also make design changes troublesome if you have to add more divs and need to give it a different styling. But since IE7 we can use new selectors that help us to build much more delicate CSS selectors. Those new selectors are:
- Child selector:
.parent > .child - First child selector:
.parent .child:first-child - Adjacent selector:
.sibling + .sibling - First child selector:
div:first-child - Attribute selectors:
div[id]
Now you can style the following HTML with just a single class:
HTML:
This is some title Lorem ipsum Lorem ipsum Lorem ipsum Some body text with lots of lorem ipsums in it Some body text with lots of lorem ipsums in it Lorem ipsum
CSS:
.container span {
font-family: sans-serif;
}
.container > span:first-child {
font-size: 1.5em;
font-weight: bold;
font-family: serif;
}
.container > span > span {
font-style: italic;
}
.container > span > span > span {
font-weight: bold;
}
.container > span + span {
display: block;
margin-top: 0.5em;
}
.container a:nth-child(2) {
font-weight: bold;
}
.container a {
display: block;
color: #f0f;
}
.container a:nth-child(4) ~ a {
font-size: 0.9em;
}
The advantage is that you can, as you can see, style whole blocks of HTML code with just one class. In theory you could even use no classes at all. Without ‘class’-attributes on every element, the HTML code looks just a little bit more cleaner and readable. You can also use those and other selectors in javascript libraries like jQuery to select particular HTML elements. Since most libraries are cross-browser you don’t have to worry if a selector is or isn’t supported by a browser. Consider this piece of code in jQuery:
jQuery(".container a:nth-child(4) ~ a").click( function() {
alert('hello world');
})
That’s all nice, but should I use it?
No. I use them some times, but I try to stay away from it if possible. The problem with these selectors is that they rely so much on the structure of the HTML that it becomes harder to change the HTML structure. If you take another look at the HTML and CSS that I showed as an example in the beginning of the article, it’s clear that you can’t add a few links or spans without having to change the CSS. Add some advanced jQuery selectors in the mix and you may have locked the HTML structure forever since no-one dares to change it.
Should I discard those new selectors then?
Not necessarily. Sometimes you just have no choice if you for some reason are not able to change the HTML. My personal guideline is that styling has to be predictable. So when you edit some piece of HTML code, the styling should behave as expected. That means that you don’t style your HTML in a way that the text-color of the 4th span is red.
So what can be styled predictable? If you ask me advanced selectors shine when the structure is relatively fixed. Lists are a good example. Just take a look at these code blocks below. The styling will behave normal, regardless what you do with the HTML.
HTML:
- Lorem
- Ipsum
- Dolor
- Sit
- Amet
CSS:
ul.list li + li {
margin-top: 10px; /* adds top margin to all list items except the first */
}
ul.list > li {
font-weight: bold; /* styles only the first level list items differently */
}
Javascript:
jQuery("ul.list li:nth-child(even)").addClass("zebra"); // adds zebra striping to a list
HTML elements you can easily apply advanced selectors
Besides ul, you can style uls, dls, tables. That doesn’t mean that other elements should only be styled with classes. There are always some exceptions to the rule. Just let your common sense be the judge.