The color-scheme property enables native dark mode support and affects browser UI elements. Here's how to use it.
Basic Usage#
1/* Support both light and dark */
2:root {
3 color-scheme: light dark;
4}
5
6/* Light only */
7:root {
8 color-scheme: light;
9}
10
11/* Dark only */
12:root {
13 color-scheme: dark;
14}
15
16/* Use system preference */
17:root {
18 color-scheme: normal;
19}
20
21/* HTML meta tag equivalent */
22/* <meta name="color-scheme" content="light dark"> */System Colors#
1/* System colors adapt to color-scheme */
2:root {
3 color-scheme: light dark;
4}
5
6body {
7 /* These automatically adapt */
8 background-color: Canvas;
9 color: CanvasText;
10}
11
12a {
13 color: LinkText;
14}
15
16a:visited {
17 color: VisitedText;
18}
19
20button {
21 background-color: ButtonFace;
22 color: ButtonText;
23 border-color: ButtonBorder;
24}
25
26input {
27 background-color: Field;
28 color: FieldText;
29}
30
31::selection {
32 background-color: Highlight;
33 color: HighlightText;
34}
35
36mark {
37 background-color: Mark;
38 color: MarkText;
39}Form Element Styling#
1/* Browser automatically styles form elements */
2:root {
3 color-scheme: light dark;
4}
5
6/* Form elements adapt to color scheme */
7input,
8textarea,
9select {
10 /* Native styling respects color-scheme */
11 color-scheme: inherit;
12}
13
14/* Dark inputs in light page */
15.dark-input {
16 color-scheme: dark;
17}
18
19/* Light inputs in dark page */
20.light-input {
21 color-scheme: light;
22}
23
24/* Scrollbar also adapts */
25.scrollable {
26 overflow: auto;
27 color-scheme: dark; /* Dark scrollbar */
28}Theme Switching#
1/* Base with system preference */
2:root {
3 color-scheme: light dark;
4
5 /* Light mode variables */
6 --bg-color: #ffffff;
7 --text-color: #333333;
8 --border-color: #dddddd;
9}
10
11/* Dark mode overrides */
12@media (prefers-color-scheme: dark) {
13 :root {
14 --bg-color: #1a1a1a;
15 --text-color: #e0e0e0;
16 --border-color: #444444;
17 }
18}
19
20/* Manual theme class overrides */
21:root.light {
22 color-scheme: light;
23 --bg-color: #ffffff;
24 --text-color: #333333;
25}
26
27:root.dark {
28 color-scheme: dark;
29 --bg-color: #1a1a1a;
30 --text-color: #e0e0e0;
31}
32
33body {
34 background-color: var(--bg-color);
35 color: var(--text-color);
36}Component-Level Schemes#
1/* Different schemes per component */
2.light-section {
3 color-scheme: light;
4 background: white;
5 color: black;
6}
7
8.dark-section {
9 color-scheme: dark;
10 background: #1a1a1a;
11 color: white;
12}
13
14/* Modal with specific scheme */
15.modal {
16 color-scheme: light;
17}
18
19.modal.dark-modal {
20 color-scheme: dark;
21}
22
23/* Card respects parent scheme */
24.card {
25 color-scheme: inherit;
26 background: Canvas;
27 color: CanvasText;
28 border: 1px solid ButtonBorder;
29}Images and Media#
1/* Different images for schemes */
2.logo {
3 content: url('/logo-light.svg');
4}
5
6@media (prefers-color-scheme: dark) {
7 .logo {
8 content: url('/logo-dark.svg');
9 }
10}
11
12/* Adjust images in dark mode */
13@media (prefers-color-scheme: dark) {
14 img:not([src*=".svg"]) {
15 filter: brightness(0.9);
16 }
17}
18
19/* Picture element approach */
20/*
21<picture>
22 <source srcset="dark.png" media="(prefers-color-scheme: dark)">
23 <img src="light.png" alt="Logo">
24</picture>
25*/Browser UI Integration#
1/* Affects browser chrome */
2:root {
3 color-scheme: dark;
4}
5
6/* Browser UI elements affected:
7 - Scrollbars
8 - Form controls
9 - Text selection
10 - Caret color
11 - Default backgrounds
12*/
13
14/* iOS/Safari specific */
15:root {
16 /* Dark status bar and UI */
17 color-scheme: dark;
18}
19
20/* PWA theme color coordination */
21/* In manifest.json or meta tags */
22/*
23<meta name="theme-color"
24 media="(prefers-color-scheme: light)"
25 content="#ffffff">
26<meta name="theme-color"
27 media="(prefers-color-scheme: dark)"
28 content="#1a1a1a">
29*/Scrollbar Styling#
1/* color-scheme affects scrollbar */
2.light-scroll {
3 color-scheme: light;
4 overflow: auto;
5 /* Light scrollbar track and thumb */
6}
7
8.dark-scroll {
9 color-scheme: dark;
10 overflow: auto;
11 /* Dark scrollbar track and thumb */
12}
13
14/* Custom scrollbars with scheme */
15.custom-scroll {
16 color-scheme: dark;
17}
18
19.custom-scroll::-webkit-scrollbar {
20 width: 10px;
21}
22
23.custom-scroll::-webkit-scrollbar-track {
24 background: Canvas;
25}
26
27.custom-scroll::-webkit-scrollbar-thumb {
28 background: ButtonFace;
29 border-radius: 5px;
30}JavaScript Integration#
1// Detect system preference
2const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
3
4// Listen for changes
5window.matchMedia('(prefers-color-scheme: dark)')
6 .addEventListener('change', (e) => {
7 const isDark = e.matches;
8 document.documentElement.style.colorScheme = isDark ? 'dark' : 'light';
9 });
10
11// Set color scheme programmatically
12function setColorScheme(scheme) {
13 document.documentElement.style.colorScheme = scheme;
14
15 // Also update meta tag
16 const meta = document.querySelector('meta[name="color-scheme"]');
17 if (meta) {
18 meta.content = scheme;
19 }
20}
21
22// Toggle function
23function toggleDarkMode() {
24 const current = getComputedStyle(document.documentElement).colorScheme;
25 setColorScheme(current === 'dark' ? 'light' : 'dark');
26}
27
28// Get effective color scheme
29function getEffectiveColorScheme() {
30 return getComputedStyle(document.documentElement).colorScheme;
31}Print Styling#
1/* Light scheme for printing */
2@media print {
3 :root {
4 color-scheme: light;
5 }
6
7 body {
8 background: white;
9 color: black;
10 }
11
12 /* Reset any dark mode styles */
13 * {
14 background-color: transparent !important;
15 color: black !important;
16 }
17}Iframe Integration#
1/* Parent document */
2:root {
3 color-scheme: light dark;
4}
5
6/* Iframe inherits by default */
7iframe {
8 color-scheme: inherit;
9}
10
11/* Force specific scheme for iframe */
12.light-iframe {
13 color-scheme: light;
14}
15
16/* In iframe document */
17/* :root { color-scheme: inherit; } */Transition Effects#
1/* Smooth transitions between schemes */
2:root {
3 color-scheme: light dark;
4 transition: background-color 0.3s, color 0.3s;
5}
6
7body {
8 background-color: Canvas;
9 color: CanvasText;
10 transition: background-color 0.3s ease, color 0.3s ease;
11}
12
13/* Disable transitions for reduced motion */
14@media (prefers-reduced-motion: reduce) {
15 :root,
16 body {
17 transition: none;
18 }
19}
20
21/* Prevent FOUC during load */
22html:not(.loaded) {
23 visibility: hidden;
24}
25
26.loaded {
27 visibility: visible;
28}Best Practices#
Usage:
✓ Set on :root for global effect
✓ Use system colors
✓ Support both schemes
✓ Test in both modes
Benefits:
✓ Native form styling
✓ Scrollbar adaptation
✓ Reduced code
✓ System integration
Browser UI:
✓ Scrollbars
✓ Form controls
✓ Selection colors
✓ Caret styling
Avoid:
✗ Ignoring system preference
✗ Inconsistent schemes
✗ Forgetting form elements
✗ Hard-coded colors
Conclusion#
The color-scheme property enables native dark mode support by telling browsers which color schemes your content supports. It automatically adapts form elements, scrollbars, and other browser UI. Combine with CSS custom properties and system colors for comprehensive theme support that respects user preferences.