CSS Combinators: Targeting by Relationship

CSS combinators target elements by their DOM relationship, not just class or ID. They let you select an element inside another (div p) or right next to one (h2 + p). This is key for styling nested menus or spacing adjacent items.
Why it exists
HTML is a tree, but simple selectors like classes or IDs treat it like a flat list. Combinators were created to apply styles based on an element's position within that tree structure—its parent, its siblings, or its ancestors. They provide essential contextual targeting.
The mental model
Think of combinators as giving directions through the DOM tree. Instead of just asking for "all elements with the class 'card'", you can ask for "the 'h2' that is an immediate child of a 'div' with the class 'card'" (div.card > h2). They express relationships: inside, directly inside, immediately after, or just somewhere after.
How it works
A combinator connects two selectors, defining the relationship that must be true for an element to be selected. The four main combinators are: Descendant (space): A B selects any B element that is a descendant of A at any depth. Child (>): A > B selects any B element that is a direct child of A. Next-Sibling (+): A + B selects the B element that immediately follows A and shares the same parent. Subsequent-Sibling (~): A ~ B selects all B elements that follow A and share the same parent, not just the immediate one.
When to use it
Use combinators for context-aware styling. For example, applying a margin-top to all paragraphs except the first one after a heading (h2 + p). Or styling list items differently based on their nesting level (ul > li vs ul li). They are essential for creating robust components that adapt to their surroundings.
When not to use it
Avoid long, specific combinator chains like div > section > ul > li > a. This creates brittle CSS that is tightly coupled to the HTML structure, making redesigns difficult. It also drastically increases specificity, which can lead to !important wars. Prefer simpler selectors and helper classes where possible.
One canonical example
A common use case is adding space between sibling elements, but not before the first one. Instead of a special "first" class, you can use the next-sibling combinator. The selector h2 + p targets only the paragraph that immediately follows an h2, allowing you to set its margin-top. For example: h2 + p { margin-top: 1.5rem; } applies a top margin to a paragraph only if it comes right after a heading.
Interview question
Which CSS combinator correctly targets all 'p' elements that appear after an 'h2' within the same parent, regardless of whether they are immediately adjacent?
- a.h2 > p
- b.h2 ~ pCorrect
- c.h2 p
- d.h2 + p
Why? this is the answer
The subsequent-sibling combinator (~) selects all sibling elements that follow the first specified element. The next-sibling combinator (+) only selects the single element immediately following.
Just read this? Test yourself on what you have been reading.
Read the original → developer.mozilla.org
You just looked this up. Could you explain it out loud?
That is the part interviews actually test. Tezvyn takes questions like this one and gives you what the interviewer is really checking, the answer that lands, and the mistake that ends the conversation, in the four minutes before your next meeting.
The iPhone app is on the way
We are building it. Until it lands, nothing here is held back from you: every interview card, your saved cards, streaks and the job board all work in Safari, plus hundreds of free practice quizzes of thirty questions each. Sign in and it all carries over to the app the day it arrives.
Want it as an icon? Tap Share at the bottom of Safari, then Add to Home Screen. It opens full screen and the cards you have read stay available offline.
We are hiring for this. Open roles that interview on css — each one lists the topics its interview covers.
See open roles