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

Support for prefers-color-scheme media query #27514

Closed
rolandasb opened this issue Oct 25, 2018 · 50 comments · Fixed by #35857
Closed

Support for prefers-color-scheme media query #27514

rolandasb opened this issue Oct 25, 2018 · 50 comments · Fixed by #35857
Assignees

Comments

@rolandasb
Copy link
Contributor

Apple introduced prefers-color-scheme media query in Safari Technology Preview 68, which allows developers to apply different rules if user is using dark mode on Mac Mojave:

@media (prefers-color-scheme: light) { ... }
@media (prefers-color-scheme: dark) { ... }

https://trac.webkit.org/changeset/237156/webkit

Maybe it's worth supporting this in Bootstrap?

@patrickhlauke
Copy link
Member

what kind of support would you envisage? doubling up the color scheme everywhere? i wouldn't be adverse, but this needs careful planning/defining

@rolandasb
Copy link
Contributor Author

I don't know if such tool exists, but what I thought was the ability to set variable like $enable-dark-mode which on compilation would find existing variables that have suffix -dark and include media queries in places where those variables are used. For example, if set variable:

$link-color-dark: lightblue;

it would insert into _reboot.scss:

a {
  color: $link-color;
  ...
  
  @media (prefers-color-scheme: dark) {
    color: $link-color-dark;
  }
}

@mdo
Copy link
Member

mdo commented Oct 27, 2018

Would be cool, but this is only in the Safari tech preview version, and no other browser. Can't really make use of it effectively for folks unless there's far more support. Closing as it's too early to use.

@mdo mdo closed this as completed Oct 27, 2018
@swrobel
Copy link
Contributor

swrobel commented Feb 1, 2019

This is in-progress for Chrome and implemented for Firefox 67 so it might be worth revisiting for BS5

@mrlife
Copy link
Contributor

mrlife commented Apr 11, 2019

Just putting this here for easy reference. The Resources tab links to browser-specific status and the specification.

https://caniuse.com/#search=prefers-color-scheme

@waterfoul
Copy link

Any chance of reopening this one?

@patrickhlauke
Copy link
Member

once it has more sizeable support @waterfoul, sure. as it stands, it's a lot of potential work for little gain just now.

@swrobel
Copy link
Contributor

swrobel commented May 3, 2019

more sizeable support

please define

@mdo
Copy link
Member

mdo commented May 3, 2019

