Ever since the 1990s there has been a concerted attempt in web design to use CSS as a means to separate presentation from content.
Often it was the case that web designers were adding extra classes or ids to page elements just so that they could use CSS to alter their design; but with CSS 2, and especially in the ongoing version 3, the push has been towards minimising HTML markup.
CSS combinators assist in this quest but it isn't just about following theoretical aesthetics, but also about making you a faster, more efficient web designer.
They may be slightly confusing at first, but practice makes perfect so try to incorporate them into your designs wherever possible.
Like much of the other CSS I have been highlighting in this series of guides, they aren't used as widely as they should be. As Vitaly Friedman of Smashing Magazine wrote:
Combinators are an overlooked part of CSS development. Most juniors don’t even know they are making use of them, others are unaware of their full potential and let’s face it, even most professionals don’t really know about the ins and outs of css combinators.
It's worth noting that there is total support for these CSS properties from Internet Explorer version 7 onwards and partial support in IE6.
CSS 2.1 Combinators
E + F / Adjacent Sibling
Before explaining the finer points of this CSS code lets present a problem first and then bring the adjacent sibling property in as the solution.
Example: You want to style the first paragraph under each heading and the first paragraph only. Lets say you want to change the first letter in the paragraph.
You could just add an extra class to this paragraph, but has been stated before the aim is to minimise HTML markup.
Here comes the adjacent sibling combinator to the rescue:
#content h1 + p:first-letter{ font-size : 2em; color : red; font-style : italic; }
And this is how it would look:
Without the + sign then no design changes would be made as p is not a straight descendent of h1.
More practical examples of uses for the adjacent sibling can be found here: Fine Use for the Adjacent Sibling (“+”) Selector, The Adjacent-Sibling Selector and In Between the Lines: The adjacent sibling selector technique.
E > F / Child
The child selector is probably the most complicated of all four to understand. It involves having to climb up and down the DOM tree and probably even falling off now and again as you become lost!
Lets take a look at inheritance. Whenever you place HTML onto a page it is always the child of another page element.
Take a look at this simple makup.
<body> <div id=”wrapper”> </div> </body>
The wrapper is a child of the body. The HTML order starts from the body (as on every HTML page) and in this example then moves on to the #wrapper.
With a line of text added:
<body> <div id=”wrapper”> <p>This is a line of text</p> </div> </body>
The paragraph is a child of the wrapper while the wrapper is a child of the body but a parent to the paragraph.
Take note of the terminology parent and child. They are used a lot in JavaScript libraries like jQuery as well as in CSS.
However, the paragraph is not a child of the body, it is a descendent.
The daughter is the child of the mother, but if the daughter then has a baby of her own then that baby is a descendent or the original mother, not her child.
Here is an example of child selectors in action:
<div id="example"> <ul> <li>List item 1</li> </ul> <div> <ul> <li>List item nested <ul> <li>Nested list item</li> </ul> </li> </ul> </div> </div> #example > ul > li { font-weight : bold }
The only way of changing “list item 1” without adding a class is to use the child selector.
Confused? Well I never promised it would be easy. It is logical but it's an issue that needs explaining from different angles. Read CSS don Eric Meyer's article from 2000, The Child Selector, for a different guide.
To sum up: child selectors allow pin point precision of elements on a page while at the same time minimising markup, although if you have clean, semantic HTML you should only need to use child selectors infrequently.
Perhaps if you regularly use child selectors you may like to post up an example and an explanation of why you feel it is the best solution for that particular purpose.
E F / Descendant
From the hard to the easy. This is actually from CSS1 released in 1996.
Lets take a look at some code:
<body> <div id=”wrapper”> <div id=”content”> <p>This is a line of text in the wrapper</p> </div> <div id=”footer”> <p>This is a line of text in the wrapper</p> </div> </div> </body>
In order to highlight the text content div then you would write:
#content p { font-style: bold; }
P is a descendent of #wrapper.
This would highlight the text in the content div too:
#wrapper p{ font-style : bold; }
But also in the #footer as p is a descendent of #wrapper, #content and #footer.
As a rule, in webdesign you keep your list of descendent selectors as short as possible. It makes it easier to edit later on but it is also more efficient for browser speed; read the Mozilla article Writing Efficient CSS for use in the Mozilla UI. Also don't forget to separate the selectors with white space.
If you are having trouble understanding the concepts discussed here then read the Sitepoint articles called Inheritance and CSS Layout and Formatting.
CSS3 Combinators
E ~ F / General Sibling
If you understand adjacent siblings (E + F) then you'll have no problem comprehending this.
See the following code:
h2 ~ p { color : #ffffff; }
This changes the colour of every sibling paragraph under the h2 header.
Again, to understand this CSS correctly you need to have an appreciation of inheritance and the DOM tree which is why I have linked out several times in this post.
It's not just efficient CSS though that requires a working knowledge of these types of CSS properties but also JavaScript libraries such as Dojo and jQuery that use Sizzle. Learning CSS combinators will also help you become a better equipped JavaScript user too – bonus!