Child and Sibling Selectors

Published
April 14, 2010
by
Chris Coyier

Do you know what the difference between these selectors are?

ul li { margin: 0 0 5px 0; }
ul > li { margin: 0 0 5px 0; }

I'll admit it took me longer than it probably should have (way back when) when I was learning the basics of CSS. In both cases, they are selecting list items that are children of unordered lists. But there is a difference between children and descendants.

The first selector above is a decendant selector. It will select any list items that are anywhere underneath an unordered list in the markup structure. The list item could be buried three levels deep within other nested lists, and this selector will still match it. The second selector above is a child combinator selector. This means it will only select list items that are direct children of an unordered list. In otherwords, it only looks one level down the markup structure, no deeper. So if there was another unordered list nested deeper, the list item children of it will not be targeted by this selector.

I think everyone understands the basic decendent selector, but let's do a quick overview of the other selectors in this style: the child combinator, the adjacent sibling combinator, and the general sibling combinator.

Child combinator

This one we covered in the intro to this article. Let's drive that same example home with a visual:

I think the nested list is a perfect example of why this selector is useful. It can be thought of as a way to prevent styling from cascading down further than you would like it to. Maybe you want to make the outer-most list items large and header-like, but the nested lists smaller and more body-copy like. Using a child combinator you can select only those top level list items and not worry about the large/header styling cascading down to the nested lists and having to fight against that styling.

Adjacent sibling combinator

An adjacent sibling combinator selector allows you to select an element that is directly after another specific element.

These selectors can help you apply styling in a contextual way. Perhaps you have a bunch of articles on a site. Most of them start with <p> elements and it looks great. But some of them start with a <ul>, which have top and bottom margin on your site to look good within an article. But when they start an article it causes an awkward gap. The latter selector above would zero out that top margin when it begins an article (immediately succeeds a title).

Hopefully helpful graphic:

General sibling combinator

The general sibling combinator selector is very similar to the adjacent sibling combinator selector we just looked at. The difference is that that the element being selected doesn't need to immediately succeed the first element, but can appear anywhere after it.

If we use the same example structure as above, the last <p> element will be selected by p ~ p as well, because it is preceded by another <p> element, even though not directly.

Note that in both the general sibling and adjacent sibling selectors the logic takes place within the same parent element. That's what siblings means... sharing the same parent. In the graphical examples above, that's what the wrapping <div> is there for. If there was another <p> element after that <div>, it would still be selected by both div ~ p and div + p though, as it would be a sibling and an adjacent sibling to that <div>.

Browser Support

These are all good-to-go in IE 8 and up and all other modern browsers. IE 7 also has support, but be aware that HTML comments can screw them up and cause them to not match when in between siblings.

If you need deeper support than that, the ie7-js project (now updated all the way to ie9.js) will get you support for all of this back to even IE 5.5 with a single simple JavaScript file inclusion.

Wish upon a star

I've said it many times before, but one of the major missing selector styles in CSS is some kind of "contains" (or "has" or "qualified" or whatever you want to call it. The idea being like "select all paragraphs that contain images".

Adobe launched dreamweaver cs5 with a lot of features and one of them is css instection mode which will handle css properties.
My question is that, will it be possible to fix CSS properties without knowing them in detail using dreamweaver cs5 . I have collected other major features at a post here Dreamweaver CS5 features for CSS properties and some others new features

And even talking about IE8, I’m not convinced it’s bad. Undesirable, yes, but acceptable when you look at the big picture.

IE7 was (afaik) mainly a feature catch-up session.
IE8 was a css catch-up session, their attempt to fully support CSS2, and almost passes acid2.
IE9 seems like it’s going to have impressive css3 support and html5 support, as well as support for hardware acceleration (though it’s debatable why this is needed).

So, while IE isn’t moving as fast as we all would have liked it to, it *is* coming along.

The example might be a little weird because some things might cascade down the list anyway, since a nested list is a child of that top level list item… But the child selector still doesn’t actually select the lower-level list items.

That sounds like gibberish kind of… Here is an example where the inner OL has a color of black, then the parent list items have a color of red. The list item selector is more specific, but it doesn’t select the OL or the OL LI’s, so the color remains black.

I get the example of the link:
the ol is black, so the bullet and the word “test” will be black. However the ol is enclosed by li tags so the entire ol becomes an li which is the child of the ul and with the style ul>li color red the ol will be red which means the bullet is red. OK clear.

In your example the ol is enclosed by the li tags from List Item 2, as a result the whole ol will be styled in the same fashion as the ul>li.

If you take the ol out of the afore mentioned li tags then Nested Item 1 and 2 will no longer be affected because they are children of the ol.

