Hover, Focus & State Variants
Learn how to style interactive states in Tailwind CSS using hover:, focus:, active:, and disabled: prefixes.
Introduction
Interactive elements like buttons, links, and form fields need visual feedback so users know their actions are registering. Tailwind makes this simple with state variant prefixes such as hover:, focus:, active:, and disabled:, which apply a utility class only when the element is in that particular state.
- How to style elements on mouse hover.
- How to style keyboard and click focus states.
- How to style the moment an element is being clicked.
- How to style disabled form controls and buttons.
- How to combine multiple state variants together.
The hover: Variant
Prefixing any utility with hover: applies that style only while the mouse pointer is over the element, exactly like the CSS :hover pseudo-class. It is the most common variant, used constantly for buttons and links.
<button class="bg-blue-500 hover:bg-blue-600 text-white px-4 py-2 rounded-lg transition-colors"> Save Changes</button>Click Run to see what this code prints.
The focus: Variant
focus: applies a style when an element receives keyboard or click focus, matching the :focus pseudo-class. It is essential for form inputs, so users always know which field is currently active, and for accessibility, since keyboard users rely entirely on focus styles to navigate.
<input type="email" placeholder="you@example.com" class="border border-slate-300 rounded-lg px-3 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500"/>Click Run to see what this code prints.
The active: Variant
active: applies a style during the brief moment an element is being pressed, matching the :active pseudo-class. It is useful for giving buttons a satisfying "pressed" feel, such as scaling down slightly or darkening further than the hover state.
<button class="bg-emerald-500 hover:bg-emerald-600 active:bg-emerald-700 active:scale-95 text-white px-5 py-2 rounded-lg transition"> Submit</button>Click Run to see what this code prints.
The disabled: Variant
disabled: targets elements that have the HTML disabled attribute, matching the :disabled pseudo-class. It is typically paired with disabled:opacity-50 and disabled:cursor-not-allowed to visually and functionally communicate that an element cannot be interacted with.
<button disabled class="bg-slate-400 text-white px-4 py-2 rounded-lg disabled:opacity-50 disabled:cursor-not-allowed"> Processing...</button>Click Run to see what this code prints.
Combining State Variants
State variants can be stacked on the same element to build up a complete interaction story: a base style, a hover style, a focus style, an active style, and a disabled style, all on one button.
<button class="bg-indigo-500 hover:bg-indigo-600 focus:outline-none focus:ring-2 focus:ring-indigo-400 active:bg-indigo-700 disabled:opacity-50 disabled:cursor-not-allowed text-white px-5 py-2 rounded-lg transition"> Continue</button>Click Run to see what this code prints.
Common Mistakes
- Removing the default focus outline with focus:outline-none without replacing it with a visible focus:ring-* — this breaks keyboard accessibility.
- Only designing hover states and forgetting that touch devices have no true hover, so critical actions should not depend on hover alone.
- Forgetting to add transition or transition-colors, which makes state changes feel abrupt instead of smooth.
- Styling disabled: on elements that do not actually have the disabled attribute, so the style never applies.
- Using the same color for hover and active states, making the pressed feedback invisible.
Best Practices
- Always pair focus:outline-none with a visible focus:ring-* or focus:border-* replacement.
- Add a transition or transition-colors utility so hover and focus changes feel smooth rather than instant.
- Design disabled states for every interactive form control, not just buttons.
- Keep hover, focus, and active shades on the same color scale so they feel like a natural progression.
- Test your interface with a keyboard only (Tab and Enter) to confirm focus states are clear.
Frequently Asked Questions
focus: applies whenever an element has focus, including after a mouse click. focus-visible: applies only when the browser determines focus should be visibly indicated, typically for keyboard navigation, avoiding a focus ring after a simple mouse click.
Yes. You can prefix virtually any utility — spacing, transforms, shadows, borders — with hover:, focus:, active:, or disabled: to change any property in that state.
Yes, Tailwind lets you stack variants, for example md:hover:bg-blue-600, which only applies the hover style at the md breakpoint and above.
Key Takeaways
- hover: applies styles while the mouse is over an element.
- focus: applies styles when an element receives keyboard or click focus.
- active: applies styles during the moment an element is pressed.
- disabled: applies styles to elements with the disabled attribute.
- Multiple state variants can be combined on the same element for a complete interaction design.
Summary
State variants turn static designs into responsive, tactile interfaces, and they are essential for both usability and accessibility. Next, you will learn how to support dark mode using Tailwind's dark: variant, so your interface can adapt to a user's preferred color scheme.