Briefly
Sometimes when writing styles we want to refer to a selector more precisely than just by class name or tag. For this, we can use various combinations.
Grouping: .element1, .element2
Example
If several selectors need to have the same rule, you can write it out long:
h1 { font-weight: bold;}h2 { font-weight: bold;}h3 { font-weight: bold;}
h1 { font-weight: bold; } h2 { font-weight: bold; } h3 { font-weight: bold; }
Or you can list all selectors separated by commas and write just one CSS rule:
h1, h2, h3 { font-weight: bold;}
h1, h2, h3 { font-weight: bold; }
How to Write
Selectors are simply written in any order separated by commas:
.selector1,code,#id,[attr="value"] { color: red;}
.selector1, code, #id, [attr="value"] { color: red; }
If you list selectors separated by commas, the rules will apply to each group:
.heading span,.block,.wrapper { color: red;}
.heading span, .block, .wrapper { color: red; }
How to Understand
In the example, the property will apply to three types of selectors:
- For all
<span>
inside the class.heading
(at any depth); - for all elements with the class
.block
; - for all elements with the class
.wrapper
.
Combination: .class1.class2
Example
.selector.selector_modificator { color: red;}
.selector.selector_modificator { color: red; }
How to Write
This technique is applicable only for classes and attributes, because only they can have more than one. Selectors are written together. Styles will be applied only to the element that contains all listed selectors.
How to Understand
This "gluing" combines selectors into one rule.
Descendants: .element1 .element2
Example
article h3 { color: red;}
article h3 { color: red; }
How to Write
Selectors are written sequentially separated by a space.
How to Understand
The sequence of selectors reflects the nesting — each subsequent selector must necessarily be at some level of nesting in the previous selector.
Directly Nested: .element1 > .element2
Example
article > h3 { color: red}
article > h3 { color: red }
How to Write
Selectors are separated by the >
sign.
How to Understand
The sequence of selectors reflects direct nesting — the selector to the right of the operator must be a direct descendant of the selector from the left side:
article > h3 { color: red;}
article > h3 { color: red; }
Styles for h3
will not apply to article > h3
, since the direct descendant of <article>
is div
, not <h3>
:
<article class="article"> <div class="article__header"> <h3 class="article__heading">Title</h3> </div></article>
<article class="article"> <div class="article__header"> <h3 class="article__heading">Title</h3> </div> </article>
In this example, styles will apply to the heading because <h3>
is a direct descendant of <article>
:
<article class="article"> <h3 class="article__heading">Title</h3></article>
<article class="article"> <h3 class="article__heading">Title</h3> </article>
And here, everything is fine — <h3>
is still a direct descendant of <article>
because it is located at the nearest nesting level, even though it follows div
:
<article class="article"> <div class="article__header">…</div> <h3 class="article__heading">Title</h3></article>
<article class="article"> <div class="article__header">…</div> <h3 class="article__heading">Title</h3> </article>
Tips
💡 This combination is handy to select an element based on its exact location in the document structure.
Adjacent: .element1 + .element2
Example
label + input { color: red;}
label + input { color: red; }
How to Write
Selectors are combined with the +
sign.
How to Understand
The element to the right of +
must follow immediately in HTML after the element to the left of +
. In simpler terms, the right element must be a sibling of the left element for the adjacent selector to work.
The code from the example will apply only to such an <input>
that comes immediately after <label>
:
label + input { color: red;}
label + input { color: red; }
This will not apply because there is a <p>
before <input>
:
<label></label><p>…</p><input>
<label></label> <p>…</p> <input>
With this markup, the style will apply only to the first <input>
, but not to the second:
<label>Label</label><input><input>
<label>Label</label> <input> <input>
And the rule will not work here. <label>
and <input>
are at different levels of nesting:
<label>Label</label><div> <input></div>
<label>Label</label> <div> <input> </div>
Subsequent: .element1 ~ .element2
Example
.star:hover ~ .star { color: red;}
.star:hover ~ .star { color: red; }
How to Write
Selectors are combined using the ~
(tilde) symbol.
How to Understand
The rule will apply to all blocks that match the right selector, provided they are siblings of the blocks from the left selector. Both selectors must have the same parent and be at the same level of nesting. In HTML, the right selector must come after the left selector.
In practice
Advice 1
🛠 It’s better to write selectors one per line — this makes them easier to read and edit:
.selector1,code,#id,[attr="value"] { color: red;}
.selector1, code, #id, [attr="value"] { color: red; }
🛠 Combining increases the specificity of the rule, so this can be convenient for overriding properties without !important
:
The code below cannot be edited for some reasons:
.class1 { color: red;}
.class1 { color: red; }
Let’s increase the specificity to override the rule described in the non-editable part and therefore having greater weight:
.class1.class2 { color: green;}.class1 { color: red;}
.class1.class2 { color: green; } .class1 { color: red; }
As a result, the text in the block that has both the class .class1
and the class .class2
will be green.
🛠 It turns out that even an innocent space already has significance when selecting a selector at any level of nesting.
Regardless of the nesting level, the selector article h3
will "find" <h3>
with the text "Very nested header" and any other <h3>
that are located inside <article>
:
<article> <div> <div> <div> <div> <div> <div> <div> <div> <div> <h3>Very nested header</h3> </div> </div> </div> <h3>Header</h3> </div> </div> </div> </div> </div> </div></article>
<article> <div> <div> <div> <div> <div> <div> <div> <div> <div> <h3>Very nested header</h3> </div> </div> </div> <h3>Header</h3> </div> </div> </div> </div> </div> </div> </article>
Advice 2
🛠 Using the adjacent combinator, it is convenient to select a group of identical elements based on the principle of "all except the first" — for example, to set a margin.
Styles will not apply to the first <li>
since there is no other <li>
before it:
<ul> <li>First item</li> <li>Second item</li> <li>Third item</li> <li>Fourth item</li></ul>
<ul> <li>First item</li> <li>Second item</li> <li>Third item</li> <li>Fourth item</li> </ul>
li + li { margin-top: 1em;}
li + li { margin-top: 1em; }
A classic example is the layout of a "star" rating. First, let's describe the structure:
<div class="rating"> <button>★</button> <button>★</button> <button>★</button> <button>★</button> <button>★</button></div>
<div class="rating"> <button>★</button> <button>★</button> <button>★</button> <button>★</button> <button>★</button> </div>
And the styles:
button { border: none; background-color: transparent; font-size: 5em;}button:hover,button:focus,button:hover ~ button,button:focus ~ button { color: #F498AD;}
button { border: none; background-color: transparent; font-size: 5em; } button:hover, button:focus, button:hover ~ button, button:focus ~ button { color: #F498AD; }
But now, when hovering the cursor, all elements after (i.e., on the right) will be highlighted.
To fix this, we will change the order of the elements using the CSS property direction
.
We will add this property to the parent of the stars .rating
:
.rating { direction: rtl;}button { border: none; background-color: transparent; font-size: 5em;}button:hover,button:focus,button:hover ~ button,button:focus ~ button { color: #F498AD;}
.rating { direction: rtl; } button { border: none; background-color: transparent; font-size: 5em; } button:hover, button:focus, button:hover ~ button, button:focus ~ button { color: #F498AD; }