RSS FeedTwitterMastodonBlueskyShare IconHeart IconGithub IconArrow IconClock IconGUI Challenges IconHome IconNote IconBlog IconCSS IconJS IconHTML IconShows IconGit IconSpeaking IconTools IconShuffle IconNext IconPrevious IconCalendar IconCalendar Edit Icon
Screenshot of 2 columns each with alternating light and dark nested elements
My google avatar.5 min read

Page and Component Adaptive Light/Dark

css

Sometimes having a light and dark version of the site isn't enough. Sometimes you need light and dark elements, sections or components. Additionally, sometimes you want more than just light and dark.

These nested light and dark scenarios can be tricky.

This post covers 3 strategies: one that can be used today and two that can be used in the future.

Today #

Color-scheme and light-dark() #

With color-scheme and light-dark(), the strategy is minimal and effective. One, possibly big, limit is that this is only for color values. But the HTML is clean and tidy.

HTML

<section class="dark">
  <h1>Dark</h1>
  
  <section class="light">
    <h1>Light</h1>
    
    <section class="dark">
      <h1>Dark</h1>
    </section>
  </section>
</section>

CSS

.dark  { color-scheme: dark }
.light { color-scheme: light }

section {
  background: light-dark(#ddd, #222);
  color: light-dark(#222, #ddd);
}

Can I Use?

Maybe color is all you need to adapt your components and pages. If so, take this code and run!

Future #

@scope #

Miriam Suzanne showed us that a primary use case for @scope is for scoping light and dark contexts.

They break it down with lots of detail in the @scope Explainer.

I've adapted the demo from this post to use @scope. The HTML can match the light-dark() version, but the CSS changes:

@scope (.dark) {
  :scope {
    color-scheme: dark;
    background: #222;
    color: #ddd;
    border: 5px dashed cyan;
  }
}

@scope (.light) {
  :scope {
    color-scheme: light;
    background: #ddd;
    color: #222;
    border: 5px solid hotpink;
  }
}

Can I Use?

We don't get to query or do anything "just in time", but we are able to change colors and any styles we want within a light or dark context.

Style Queries #

But if you want to adapt more than just color in these nested scenarios, then Style Queries and custom properties holding the color-scheme value can be used.

The HTML does need adjusted though because a style query can only query a parent, so each new context needs wrapped in an element with the .dark or .light class.

<div class="dark">
  <section>
    <h1>Dark</h1>
    <div class="light">
      <section>
        <h1>Light</h1>
        <div class="dark">
          <section>
            <h1>Dark</h1>
          </section>
        </div>
      </section>
    </div>
  </section>
</div>
.dark, .light {
  color-scheme: var(--color-scheme);
}

.dark  { --color-scheme: dark }
.light { --color-scheme: light }

section {
  background: light-dark(#ddd, #222);
  color: light-dark(#222, #ddd);
  
  @container style(--color-scheme: light) {
    border: 10px solid pink;
  }
  
  @container style(--color-scheme: dark) {
    border: 5px dashed cyan;
  }
}

Can I Use?

While the HTML is decently less approachable and manageable, it does have some nice benefits.

What strategy are you using?

Mentions #

Join the conversation on

47 likes
18 reposts
  • Sara Joy :happy_pepper:
  • Apple Annie :prami:
  • Toby Evans
  • Jan ⚓️
  • Matthias Ott
  • graste
  • Roma Komarov
  • Kai Klostermann
  • Francis Rubio :verified:
  • bizzl / fourteen bit
  • Sylvain Soliman ☕️
  • Ryan Mulligan
  • Fynn Becker
  • Martin Matovu
  • GENKI
  • Brett Peary
  • Heather Buchel
  • Marcos de Miguel

@chriskirknielsen @argyleink Style queries might be so powerful that you might be able to create a IE6 rendering simulator for modern engines.

Because thats of course the first useful thing that comes to my mind.

Vesa PiittinenVesa Piittinen

@argyleink oh, one less draft for me to finish, haha.

Edit: oh wait, nevermind, still need to finish it, just with less content :D

Roma KomarovRoma Komarov

@argyleink 👏 Great post!

Matthias OttMatthias Ott
I prefer using `color-mix()` (for `color`, `background`, `border-color`, etc.) with a percentage that depends on a `--dark` flag that's either `0` or `1`. This `--dark` can be then changed on any element. Also, margins, paddings, clip-paths and so on can be made to depend on it.
Ana TudorAna Tudor
Pinning this one for later! 📌
Sherri AlexanderSherri Alexander
I'm planning on making my next color scheme with each custom property equivalent to and falling back to each of the 'forced' color keywords: "Canvas, CanvasText, ButtonFace, etc", which should be pretty handy for dark mode, and easier for testing with high-contrast etc. codepen.io/crowjake/pen...
Jacob MirzaianJacob Mirzaian
Sounds like a good idea!
Adam ArgyleAdam Argyle
No style queries needed!
Adam ArgyleAdam Argyle

Crawl the CSS Webring