
Quick answer: Tailwind handles dark mode with a dark: variant that applies a utility only when dark mode is active. You can switch on the operating system preference, or toggle a class on the root element for a manual switch. Custom colors, fonts and spacing live in one theme configuration, so the whole site stays consistent. This guide covers dark mode, a brand palette, and the usual mistakes around contrast and flicker.
Dark mode with the dark variant
Pair a light utility with its dark counterpart. The light value applies by default and the dark: value takes over when the page is in dark mode. Keeping both in the markup means you never write a separate dark stylesheet.
<section class="bg-white text-slate-900 dark:bg-slate-900 dark:text-slate-100">
<h2 class="text-xl font-semibold">Account settings</h2>
</section>Choosing how dark mode switches
By default, dark: follows the system preference through the prefers-color-scheme media query. If you want a user toggle, configure Tailwind to use a class strategy: the variant then applies only inside an element with the dark class. Pick one strategy per project. Mixing system and class switching makes the page disagree with the user’s choice.
/* src/style.css (class strategy for a manual toggle) */
@import "tailwindcss";
@custom-variant dark (&:where(.dark, .dark *));A brand palette in the theme
Extend the theme rather than hard-coding hex values in markup. Declare your brand colors inside an @theme block in your main stylesheet. Each --color-* variable becomes a utility, so --color-brand-600 gives you bg-brand-600 and text-brand-600. When the brand changes, you edit one file.
/* src/style.css */
@import "tailwindcss";
@theme {
--color-brand-50: #ecfeff;
--color-brand-600: #0891b2;
--color-brand-700: #0e7490;
}Avoiding the flash of the wrong theme
With a manual toggle, the saved preference is applied after the page loads, so users see a flash of light theme first. Read the saved choice in a small inline script in the document head, before the body renders, and add the dark class to the root element there. Keep that script tiny and dependency-free.
Contrast and the mistakes to avoid
The most common dark mode bug is low contrast: muted grey text that is readable on white becomes hard to read on a dark background. Test body text against WCAG 2.2 contrast minimums of 4.5:1 in both themes. Also avoid pure black on pure white and pure white on pure black for long reading, since it causes glare. Finally, don’t forget images and icons, which may need their own dark variant or a subtle background.
Runtime theming with CSS variables
Some themes need to change while the page is open, such as a per-customer brand color loaded from an API. Define the color as a CSS variable and point the Tailwind palette at it, so the utilities read the variable at runtime. Changing the variable on the root element then restyles every element that uses the utility, with no rebuild and no class changes in the markup.
/* src/style.css */
@import "tailwindcss";
@theme inline {
--color-brand: rgb(var(--brand));
}Set --brand as a space-separated RGB triplet such as 8 145 178 on the root element. The <alpha-value> placeholder lets opacity modifiers like bg-brand/50 keep working. Keep runtime values limited to colors and a few tokens; structural layout is better left in the build-time config.
Putting the theme together
A working theme usually combines three layers. The first is the palette in the config, which defines brand and neutral colors once. The second is the variant rules in markup, which pair each surface and text color with its dark value. The third is the root class or CSS variable that switches between them. Keep the palette and variant rules in version control with the rest of the code, and review them whenever a new component is added, because a single missed dark: pair is the most frequent source of an unreadable panel.
Test the finished theme in both modes at the same time: a screenshot pair of each page makes differences in contrast and border visibility obvious. Pay attention to shadows, which tend to vanish on dark backgrounds, and replace them with a subtle border or a lighter surface color where elevation matters for understanding the layout.
Frequently asked questions
How do I turn on dark mode in Tailwind?
Add the dark: prefix to any utility you want to change. It follows the system preference by default, or you can set darkMode to class and toggle a dark class on the root element.
Should I use system or class dark mode?
Use system mode for a simple site that should simply follow the device. Use class mode when visitors need a switch of their own that they can save.
How do I stop the page flashing the wrong theme?
Apply the saved theme in a small inline script in the document head, before the body renders, so the first paint already uses the right colors.
Last updated on · Written by Dinesh Kumar R

