Tailwind CSS Hover, Focus and Dark Mode
Tailwind uses prefixes, just like breakpoints, to style elements in special states such as hover and focus.
State Prefixes
| Prefix | Applies when |
|---|---|
hover: | The mouse is over the element |
focus: | The element has keyboard or click focus (inputs, buttons) |
active: | The element is being pressed |
disabled: | A form element is disabled |
first:, last: | The element is the first or last child |
odd:, even: | Odd or even children (table rows, lists) |
Hover and Transitions
transition makes changes smooth. duration-300 sets the time in milliseconds.
Example
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
</head>
<body class="p-8 space-x-3">
<button class="bg-cyan-500 hover:bg-cyan-700 active:scale-95 text-white px-5 py-2 rounded-lg transition duration-300">
Hover me
</button>
<button class="border border-gray-300 hover:border-cyan-500 hover:text-cyan-600 px-5 py-2 rounded-lg transition">
Outline
</button>
<button class="bg-gray-300 text-gray-500 px-5 py-2 rounded-lg disabled:cursor-not-allowed" disabled>
Disabled
</button>
</body>
</html>Try it Yourself »Focus Styles for Forms
Use focus: with ring classes for a clear outline when a user clicks or tabs into an input.
Example
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
</head>
<body class="p-8 max-w-sm space-y-3">
<input class="w-full border border-gray-300 rounded-md px-3 py-2 outline-none focus:border-cyan-500 focus:ring-2 focus:ring-cyan-200" placeholder="Your name">
<input class="w-full border border-gray-300 rounded-md px-3 py-2 outline-none focus:border-cyan-500 focus:ring-2 focus:ring-cyan-200" placeholder="Phone number">
<ul class="border border-gray-200 rounded-md">
<li class="px-3 py-2 odd:bg-gray-50">Ali</li>
<li class="px-3 py-2 odd:bg-gray-50">Ayesha</li>
<li class="px-3 py-2 odd:bg-gray-50">Sana</li>
</ul>
</body>
</html>Try it Yourself »Never remove the focus outline without adding a clear focus: style instead. Keyboard users need to see which field they are in.
Styling Children with group
Add group to a parent. Then group-hover: on a child changes the child when the mouse is over the parent.
Example
<a href="#" class="group block border border-gray-200 p-4 rounded-lg hover:bg-cyan-600">
<p class="font-bold group-hover:text-white">Web Development</p>
<p class="text-gray-500 group-hover:text-cyan-100">6 months, weekend classes</p>
</a>Dark Mode
The dark: prefix applies a class when the user's device is set to dark mode.
Example
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
</head>
<body class="bg-white dark:bg-slate-900 p-8">
<div class="max-w-sm bg-gray-100 dark:bg-slate-800 p-6 rounded-xl">
<h2 class="text-xl font-bold text-gray-900 dark:text-white">Night Reading</h2>
<p class="text-gray-600 dark:text-slate-300 mt-2">Switch your phone or computer to dark mode, then run this example again.</p>
</div>
</body>
</html>Try it Yourself »A Dark Mode Button
To control dark mode with a button instead of the device setting, tell Tailwind to use a dark class on the <html> element:
Example
@custom-variant dark (&:where(.dark, .dark *));Then a small script can add or remove the class: document.documentElement.classList.toggle("dark").
Combining Prefixes
Prefixes can be stacked. md:hover:bg-cyan-700 changes the background on hover, but only on screens 768px and wider. dark:hover:bg-slate-700 is a hover colour for dark mode.
Exercise
Exercise
Which class changes a button's background to cyan-700 when the mouse is over it?
