Knowing how to use CSS selectors effectively is useful for Frontend developers. I created a cheatsheet of commonly-used selectors.
Why another CSS cheatsheet?
Although other CSS selector cheatsheets exist (see resources), I find them either lacking grouping/organization, missing examples, or have too much information.
That's why I group this cheatsheet into 8 different types. At the start of each group you'll find HTML snippet. Use that HTML snippet with that group (and play around with it!). The list is not comprehensive and I intend it to be. The list below should cover most development needs.
Table of Contents
Basic selectors
They select element/id/class. They are also used most often and easiest to remember.
<div id="app">
<div class="container">
<p class="hello">Hello</p>
<p class="hola">Hola</p>
</div>
<div class="other">
I am left behind...
</div>
</div>
- Element selector:
Element
. It selects any given element.
p { color: blue; }
div { color: magenta; }
- Class selector:
.class
. It selects all element containing given class name.
.hello {
color: red;
}
- ID selector:
#id
. It selects the element containing given HTML ID.
#app {
color: red;
}
- Universal selector:
*
. It selects all elements.
* {
color: yellow;
}
Descendant selectors
These are selectors for choosing descendants of any element.
<div class="container">
<div class="paragraph-container">
<p id="hola-id" class="hola-class">Hola world</p>
<p class="hello-class">Hello world</p>
<p class="hello-class again-class">Hello again world</p>
</div>
</div>
- Any descendant selector:
A B
. Selects any elements B that are descendants of A. The descendant can be nested really deep.
.container .hello-class {
color: red;
}
We can combine this with *
to get:
.paragraph-container * {
color: blue;
}
This selects everything inside .paragraph-container
- Child selector:
A > B
. Unlike any descendant selector, this one only selects direct descendant/ child.
.paragraph-container > .hello-class {
color: blue;
}
While below won't work because .hello-class
in this scenario is not direct descendant:
.container > .hello-class {
color: blue;
}
Multiple Selector
<div class="container">
<div class="paragraph-container">
<p id="hola-id" class="hola-class">Hola world</p>
<p class="hello-class">Hello world</p>
<p class="hello-class again-class">Hello again world</p>
</div>
<p class="outside-class">I'm outside</p>
</div>
Multiple selectors allow us to select multiple unrelated elements together.
- Multiple selectors:
A, B, C, ...
. To select multiple elements/classes/ids, connect them with,
:
.outside-class, .again-class, .hola-class {
color: purple;
}
Combination selector
Combination selector allows you to choose very specific element using multiple references. A popular use-case is button highlight effect when hovered/ clicked by giving them an .active
class.
<div class="container">
<div class="paragraph-container">
<p id="hola-id" class="hola-class">Hola world</p>
<p class="hello-class">Hello world</p>
<p class="hello-class active">Hello again world</p>
</div>
<p class="outside-class">I'm outside</p>
</div>
- Combination selector:
AB
. This selects element containing BOTH A and B. The syntax looks like descendant selector, except this does not have space.
p.active {
color: yellow;
}
We can combine anything, not just element and class:
p#hola-id {
color: blue;
}
.hello-class.active {
color: red;
}
Sibling selectors
These selectors target their siblings.
<div class="container">
<div class="paragraph-container">
<p id="hola-id" class="hola-class">Hola world</p>
<p class="hello-class">Hello world</p>
<p class="hello-class again-class">Hello again world</p>
</div>
<p class="outside-class">I'm outside</p>
</div>
- Adjacent sibling selector (strict):
A + B
. Targets one sibling element placed immediately after that element.sibling1 + sibling2
#hola-id + .hello-class {
color: blue;
}
Note that CSS below won't work because .again-class
, although it is #hola-id
's sibling, is 2 elements away.
#hola-id + .again-class {
color: blue;
}
- Any adjacent sibling selector (relaxed):
A ~ B
. Like adjacent sibling selector, but selects ANY sibling selector(s) after. The syntax~
personally reminds me of shrugging 🤷♂️🤷♀️ - hence~
is more relaxed than+
.
#hola-id ~ .hello-class {
color: purple;
}
Note it doesn't work backwards (B ~ A
is not the same as A ~ B
):
.again-class ~ #hola-id {
color: red
}
Pseudo Selectors
<div class="container">
<div class="paragraph-container">
<p id="hola-id" class="hola-class">Hola world</p>
<p class="hello-class">Hello world</p>
<p class="hello-class again-class">Hello again world</p>
</div>
<p class="outside-class">I'm outside</p>
<ul id="list-id" class="list-class">
<li class="list-item-class">First</li>
<li class="list-item-class">Second</li>
<li class="list-item-class">Third</li>
<li class="list-item-class">Fourth</li>
<li class="list-item-class">Fifth</li>
</ul>
<div class="single-paragraph-container">
<p>I'm the only child of this span</p>
</div>
</div>
- First child selector:
A:first-child
. It selects each target that is the first child of its parent. The definition is a bit confusing at first. The way I think of it, the target (A
) must itself be a first child of a parent.
note the phrase: the first child of its parent.
li:first-child {
color: blue;
}
The above one works because li
has a parent: ul
. li
is also ul
's first child.
What would happen if you target ul
?
ul:first-child {
color: red;
}
Nothing happens. This is because although ul
has a parent (div
with class container
), ul
is not a first child (it is a 3rd child).
The code below will work because .paragraph-container
is .container
's first child.
.paragraph-container:first-child {
color: red;
}
- Last child selector:
A:last-child
. Works like first-child, except instead of first, our target must be a last child.
li:last-child {
color: purple;
}
- Only child selector:
A:only-child
. Selects allA
that is the only child of its parent. Similar to first and last child selectors. Except the target must not have any siblings.
p:only-child {
color: red;
}
Note although we have several p
elements, only the last one applies because the other p
elements are not its parent's only child. They have siblings.
- Nth child selector:
A:nth-child(n)
. It selects each target that is the nth child of its parent.
li:nth-child(2) {
color: red;
}
Let's try with p
now:
p:nth-child(2) {
color: red;
}
Can you see why two p
elements changed colors?
- Last nth child selector:
A:nth-last-child(n)
. It is similar to the nth child selector, except it counts from last.
li:nth-last-child(2) {
color: red;
}
- Not selector:
A:not(B)
. Selects allA
element that is notB
.
p:not(.outside-class) {
color: blue;
}
- First type selector:
A:first-of-type
. It selects the first element of its type among its sibling elements.
This one sounds similar to :first-child
when I first hear about it. To feel how it is different, let's play around:
li:first-of-type {
color: blue;
}
Ok, that's not a good example because it shows same result as li:first-child
😅. Let's do another example:
p:first-of-type {
color: red;
}
This one is better. Compare that with p:first-child
. You'll notice that the middle p
turns red using first-of-type
and it doesn't using first-child
. This is because the middle p
is the first p
element type among its siblings 💡.
- Last type selector:
A:last-of-type
. Just like the above, but opposite.
li:last-of-type {
color: blue;
}
- Nth type selector:
A:nth-of-type(n)
. Just like the two above, but this selects nth element of that time.
li:nth-of-type(2) {
color: blue;
}
Let's try different element:
p:nth-of-type(2) {
color: blue;
}
If we changed it to p:nth-of-type(1)
, it behaves just like first-of-type
. Also if we changed it to p:nth-of-type(4)
, nothing changes color - this is because there is no 4th p
element among siblings.
- Only type selector:
A:only-of-type
. Selects the element with ONLY that type (no siblings)
p:only-of-type {
color: purple;
}
Notice two p
elements change color. This is because there are two p
elements that have no sibling with the same type.
Pseudo-selectors (links and inputs)
Below are a list of more pseudo selectors. These are commonly associated with links (a
) (although they may work with non-link elements).
<div id="app">
<a class="cheesyLink" href="#">I like cheese</a>
<a class="sweetLink" href="#">I like donut</a>
<div class="burger">I like cheezburger</div>
<div class="container">
<form onsubmit="event.preventDefault()">
<input class="myinput"type="text" />
<input class="mysubmit" type="submit" />
</form>
</div>
</div>
- Hover selector:
A:hover
. Selects hovered element. Commonly used to highlight links.
a:hover {
color: red;
}
It doesn't have to be a
tag though. This selector works with anything.
.burger:hover {
color: red;
}
- Focus selector:
A:focus
. Selects a focused element. Usually works withinput
.
input:focus {
background: red;
}
- Active selector:
A:active
. Selects an element that is in active state.
Note as you click it, the background changes.
.cheesyLink:active {
background: red;
}
- Link selector:
A:link
. It selects all links that have not been clicked yet
a:link {
background: blue;
}
Attribute selectors
Attribute selector is useful for selecting HTML attributes.
<div for="chocolate">Chocolate</div>
<div for="peanut">Peanut</div>
<div for="butter">Butter</div>
<div>Jelly</div>
- Basic attribute selector:
A[B]
. Selects all elementsA
with attributeB
.
div[for] {
color: red;
}
- Specific attribute selector:
A[B="C"]
. Selects all elementA
with attributeB
with valueC
div[for="chocolate"]{
color: blue;
}
- Specific attribute selector (starting):
A[B^="C"]
. Selects all elementA
with attributeB
withC
starting value. Note that^
is Regex for starting string.
div[for^="cho"] {
color: magenta;
}
- Specific attribute elector (ending):
A[B$="C"]
. Selects all elementA
with attributeB
withC
ending value. Note that$
is Regex for ending string.
div[for$="er"] {
color: yellow;
}
- Specific attribute selector (wildcard):
A[B*="C"]
. Selects all elementA
with attributeB
containingC
value. Note that*
is usually a wildcard in regex and globs.
div[for*="ut"]{
color: cyan;
}
So there you have it folks! If you need more references, feel free to check out the resources below. If you think a different way I can make this cheatsheet more practical, feel free to comment below.