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 allAthat 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 allAelement 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 elementsAwith attributeB.
div[for] {
  color: red;
}
- Specific attribute selector: A[B="C"]. Selects all elementAwith attributeBwith valueC
div[for="chocolate"]{
  color: blue;
}
- Specific attribute selector (starting): A[B^="C"]. Selects all elementAwith attributeBwithCstarting value. Note that^is Regex for starting string.
div[for^="cho"] {
  color: magenta;
}
- Specific attribute elector (ending): A[B$="C"]. Selects all elementAwith attributeBwithCending value. Note that$is Regex for ending string.
div[for$="er"] {
  color: yellow;
}
- Specific attribute selector (wildcard): A[B*="C"]. Selects all elementAwith attributeBcontainingCvalue. 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.
 

 
    
Top comments (1)
This has been very helpful