Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to use with prefers-color-scheme? #26

Open
Spone opened this issue Nov 8, 2022 · 3 comments · May be fixed by #27
Open

How to use with prefers-color-scheme? #26

Spone opened this issue Nov 8, 2022 · 3 comments · May be fixed by #27

Comments

@Spone
Copy link

Spone commented Nov 8, 2022

I'd like to toggle the dark theme depending on the browser setting, which can be accessed using prefers-color-scheme.

What's the recommended way of doing that?

@gskril
Copy link

gskril commented Jan 6, 2023

Also curious about this. @Spone did you find a solution? I've just started making my own big CSS file like this but it's definitely not ideal.

I would have expected both light/dark scales to apply their CSS variables to the :root element for automatic dark mode.

@Zwyx
Copy link

Zwyx commented Jan 9, 2023

Also thinking about this.

At the moment, Radix outputs things this way:

:root {
  /* variables for light theme */
}
.dark-theme {
  /* variables for dark theme */
}

So by default it's light, and if we apply the dark-theme class to body, then it's dark. This necessitates JavaScript (although it can be done very effectively and without the dreaded flash, by adding a tiny bit of JS at the beginning of body to read the preferred choice from local storage or prefers-color-scheme and set the dark-theme class if necessary; see this and this).

NextJS (create-next-app) does this:

:root {
  /* variables for light theme */
}
@media (prefers-color-scheme: dark) {
  :root {
    /* variables for dark theme */
  }
}

Which works very well to set the correct theme based on OS preferences. And doesn't require JavaScript.

So what Radix could do to combine the best of both, is this:

:root {
  /* variables for light theme */
}
@media (prefers-color-scheme: dark) {
  :root {
    /* variables for dark theme */
  }
}
.light-theme {
  /* variables for light theme */
}
.dark-theme {
  /* variables for dark theme */
}

This way, when the page loads, the correct theme is selected based on OS preferences (even if the user has JavaScript disabled). And then, JavaScript could read local storage and apply light-theme or dark-theme based on the user preference for this particular site.

It's a bit annoying to have to repeat the variables declaration, there might be other ways (@apply was a good candidate, but it has been abandoned).


EDIT: this is basically what PicoCSS does, with only three blocks instead of four:

[data-theme=light],
:root:not([data-theme=dark]) {
  /* variables for light theme */
}

@media only screen and (prefers-color-scheme: dark) {
  :root:not([data-theme=light]) {
  /* variables for dark theme */
  }
}

[data-theme=dark] {
  /* variables for dark theme */
}

Clever!

@Spone
Copy link
Author

Spone commented Jan 18, 2023

Thanks a lot @Zwyx for taking the time to investigate!

@vladmoroz @colmtuite would you be open to supporting this? I can work on a PR if it has a chance to be merged :)

@tubbo tubbo linked a pull request Jan 23, 2023 that will close this issue
tubbo added a commit to tubbo/colors that referenced this issue Jan 23, 2023
Currently, Radix Colors does not easily support the concept of a
machine's own preference for dark/light mode. This poses a problem
when trying to write CSS for dark mode without copying a whole bunch
of variable definitions around. Inspired by the way Pico CSS handles
things, and allowing compatibility between the two, this commit changes
how dark mode is enabled for the document element by using a `data-
theme` attribute rather than a class name. This attribute can be set to
either "dark" or "light", and uses some clever CSS trickery (inspired
by [@Zwyx's comment about Pico](https://github.com/radix-ui/colors/
issues/26#issuecomment-1375542488)) to achieve automatically setting
color variables to the right settings when the system preference for
dark or light mode is set.

To maintain backwards compatibility, these new variants are built using
a different file naming convention. The CSS with `.dark-theme` will
still be available in `${scale}.css` files, but the "classless" variants
that use data-attributes are now available in `${scale}.classless.css`
files.

Resolves: radix-ui#26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants