Detailed explanation
Tailwind’s variant prefixes conditionally apply utility classes. A prefix goes before a utility, separated by a colon: hover:bg-blue-700 means “apply this background colour when the element is hovered.” Responsive variants depend on viewport width, while variants such as hover:, focus:, and disabled: depend on an element’s state. Other variants, including dark:, represent conditions rather than interaction states. They let you describe responsive and interactive behaviour directly in HTML while Tailwind generates the corresponding CSS rules.
Responsive variants follow a mobile-first, minimum-width approach. With the default configuration, sm: starts at 40rem (typically 640px), md: at 48rem (768px), lg: at 64rem (1024px), xl: at 80rem (1280px), and 2xl: at 96rem (1536px). These breakpoints can be customised. Unprefixed utilities apply at every viewport width unless overridden by another applicable rule. For example, px-4 md:px-8 gives an element horizontal padding of four spacing units initially and eight units from the medium breakpoint upward. Importantly, sm: does not mean “only on small screens”; it applies at that breakpoint and above.
State variants generate rules targeting the appropriate CSS states. For example, focus: targets focus and disabled: targets the disabled state of supported controls. A disabled: utility only changes styling; it does not disable a button without the disabled attribute or equivalent DOM property. In current Tailwind versions, hover: also checks whether the primary input supports hovering. The dark: variant follows the configured dark-mode strategy: commonly the user’s system preference, or an explicitly configured selector for manual theme switching. Variants can also be stacked, such as md:hover:bg-blue-700, requiring both conditions to match.
In the supplied button example, bg-blue-500 supplies the base background, hover:bg-blue-700 changes it on hover, disabled:opacity-50 reduces opacity when disabled, md:px-8 adds horizontal padding from the medium breakpoint, and dark:bg-blue-900 supplies a dark-mode background. Under the hood, Tailwind generates escaped class selectors, pseudo-class rules, and conditional CSS such as media queries. Interviewers mainly look for correct mobile-first reasoning, the distinction between styling and behaviour, and awareness that multiple variants can apply together.
Key points to remember
- Variants use the syntax prefix:utility and apply styles only when their conditions match.
- Unprefixed utilities are the base; sm:, md:, and lg: apply from their minimum widths upward.
- hover:, focus:, and disabled: target element states, not JavaScript events.
- dark: applies dark-theme styling according to the configured dark-mode strategy.
- Stack variants such as md:hover:bg-blue-700 to require multiple conditions together.
Common mistakes candidates make
- Treating sm: as a mobile-only style instead of a minimum-width breakpoint.
- Expecting disabled: styling to disable a control without setting its disabled attribute.
- Assuming dark: always responds to a dark class without checking the theme configuration.
Likely follow-up questions
How do you apply a style only below the medium breakpoint?
Use a maximum-width variant such as max-md:hidden to hide an element below the medium breakpoint. Alternatively, use hidden md:block when the intended behaviour is hidden by default and block-level from medium upward.
What is the difference between focus: and focus-visible:?
focus: applies whenever the element has focus. focus-visible: applies when the browser determines that a visible focus indicator is appropriate, commonly during keyboard navigation.
Does the order of utilities in the class attribute decide which style wins?
No; moving a class later in the HTML attribute does not generally give it precedence. Conflicts are resolved by the generated CSS cascade, including rule order, specificity, and cascade layers, so use explicit combined variants when necessary.
Interview tip: Define the prefix syntax, explain mobile-first behaviour with one example, and then distinguish state styling from actual element behaviour.
