One of the more confusing and often overlooked parts of CSS are Selectors. By understanding descendant, child, and sibling selectors we can reduce the level of markup on our site and let CSS do some of the heavy lifting. Lets take a closer look at these and get a better understanding of how they work and can help make our code cleaner.
Descendant v. Child Selectors
Descendants are usually the first selector type learned in CSS. A simple example would be
ul li. This targets all
li elements that are descendants of an unordered list - meaning the declaration targets every
li element within the top level
ul. If you have an ordered list nested in a unordered list it will target items from each list.
While descendant selectors target every successive element, the Child Selector targets only the child of the targeted parent element. This prevents any
ul > li style declarations from cascading down to every element below. Lets see an example of this in action:
As we can see in the example above the descendant selector (left) applied the italics & color style to both unordered list items as well as the ordered list. The child selector (right) only applied the styling to the unordered list, but not the ordered list.
Adjacent Sibling Selectors
Adjacent selectors target elements immediately preceded by a sibling element. A great use case would be to adjust the spacing between a headline and sub-headline for a blog post. In our CSS we would do this by declaring
h1 + h2, which targets any
h2 element that immediately follows an
h1. This allows us much more flexibility in targeting sub-headlines on our page without having to add un-necessary markup such as extra classes or spans to the html.
General Sibling Selectors
General Sibling selectors are very close to adjacent selectors, but the target elements do not have to immediately follow its sibling. As the name implies the siblings must belong to the same parent element. Let's take a look at some example code and how General Sibling Selectors function:
<p>So long and thanks for all the fish...
<p>So sad that it should come to this</p>
<p>We tried to warn you all but oh dear?</p>
In the above example
p ~ p will target 'So sad...' and 'We tried' because they are siblings to 'So long...' even though there is another
div between them. However, if we declare
div ~ p then the middle div and 'We tried' will be selected, since they both share the same parent. These selectors give us much more flexibility to use CSS to our advantage without having to clutter up the HTML elements.
The best way to understand how selectors work is to practice working with them and see for yourself. I suggest just creating a basic HTML + CSS sandbox and start targeting elements using different selectors. Be sure to checkout W3.org's full list of Selectors to see more child & sibling examples, as well as selectors such as
pseudo-classes, and more.