CSS Selectors Cheat Sheet

January 31, 2020

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 all A 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 all A element that is not B.
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 with input.
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 elements A with attribute B.
div[for] {
  color: red;
}
  • Specific attribute selector: A[B="C"]. Selects all element A with attribute B with value C
div[for="chocolate"]{
  color: blue;
}
  • Specific attribute selector (starting): A[B^="C"]. Selects all element A with attribute B with C starting value. Note that ^ is Regex for starting string.
div[for^="cho"] {
  color: magenta;
}
  • Specific attribute elector (ending): A[B$="C"]. Selects all element A with attribute B with C ending value. Note that $ is Regex for ending string.
div[for$="er"] {
  color: yellow;
}
  • Specific attribute selector (wildcard): A[B*="C"]. Selects all element A with attribute B containing C 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.

Resources: