Dark mode
Style supports dark mode out of the box using the dark: variant prefix. Dark mode classes activate based on your app’s ThemeMode.
Basic usage
Section titled “Basic usage”Prefix any utility with dark: to apply it only when dark mode is active:
Style('bg-white dark:bg-gray-800 rounded-lg px-6 py-8 ring shadow-xl ring-gray-900/5', children: [ Style('inline-flex items-center justify-center rounded-md bg-indigo-500 p-2 shadow-lg', child: Icon(Icons.edit, color: Colors.white, size: 24)), Style('text-gray-900 dark:text-white mt-5 text-base font-medium tracking-tight', child: Text('Writes upside-down')), Style('text-gray-500 dark:text-gray-400 mt-2 text-sm', child: Text('The Zero Gravity Pen can be used to write in any orientation, including upside-down. It even works in outer space.')),])The same component in dark mode — dark:bg-gray-800 replaces the white background, and dark:text-white replaces the dark text.
How it works
Section titled “How it works”In Tailwind CSS, dark: variants respond to prefers-color-scheme: dark or a .dark class on the HTML element.
In Flutter with Style, dark: variants respond to the app’s ThemeMode:
MaterialApp( themeMode: ThemeMode.dark, // Activates dark: variants theme: ThemeData(...), darkTheme: ThemeData(...), home: ...,)| ThemeMode | dark: variants |
|---|---|
ThemeMode.light | Inactive |
ThemeMode.dark | Active |
ThemeMode.system | Follows device setting |
Toggling dark mode
Section titled “Toggling dark mode”Using system preference
Section titled “Using system preference”The simplest approach — let the operating system decide:
MaterialApp( themeMode: ThemeMode.system, // Follows device dark mode setting theme: ThemeData(...), darkTheme: ThemeData(...), home: ...,)Manual toggle
Section titled “Manual toggle”Manage theme state and let users choose:
class MyApp extends StatefulWidget { @override State<MyApp> createState() => _MyAppState();}
class _MyAppState extends State<MyApp> { ThemeMode _themeMode = ThemeMode.system;
void toggleTheme() { setState(() { _themeMode = _themeMode == ThemeMode.dark ? ThemeMode.light : ThemeMode.dark; }); }
@override Widget build(BuildContext context) { return MaterialApp( themeMode: _themeMode, theme: ThemeData(...), darkTheme: ThemeData(...), home: ..., ); }}Common patterns
Section titled “Common patterns”Card with dark mode
Section titled “Card with dark mode”Style( 'bg-white dark:bg-gray-800 rounded-lg shadow-lg p-6', child: Style( 'text-gray-900 dark:text-white font-medium', child: Text('Card title'), ),)Notification with dark mode
Section titled “Notification with dark mode”Style('mx-auto flex max-w-sm items-center gap-x-4 rounded-xl bg-white p-6 shadow-lg outline outline-black/5 dark:bg-slate-800 dark:shadow-none dark:-outline-offset-1 dark:outline-white/10', children: [ Style('size-12 shrink-0', child: Image.network('/img/logo.svg')), Style('...', children: [ Style('text-xl font-medium text-black dark:text-white', child: Text('ChitChat')), Style('text-gray-500 dark:text-gray-400', child: Text('You have a new message!')), ]),])Combining dark with other variants
Section titled “Combining dark with other variants”Dark mode can be combined with hover, focus, and responsive variants:
// Dark mode + hoverStyle('bg-white dark:bg-gray-800 hover:bg-gray-50 dark:hover:bg-gray-700', child: ...)
// Dark mode + responsiveStyle('bg-white dark:bg-gray-800 md:bg-gray-100 md:dark:bg-gray-900', child: ...)Design tips
Section titled “Design tips”- Don’t just invert colors — reduce contrast slightly in dark mode. Use
gray-400instead of pure white for body text. - Adjust shadows — shadows are less visible on dark backgrounds. Consider
dark:shadow-noneor using rings/outlines instead:dark:ring-1 dark:ring-white/10. - Reduce saturation — bright colors can feel harsh on dark backgrounds. Use lighter shades like
dark:bg-sky-400instead ofdark:bg-sky-500.