Dark Mode (prefers-color-scheme)
Most operating systems let a user choose a light or dark theme system-wide, and prefers-color-scheme is the media query that exposes that choice to CSS. Building dark mode support well is less about writing an entirely separate dark stylesheet and more about designing your color system — with custom properties — so light and dark are just two different sets of values for the same variable names.
Detecting the OS theme preference
/* Applies only when the user's OS is set to a dark theme */
@media (prefers-color-scheme: dark) {
body {
background: #121212;
color: #f0f0f0;
}
}A clean architecture: variables + media query
var() automatically follows the active theme — you never touch those rules again when adding or adjusting a theme.:root {
--color-bg: #ffffff;
--color-text: #1a1a1a;
--color-muted: #595959;
--color-border: #dddddd;
--color-accent: #2a6df4;
color-scheme: light;
}
@media (prefers-color-scheme: dark) {
:root {
--color-bg: #121212;
--color-text: #f0f0f0;
--color-muted: #b3b3b3;
--color-border: #3a3a3a;
--color-accent: #6fa1ff;
color-scheme: dark;
}
}
body {
background: var(--color-bg);
color: var(--color-text);
}
.card {
background: var(--color-bg);
border: 1px solid var(--color-border);
}
.card__meta {
color: var(--color-muted);
}
a {
color: var(--color-accent);
}The color-scheme property
Setting color-scheme (covered fully on the color-scheme & prefers-color-scheme page) tells the browser which theme your page currently supports, so it can adapt things you don't directly style — form control chrome, scrollbars, and the text-selection color — to match. Without it, dark-mode pages often end up with a jarring white <select> or input floating in an otherwise dark UI.
:root {
color-scheme: light dark; /* supports both; browser follows the active theme */
}Worked example: a themed component
<div class="notice">
<p>Your changes have been saved.</p>
</div>
:root {
--notice-bg: #eaf4ff;
--notice-border: #a9c9f5;
--notice-text: #0b3d91;
color-scheme: light;
}
@media (prefers-color-scheme: dark) {
:root {
--notice-bg: #10233d;
--notice-border: #274b7a;
--notice-text: #9cc3ff;
color-scheme: dark;
}
}
.notice {
background: var(--notice-bg);
border: 1px solid var(--notice-border);
color: var(--notice-text);
padding: 1rem;
border-radius: 8px;
}