Skip to content

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.


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.


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: ...,
)
ThemeModedark: variants
ThemeMode.lightInactive
ThemeMode.darkActive
ThemeMode.systemFollows device setting

The simplest approach — let the operating system decide:

MaterialApp(
themeMode: ThemeMode.system, // Follows device dark mode setting
theme: ThemeData(...),
darkTheme: ThemeData(...),
home: ...,
)

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: ...,
);
}
}

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'),
),
)
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!')),
]),
])

Dark mode can be combined with hover, focus, and responsive variants:

// Dark mode + hover
Style('bg-white dark:bg-gray-800 hover:bg-gray-50 dark:hover:bg-gray-700', child: ...)
// Dark mode + responsive
Style('bg-white dark:bg-gray-800 md:bg-gray-100 md:dark:bg-gray-900', child: ...)

  • Don’t just invert colors — reduce contrast slightly in dark mode. Use gray-400 instead of pure white for body text.
  • Adjust shadows — shadows are less visible on dark backgrounds. Consider dark:shadow-none or 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-400 instead of dark:bg-sky-500.