Encodera

Thanks for reading!

Donate to the site — we work hard for you.

Contents

Pseudo-classes

A pseudo-class picks an element not by tag or class but by its state or position: "the element under the cursor", "the first in a list", "a checked checkbox". It is written after a selector with a colon and no space. Such styles change by themselves, without a single line of JavaScript.

Hover and press

:hover applies while the mouse cursor is over the element, and :active applies at the moment of pressing:

<style>
  .button {
    padding: 8px 16px;
    border: 0;
    border-radius: 8px;
    background: rebeccapurple;
    color: white;
  }
  .button:hover { background: indigo; }
  .button:active { background: black; }
</style>
 
<button class="button">Hover and press</button>

Phones have no cursor, so an important action must not be hidden behind :hover alone.

Focus

The element in focus is the one the user is working with right now: the field with a blinking cursor, or a button reached with the Tab key. :focus applies on any focus, while :focus-visible applies only when focus should be shown, for example when using the keyboard:

<style>
  input:focus { outline: 3px solid gold; }
  button:focus-visible { outline: 3px solid deeppink; }
</style>
 
<input placeholder="Click here">
<button>Press Tab to reach me</button>

Links have their own states: :link is not yet visited, :visited has been opened. They are written in the order link, visited, hover, active — otherwise a lower rule overrides an upper one:

<style>
  a:link { color: royalblue; }
  a:visited { color: purple; }
  a:hover { color: crimson; }
</style>
 
<p><a href="#nowhere">Hover over the link</a></p>

Position among siblings

Structural pseudo-classes pick an element by its place among its siblings — elements with the same parent:

<style>
  li:first-child { font-weight: 700; }
  li:last-child { color: crimson; }
  li:nth-child(even) { background: whitesmoke; }
</style>
 
<ul>
  <li>First</li>
  <li>Second</li>
  <li>Third</li>
  <li>Fourth</li>
</ul>
Pseudo-classWhat it picks
:first-childthe first element
:last-childthe last element
:nth-child(3)the third element
:nth-child(odd)odd ones: 1, 3, 5…
:nth-child(even)even ones: 2, 4, 6…
:nth-child(3n)every third one

Exclusion

:not() picks every element except those named in the parentheses. It is handy for adding a line between items but not after the last one:

<style>
  li:not(:last-child) { border-bottom: 1px solid silver; }
</style>
 
<ul>
  <li>Apples</li>
  <li>Pears</li>
  <li>Plums</li>
</ul>

Form field states

:checked picks a checked checkbox or radio button, and :disabled picks a disabled field:

<style>
  input:checked + label { color: seagreen; font-weight: 700; }
  input:disabled { background: gainsboro; }
</style>
 
<input type="checkbox" id="news" checked> <label for="news">Subscribe to news</label>
<p><input disabled placeholder="Unavailable"></p>

The + sign picks the element that comes right after the previous one: here, the label after the checkbox. Uncheck the box and the label becomes regular.

Common mistake

:first-child checks whether the element is first among all its siblings, not among elements of its tag. If a heading comes before a paragraph, p:first-child does not match. For that there is :first-of-type — the first of its tag:

<style>
  p:first-child { color: crimson; }
  p:first-of-type { font-weight: 700; }
</style>
 
<div>
  <h3>A heading</h3>
  <p>Not red: h3 comes first. But bold — the first paragraph.</p>
  <p>The second paragraph.</p>
</div>

Thanks for reading!

Donate to the site — we work hard for you.