Safari and Firefox support isn't enough IMO and the supporting the media query presents additional implementation issues that we'd have to advise on or implement ourselves (e.g., fallbacks for IE and Edge that don't support it currently). Getting Chrome on board would be helpful obviously, but I think this is something more suited to a v6.

@swrobel
Copy link
Contributor

swrobel commented May 3, 2019

Getting Chrome on board would be helpful

As previously mentioned, this is being actively worked on and is targeted for Chrome 76, to be released around July 30

@waterfoul
Copy link

waterfoul commented May 3, 2019

We currently use two css classes to pull this off with a style switcher but it requires a very bloated payload to pull off (since having multiple color schemes requires multiple copies of bootstrap). In order to better support using multiple themes and to prepare for these media queries would it make sense to provide a way to generate a copy of bootstrap with color information only which could be used as an override?

@felixfbecker
Copy link

felixfbecker commented May 5, 2019

This is implemented in Chrome and will ship in the next release, working on macOS, Windows and Linux. Intend to ship: https://groups.google.com/a/chromium.org/forum/#!topic/blink-dev/sLK1cLgvieg/discussion

That means it is then supported by Safari, Firefox and the new Chromium Edge (I don't think there is active development on old Edge).

I think this is a great oppurtunity for Bootstrap - I predict that websites will be expected to have automatic dark modes in the future, and developers will not want to hand-code it. Bootstrap can help here by making automatic dark mode "just work", and it can still be configurable.

@patrickhlauke
Copy link
Member

for all those who are pushing for it...i look forward to your pull requests

@felixfbecker
Copy link

@patrickhlauke shall we interpret that as an approval of the feature? Surely noone wants to work on this if it would not get merged anyway because maintainers think it's a bad idea

@felixfbecker
Copy link

As it stands, the issue is closed, which communicates that there is no interest in having this feature. If you want PRs, a first step would be to reopen the issue

@patrickhlauke
Copy link
Member

nobody said it's a bad idea. what was said is that it's a lot of work for little practical gain just now. if somebody wants to start putting all the work in... (chicken and egg)

@bardiharborow bardiharborow self-assigned this May 5, 2019
@bardiharborow bardiharborow reopened this May 5, 2019
@bardiharborow
Copy link
Member

@felixfbecker sorry if there was miscommunication, you can consider this tentatively approved for either v5 or v6, but we're lacking cycles on our end. I'm happy to coordinate with someone if they don't mind slightly delayed turnaround.

@waterfoul
Copy link

waterfoul commented May 5, 2019

The more I look at this the more this feels like the perfect use-case for css variables. They are currently supported in every evergreen browser but are not available in IE which bootstrap currently supports. Would the bootstrap team be open to dropping IE support in the next major? It's become a little used browser (<3% usage world wide/<5% in the US/It's biggest market) and even Microsoft is recommending people not use it except for legacy applications.

@bardiharborow
Copy link
Member

@waterfoul v6, yes. v5, no.

@waterfoul
Copy link

Are there any rough timelines for v5 and v6? I would rather this be done right since it will likely be a large change and if that means waiting a bit longer that's fine. I would just like to know roughly how much longer

@lachlanjc
Copy link
Contributor

Dark Mode is now on production Safari, & coming to iPhone/iPad this fall. This would be an awesome update to Bootstrap!

@mdo
Copy link
Member

mdo commented Jun 13, 2019

Without the move to CSS custom properties, is the intent here then a mixin and proper dark mode (or more generally, color scheme) support across all components?

@ntkme
Copy link
Contributor

ntkme commented Jul 7, 2019

I would like to start a little bit technical conversation here, as I recently implemented dark mode on websites I built with bootstrap.


Here are a few ideas:

Option 1

It is going to be tedious due to the ugly design of the prefers-color-scheme media query itself. Today's bootstrap already provides light & dark theme on a few components, which means it would be difficult to modifying current implementation with mixins, and such change would doubling color related code as result (compression might help, but still very annoying). Just imagine the result as below:

.table {
  /* light color scheme */
}

.table-dark {
  /* dark color scheme */
}

@media (prefers-color-scheme: dark) {
  .table {
    /* dark on dark (?) color scheme */
  }

  .table-dark {
    /* light on dark (?) color scheme */
  }
}

Option 2

We can drop .*-dark classes everywhere, and have light as default and dark in dark mode, which would cut the clutter, but would also greatly limit the possibility in website design.

Option 3

We will never support prefers-color-scheme via mixin & in-stylesheet media query, instead bootstrap would officially support a build with different colors that's optimized for dark mode, and users would use it like this:

<link href="bootstrap-light.css" rel="stylesheet">
<link href="bootstrap-dark.css" rel="stylesheet" media="(prefers-color-scheme: dark)">

The work to implement this option is minimum (pick a set of colors). It does have a catch that when dark mode is loaded, all css rules (including non-color related) are double loaded. However, this would also give designer the flexibility to choose between:

  1. Light theme everywhere.
  2. Dark theme everywhere.
  3. Light theme on light mode, dark theme on dark mode.
  4. Dark theme on light mode, light theme on dark mode.

Option 4

Fully switch to css variables, which means drop IE 11 support. This might be a future solution but probably won't happen anytime soon. https://caniuse.com/#feat=css-variables


Personally I would vote for option 3 today for two major reasons:

  1. It would work with a custom build of today's v4.
  2. It would not over-complicate the current scss building system and utilities.

For the long term future (v6 I guess), I would vote for option 4.

@florianlacreuse
Copy link
Contributor

To solutions with multiple css <link>, be careful of FOUC behavior. This issue may be increasingly irrelevant these days but could still occur.

@vinorodrigues
Copy link
Contributor

For those of you who took the time to read my The Definitive Guide to Dark Mode and Bootstrap 4 (also on GitHub.) ...

... I've also churned the Bootstrap 5β1 variant (also on GitHub.)

@ffoodd
Copy link
Member

ffoodd commented Feb 10, 2021

Another piece of thinking: in an initial question on Twitter by @fvsch, @chriskirknielsen suggested an interesting approach based on CSS custom properties. Here's the CodePen demoing this.

This works thanks to the "guaranteed invalid value at computed time" feature, using the initial keyword (might also be know as the space toggler —named this way by @James0x57 and heavily used in CSS Media Vars for example).

This basically unveils to have a very simple layer on top of our styles, working as an API for color themes—being defined through a class, an attribute or a user preference.

Don't know if it's applicable to Bootstrap and how much work would be required, but it's definitely the smarter and CSS-ier approach I've seen so far.

@ThisGitHubUsernameWasAvailable

Why v6? IE support is already dropped, so now there is no reason not to do this in v5.

@mdo
Copy link
Member

mdo commented Nov 30, 2021

There's a chance we can do this in v5, but there's a lot of work to be done in converting all components and utilities to CSS variables. Difficult to get it right quickly for a large codebase :).