If you change the ol into ul you get a parent ul with 3 children (3 li) of which 1 has 1 child (the second ul which inturn has 2 children, the Nested Items.

OK so now ul>li will target the 3 li that are children of the top ul but also the 2 nested li from the nested ul…

Are you worried that using this would select all the list items in nested lists anyway (not help “stop cascading” like I mentioned?).

If that’s the case, I think in general usage this would be combined with, for example, and ID selector. So like ul#main-navigation > li would only select those top level LI’s without selected other nested LI’s

Yes an ID would do the trick but this brings me back to me initial point.

Let’s say (in your example) you want the font color of the content of the 3 top li’s (so the text List Item One, Two and Three) to be red.
If you use ul>li not only will the 3 li become red but also the entire ol (bullets and text Nested Item One and Two.
If you take the ol out of the 2nd li (with content List Item Two) then indeed only the 3 main li’s will be red, but only because the nested li’s are children of a ol.

Change this ol into ul and the content (text) of the 3 main li’s AND the content (text) of the 2 nested li’s will be red.

So the cascade doesn’t stop at the first level, but goes through the whole thing and will hunt down each and every li that is a child of a ul, no matter how deep is sits.

But I think this language is what is confusing:
“In otherwords, it only looks one level down the markup structure, no deeper”

Which is not correct. I just tested this. Without any other styling (yes i see your jsbin Chris, and you are styling the ol), it indeed DOES go deeper. It will hit every li within that ul, no matter if the you use an id/class or not.

You would have to style the ol in order to get the nested li’s to change color (which is what Chris has done in the jsbin thing)

Thanks for this Chris!
You mention it being supported across modern browsers, is it all good with safari and firefox then?

This could be really useful when styling lists in certain ways, I’m forever adding classes to items to make them appear different but using the technique shown this won’t be an issue.

But something Leonardo mentioned above me about the ul>li targeting any li that is a child of a ul, does this mean you will have to have instead of using another ? Hope I’m making sense here! But if you were to us a within a and use ul>li this will surely still style the inner ul li’s?

I really wish there was a “parent” selector. So you could select the container of an item. This would be especially useful when you’re not sure what container the content will be in, but you need to add a style to that container.

Chris said:
“These are all good-to-go in IE 8 and up and all other modern browsers. IE 7 also has support, but be aware that HTML comments can screw them up and cause them to not match when in between siblings.”

the reason why you can’t have a “parent of” selector is due to a restriction of CSS to use a once-over algorithm.

When a browser parses css selectors, it can apply the styles to each element by iterating through each element exactly once. if parent selectors were allowed, the parser would need to travel back up the xml tree, which is exponentially slower.

“I’ve said it many times before, but one of the major missing selector styles in CSS is some kind of “contains” (or “has” or “qualified” or whatever you want to call it.”

I haven’t looked into this subject in any detail, but I understand that would go against the concept of the cascade itself, and thus isn’t on the cards. I’ve used jQuery to select anchors which contain images (to take away a border-bottom).

Thanks Chris! I’ve seen these around a lot but admittedly have been lazy and never took the time to understand what the heck they were doing. These will be very useful going forward. I’ll likely try them out on my new site.

I’ve had mixed success using child selectors, primarily due to IE6 and IE7 issues.

I tried the IE7.js and IE8.js but they both seemed somewhat buggy at the time and caused even more erratic behaviour after inclusion.

For some reason it was completely unable to handle certain absolutely and relatively positioned elements resulting in blocks of html not being displayed at all in IE6 for no apparent reason. I ended up having to discard the JS inclusion and use a conditionally included ie6.css file instead.

Those diagrams are so key for learning the difference between the selectors, it can be very confusing to explain.

This comment thread is closed. If you have important information to share, you can always contact me.

Treehouse is where you go to learn HTML, CSS, and how to build iOS apps. It's a complete education in modern web and app technology, designed to get you ready for a hot new job or to kickstart your own business.

The Lodge is a member login only area with access to video training on how to build websites from scratch using the best modern tools.

How many people touch the CSS in your current main project?

What now? I have some ideas for you.

Go explore CodePen!

As a front end designer and developer, you should have an account on CodePen so you can save your snippets, present your ideas, and engage with the rest other front end folk. I'd encourage you to go PRO as well, to unlock the full power of CodePen.

Get the newsletter!

You should sign up for the CSS-Tricks newsletter. It's a clean copy of all the blog posts each week, combined together, right to your inbox. If email isn't your thing, there is an RSS feed, iTunes, and lots of other ways to subscribe.

Listen to ShopTalk!

Subscribe to The Lodge!

The Lodge is a members-only, ad-free video learning area here on CSS-Tricks. Just like the free screencasts, but organized into four large complete series. Membership is also the #1 best way to support CSS-Tricks.

We can do the real footer now.

Site Links

Colophon

CSS-Tricks* is created, written by, and maintained by Chris Coyier. It is built on WordPress, hosted by Media Temple, and the assets are served by MaxCDN. The fonts are Source Sans and Source Code Pro. It is made possible by viewers like you who subscribe to The Lodge and through advertising for products and services I like.