Dark Mode & color-scheme

Implement Dark Mode effortlessly using the color-scheme property and the new light-dark() CSS function.

CSS4 min readConcept 41 of 43

The evolution of Dark Mode

In the early days of dark mode, developers had to write extensive @media (prefers-color-scheme: dark) blocks to manually override the colors of every single element.

Later, we moved to CSS Variables, swapping --bg-color: white to --bg-color: black inside a .dark-theme class.

Modern CSS introduces a native, streamlined approach using the color-scheme property and the light-dark() function, removing the need for media queries entirely.

Less code, native UI support

By simply adding color-scheme: light dark; to your :root, you immediately get dark mode support for native browser elements. Scrollbars, form inputs, checkboxes, and default backgrounds will automatically adapt to the user's OS preference.

For custom elements, the light-dark() function allows you to define both the light and dark colors inline. background-color: light-dark(white, black); is infinitely more readable than maintaining a separate stylesheet for dark overrides.

Implementing light-dark()

First, opt-in at the root level: :root { color-scheme: light dark; }.

Next, use the function for your colors: .card { background: light-dark(#ffffff, #1a1a1a); color: light-dark(#333333, #f5f5f5); }.

The browser will read the current color-scheme (which defaults to the OS preference) and automatically select the first color for light mode, or the second color for dark mode.

Try it

Toggle the color-scheme property of the container below. Watch the light-dark() functions and native UI elements instantly repaint.

light-dark() & color-scheme

Toggle Wrapper Theme

// 1. Force the color-scheme
.theme-wrapper {
color-scheme: light;
}
// 2. Define both colors inline
.surface {
background: light-dark(#ffffff, #1e293b);
color: light-dark(#334155, #e2e8f0);
border: 1px solid light-dark(#e2e8f0, #334155);
}
// Native elements adapt automatically
.native-input {
/* No color CSS needed! */
}
.surface

Account Settings

Notice how everything repaints instantly just by toggling the wrapper's color-scheme.

Native Elements

Check yourself

Pick an answer to lock it in, then read why. Getting one wrong is part of how it sticks.

  1. 1What does `color-scheme: light dark;` applied to the `:root` do?
  2. 2Given `color: light-dark(#ff0000, #0000ff);`, which color will be displayed if the user's OS is in Dark Mode?
  3. 3How can you manually force a specific container (and all its children) to display in dark mode, overriding the OS preference?

Remember this

  • Add color-scheme: light dark; to :root to get free dark-themed scrollbars and form inputs.
  • Use light-dark(light_value, dark_value) to define both themes inline without media queries.
  • Force a theme manually by overriding the color-scheme property on a specific element.

Done with this concept?

Mark it complete to track your progress. No login needed.