Lesson 8 +10 XP

Hover, Focus & Other States

Hover, Focus & Other States

Every utility can be applied conditionally by prefixing it with a variant that describes the condition - like hover:, focus:, or sm:.

The basic idea

To style a button on hover:

<button class="bg-sky-500 hover:bg-sky-700 ...">Save changes</button>

The generated CSS looks like:

.hover\:bg-sky-700:hover {
  background-color: var(--color-sky-700);
}

Notice hover:bg-sky-700 does nothing unless the element is hovered.

Stacking variants

You can stack variants to target multiple conditions:

<button class="bg-sky-500 disabled:hover:bg-sky-500 ...">Save changes</button>

Or combine dark mode + breakpoint + state:

<button class="dark:md:hover:bg-fuchsia-600 ...">Save changes</button>

Common pseudo-class variants

  • hover, focus, active, visited, focus-within, focus-visible
  • first, last, odd, even, nth-*
  • required, invalid, disabled, read-only, checked, indeterminate
  • has-* - style based on descendants

Pseudo-elements

  • before and after (auto content: '')
  • placeholder, file, marker, selection, first-line, first-letter, backdrop

Media and feature queries

  • sm, md, lg, xl, 2xl - responsive breakpoints
  • dark - prefers-color-scheme
  • motion-reduce, motion-safe, contrast-more, print, portrait, landscape
  • supports-[...]

Styling based on parent state

Mark a parent with group, then use group-hover on children:

<a href="#" class="group rounded-lg p-8">
  <h3 class="text-gray-900 group-hover:text-white">New project</h3>
</a>

Name nested groups with group/item and group-hover/item.

Styling based on sibling state

Mark a sibling with peer, then use peer-invalid etc.:

<input type="email" class="peer ..." />
<p class="invisible peer-invalid:visible">Please provide a valid email.</p>

Arbitrary variants

Write any selector with arbitrary variants:

<div class="[&>[data-active]+span]:text-blue-600 ...">...</div>

TL;DR

  • Prefix any utility with a variant: hover:, focus:, sm:, dark:.
  • Variants stack: dark:md:hover:.
  • group and peer target parent/sibling states.
  • Arbitrary variants let you write any selector.