webroad.online
  1. 1Web
  2. 2HTML
  3. 3CSS
  4. 4JavaScript
  5. 5TypeScript
  6. 6Git
  7. 7Tooling
  8. 8React
  9. 9State management
  10. 10Next.js
  11. 11Forms
  12. 12Data and backend
  13. 13SEO
  14. 14Tailwind CSS
  15. 15Animations
  16. 16Testing
  17. 17Architecture
Tailwind CSS · Lesson 2 of 6

Responsive and states

Mobile-first, hover/focus-visible, group/peer, aria-* and container queries.

Updated

What variants are

In Tailwind, a variant is a prefix that applies a class only under certain conditions: on a wider screen (md:), on hover (hover:), in dark mode (dark:), when the parent is in a certain state (group-hover:). The equivalent of media queries and pseudo-classes in CSS, written directly on the element.

<button class="bg-surface hover:bg-hover md:px-6 dark:border-line">
Kind of variant Examples The CSS equivalent
breakpoint sm: md: lg: max-md: @media (min-width: ...)
state hover: focus-visible: active: disabled: pseudo-classes
relational group-hover: peer-checked: has-[img]: parent / sibling selectors
attributes aria-expanded: data-[state=open]: attribute selectors
environment dark: motion-reduce: print: preference media queries
container @md: @container

Variants can be combined: md:hover:bg-hover.

Mobile-first

A class without a prefix = every screen. The prefix = from that breakpoint up.

<div class="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-4">
Prefix Minimum width
sm: 40rem (640px)
md: 48rem (768px)
lg: 64rem (1024px)
xl: 80rem (1280px)

Think of it this way: you write the mobile version, then add what changes on big screens. max-md: = only below md.

States

<a class="text-muted hover:text-fg focus-visible:outline-2 active:scale-95">
<input class="border invalid:border-red-500 disabled:opacity-50 placeholder:text-gray-400" />
<li class="odd:bg-gray-50 first:pt-0 last:border-0">

focus-visible: instead of focus: — the ring shows up only for the keyboard, not on click.

group and peer

You style a child by the state of its parent (group) or of a sibling (peer):

<a class="group">
  <h3 class="group-hover:text-blue-600">Title</h3>
</a>

<input class="peer" type="checkbox" />
<span class="peer-checked:line-through">Task</span>

ARIA and data-* attributes

<button aria-expanded="true" class="aria-expanded:rotate-180">
<div data-state="open" class="data-[state=open]:block hidden">

Perfect with headless components (Radix, React Aria) that set these attributes.

Container queries

Responsive by the parent's width, not the screen's — ideal for cards reused in different places:

<div class="@container">
  <div class="flex flex-col @md:flex-row">...</div>
</div>

Summary

  • A variant = a conditional prefix; no prefix = every screen.
  • Mobile-first: write for mobile, add md:, lg: for big screens.
  • focus-visible: for focus; group-* / peer-* for relationships; @container for components.

Official sources

Exercises

Was this page helpful?

One tap — no account needed.