When writing efficient code, the way you nest your CSS selectors makes a big difference. Properly nesting your CSS selectors helps ensure that when someone visits your webpage they get the experience they were looking for without any fuss or hassle that could come with tangled up or unorganized code.
As is generally true in computer science, there are many ways to accomplish the same thing in CSS, and some ways are more efficient than others.
A more efficient route is nesting your CSS rules so you can target elements within elements - and that's where "combinators" come into play. With the correct understanding of what a combinator does and how it operates, you'll be able to create cleaner code that will simplify things for yourself and other readers. So let’s dive right in.
What are CSS combinators?
In CSS, a combinator is a symbol that relates two CSS selectors to each other in order to style elements in a certain way. Combinators allow us to apply style rules to elements based on their parent elements or sibling elements.
Types of CSS Combinators
CSS3 includes four types of combinators: the descendant combinator, the child combinator, the adjacent sibling combinator, and the general sibling combinator. Let’s review each one.
The descendant combinator is written as two selectors separated by a single space, and targets all instances of the second selector that descend from (i.e., are nested inside) the first selector.
For example, the descendant combinator #my-div p applies the associated rules to all <p> elements inside the div #my-div — see below.
The descendant combinator works well when you want to style all instances of an element within a specified section of your page. Referring back to our situation in the intro, you might want to style all <p> elements inside your <main> section one way and all other <p>s on the page a different way. In this case, you can use the descendant combinator main p.
Importantly, the descendant combinator selects every instance of an element nested inside another, including child elements, child elements of those child elements, and so on.
However, you might not always want to apply styling this deeply — this is where the child combinator comes in.
The child combinator is written as a greater-than symbol (>) placed between two CSS selectors. It targets all instances of an element that are direct descendants, or child elements, of another element. The style cascade stops after the first nesting level.
In the example below, I’ve used a descendant combinator to color all paragraph text inside <main> orange, and a child combinator to style only the child paragraphs of <main> with a larger font size. Notice how the main > p combinator does not affect the <p> inside the <div> element.
Adjacent Sibling Combinator
The adjacent sibling combinator is written as a plus sign (+) between two CSS selectors. It targets an element matching the second selector only if it immediately follows an element that matches the first selector. Additionally, both elements must be children of the same parent element (and are thus called “sibling elements”).
Below, see how the first paragraph receives styling because it directly follows <h1>. However, the second paragraph does not.
General Sibling Combinator
The general sibling selector is written as the tilde symbol (~) and targets all elements that follow a specific sibling element. Unlike the adjacent sibling selector, the targeted elements do not need to immediately follow the first element.
In this example, all <p> elements are styled because they proceed <h1> in the document, despite not all being directly adjacent to each other.
Writing Clean CSS
Nesting your CSS selectors is one small trick that makes things much easier down the road. You’ll write your CSS more quickly, apply style changes more efficiently, and not have to worry about remembering to place a slew of id or class attributes in the right HTML tags.
Combinators will take some practice to get right. But, before mastering CSS, you should learn them — they’re a handy trick for your front-end tool belt.