CSS light-dark() Function

CSS light-dark() lets you provide two values for a color-related property: one for a light color scheme and one for a dark scheme. The browser chooses the value that matches the element's effective color-scheme. This can make a theme easier to maintain than repeating the same selectors inside many dark-mode media queries.

Use it for surfaces, text, borders, and other places that accept a color. The function is available in modern browsers; if you support older ones, keep a conventional fallback declaration first.

How light-dark() chooses a color

The syntax is light-dark(light-value, dark-value). The first argument is used in a light scheme; the second is used in a dark scheme. The values must be valid for the CSS property where you use them. The browser does not decide from the page's current background color. It uses the color-scheme setting.

Declare color-scheme: light dark on :root when your page supports both schemes. The browser can then follow the user's light or dark preference. You can also set color-scheme: dark or color-scheme: light on a component to force one scheme within it.

Example: Give a card two color sets

/* Allow the page to follow the user's color preference. */
:root { color-scheme: light dark; }

.card {
  background: #fff; /* Fallback before the newer declaration. */
  background: light-dark(#fff, #1e293b);
  color: light-dark(#1e293b, #f8fafc);
  border: 1px solid light-dark(#cbd5e1, #64748b);
}

The light card has a white surface and dark text. In a dark scheme, those choices reverse to a dark surface and light text. Notice that the border changes too; switching only the background may leave a component hard to read.

Try a complete light-dark() example

The following demo contains a scheme selector. Choose Light or Dark to set the card's color-scheme directly, or leave System preference selected to let the browser decide. You can edit the colors and run it again.

Example: Switch a card between color schemes

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>CSS light-dark() demo</title>
  <style>
    :root { color-scheme: light dark; }
    body { font: 1rem/1.5 system-ui, sans-serif; margin: 2rem; }
    .card {
      max-width: 28rem;
      padding: 1.25rem;
      border-radius: .75rem;
      background: #fff; /* Fallback for older browsers. */
      background: light-dark(#fff, #1e293b);
      color: light-dark(#1e293b, #f8fafc);
      border: 1px solid light-dark(#cbd5e1, #64748b);
    }
    label { display: block; margin-bottom: .5rem; }
    select { margin-bottom: 1rem; padding: .4rem; }
  </style>
</head>
<body>
  <label for="mode">Choose a color scheme</label>
  <select id="mode">
    <option value="normal">System preference</option>
    <option value="light">Light</option>
    <option value="dark">Dark</option>
  </select>
  <section class="card" id="card">
    <h1>Reading card</h1>
    <p>The same light-dark() rules adapt to the chosen scheme.</p>
  </section>
  <script>
    // Change the scheme on this card without changing its CSS colors.
    document.querySelector('#mode').addEventListener('change', (event) => {
      document.querySelector('#card').style.colorScheme = event.target.value;
    });
  </script>
</body>
</html>

The dropdown changes the card's scheme, not each color separately. That is the benefit of this pattern: one scheme setting drives all of the card's light-dark() declarations. Its text, border, and background stay coordinated.

Use a fallback for older browsers

Write the ordinary declaration before the light-dark() declaration for the same property. A browser that does not understand the function ignores that later declaration and retains the earlier value. Choose a fallback with enough contrast, usually the light version if that is your default design.

Example: Keep a readable fallback

.notice {
  background-color: #f1f5f9; /* Older-browser fallback. */
  background-color: light-dark(#f1f5f9, #334155);
  color: #0f172a;
  color: light-dark(#0f172a, #f8fafc);
}

If you support older browsers and still require a complete dark theme there, add a prefers-color-scheme media query as part of your fallback strategy. A single light fallback alone will not create a dark theme in those browsers.

Practical checks

  • Test both schemes, including keyboard focus, links, form controls, and disabled states.
  • Check color contrast in both versions; light-dark() selects colors but does not guarantee readability.
  • Set color-scheme intentionally. Without both schemes enabled, the user's dark preference may not produce the result you expect.
  • Use a local color-scheme for a themed component only when its descendants and built-in controls should follow that scheme too.

Conclusion

light-dark() pairs a light value with a dark one in a single CSS declaration. Enable the schemes your page supports, supply a readable fallback, and test the entire component in both modes. It is a concise way to keep related theme colors together while respecting the user's preference.



Found This Page Useful? Share It!
Get the Latest Tutorials and Updates
Join us on Telegram