@Carl-Hugo
Copy link

Carl-Hugo commented Dec 2, 2021

In case this can help @mdo, how I'm tackling this in my Bootstrap 4 dark theme project (latest option) is:

  1. Build the two stylesheets: Bootstrap standard + Bootstrap dark (basically just setting variables and a few other tweaks for the dark theme)
  2. A (gulp) script builds two more stylesheets, wrapped into a prefers-color-scheme (dark and light).
  3. The script strips all but colors from those two stylesheets and saves them
  4. The script assembles a default stylesheet (step 1: light or dark) then the opposite color sheet (output of step 3), leading to two stylesheets and the use-cases below.

Use cases:

- default: light - prefers: -     => light
- default: light - prefers: light => light
- default: light - prefers: dark  => dark
- default: dark - prefers: -      => dark
- default: dark - prefers: light  => light
- default: dark - prefers: dark   => dark

That seems to work pretty well so far (but one detail). I chose to tackle this method as it seemed very low maintenance. In your case, you could even apply the few tweaks directly to the codebase leading to even less effort to implement at first glance and easier maintainability. Anyway, if you are interested in knowing more please let me know.

Here's my WIP PR: ForEvolve/bootstrap-dark#51


EDIT:
Please let me know @vinorodrigues if you are still confused after this addition. Also, feel free to let me know if things changed a lot from BS4 to BS5; I don't do much CSS/frontend work these days but based on a quick scan of the Bootstrap 5 [S]CSS files I think this automated process should still work.

Assuming things haven't changed that much, let's start with the basics so we are talking about the same thing. To have two themes (light and dark) and allow users to choose, we need:

  • 1x Core styles (padding, margin, etc.)
  • 2x Color styles (one dark, one light)

Bootstrap generates (Core + Light Colors) in one pass leading to one CSS file. Bootstrap is inputting a single set of variables, including colors.

To generate the dark version of Bootstrap, you can do the same thing but provide an overridden version of the color variables. If you run this through the same process, you end up with a (Core + Dark Colors) CSS file.

Assuming we all agree on that process, the aforementioned script saves the time to refactor the CSS to support two sets of color by taking one of the two CSS files and stripping all non-color properties from it, leading to a color-only CSS file.

If you take a full CSS file (say Bootstrap), then append a Dark Color-only CSS file wrapped in a prefers-color-scheme: dark media query to it (give or take), you end up with a light theme by default and a dark theme when preferred. The CSS is even "optimized" with 1x Core + 2x Colors, no duplicated styles.

Here is part of an example of such result (from Bootstrap 4 code):

// Default (Core + Light)
body {
    margin: 0;
    font-family: ...;
    font-size: 1rem;
    font-weight: 400;
    line-height: 1.5;
    color: #212529;
    text-align: left;
    background-color: #fff;
}
// more styles...

// Dark part (colors-only)
@media (prefers-color-scheme:dark) {
    body {
        color: #d3d3d3;
        background-color: #191d21;
    }
     // More styles (colors-only)
}

Of course, you can always refactor everything to support two sets of color or maintain multiple stylesheets instead, but this seems like a straightforward enough workaround (see even final solution) that leads to the expected results of the requirements: 1x Core CSS + 2x Colors supporting a default and a prefers-color-scheme.

In the end, the process takes a few [milli]seconds of "build time" in a CI pipeline and allows maintaining a single codebase/generation process. This just attacks the problem from a different, maybe less classic, angle.

@tonimelisma
Copy link

Hey @mdo, I understand this was added to the v5.3.0 To do list. Can you clarify if you're looking to include the functionality in 5.3.0?

@twbs twbs deleted a comment from tungphan995 Aug 17, 2022
@mdo
Copy link
Member

mdo commented Aug 20, 2022

We already have the mixin available, but the color mode work is coming in #35857. The implementation there will be via data attribute as opposed to media query, but I'm exploring an option to support both somehow, perhaps through use of a mixin and global variable flip.

The intention in that PR is to support multiple color modes/themes, improve global theming, and not just provide an involuntary light/dark option.

@vanillajonathan
Copy link
Contributor

Maybe there could also be support for the CSS media query "prefers-contrast" which could be "more" or "less" for more or less contrast.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
No open projects
Status: Done
Development

Successfully merging a pull request may close this issue.