I found a solution, that would be using cssRules
, that the @Augusto Vasques mentioned in a comment.
This isn’t exactly how I wanted it, it won’t work with more complex media queries (example: min-width). For it to work it would require you to create some dictionary to then retrieve the old values.
Considering, exactly:
html {
--color: #OOOOOO;
}
@media (prefers-color-scheme: dark) {
html {
--color: #FFFFFF;
}
}
If we were running the browser with light
, the color will be #OOOOOO
. My question would be how to change the browser to dark
, unfortunately this has no way and I will mark any other reply as valid that does just that.
What we have to do is change the @media (prefers-color-scheme: dark)
for @media (prefers-color-scheme: light)
, this way the second variable will override the previous one. So how are you like light
will now use #FFFFFF
, because the dark
of CSS turned light
.
To do this magic there is the cssRules
, as I mentioned before. In total, my code was something like:
JS:
// Quando tiver mais tempo dou uma organizada no código, porque nem eu estou entendendo, simplesmente copiei o que fiz em Golang. Deve ter como fazer melhor em JS.
window.document.querySelector("fullscreen").addEventListener("click", function(e) {
if (!(e.target instanceof HTMLButtonElement)) {
return;
}
if (IsBrowser(e.target.dataset.mode)) {
SetTheme("light", "dark"); // Mudamos para o padrão, já que quer usar aquilo que o seu navegador já é.
} else {
SetTheme("dark", "light"); // Mudamos para o oposto ao seu navegador (porque se estiver como "dark" o CSS virá "light"; se estiver usando como "light" passará a ser "light" e então o modo noturno será ativado).
}
});
window.matchMedia("(prefers-color-scheme: light)").addEventListener("change", function (_) {
SetTheme("light", "dark"); // Se você mudar no browser voltamos ao modo normal do CSS.
})
function IsBrowser(t) {
return window.matchMedia("(prefers-color-scheme: " + t + ")").matches;
}
function SetTheme(o, n) {
let rules = window.document.styleSheets[0].cssRules;
for (i = 0; i < rules.length; i++) {
media = rules[i].media
if (media == undefined) {
continue
}
current = media.mediaText
current = current.replace("(prefers-color-scheme: " + o + ")", "(prefers-color-scheme: " + n + ")");
rules[i].media.mediaText = current
}
}
html {
--background: aqua;
}
@media (prefers-color-scheme: dark) {
html {
--background: brown;
}
}
fullscreen {
display: block;
height: 100vh;
width: 100vw;
background-color: var(--background);
}
<fullscreen>
<button data-mode=dark>Escuro</button>
<button data-mode=light>Claro</button>
</fullscreen>
Golang:
func SetTheme(old, new string) {
rules := js.Global.Get("document").Get("styleSheets").Index(0).Get("cssRules")
for i := 0; i < rules.Length(); i++ {
media := rules.Index(i).Get("media")
if media == js.Undefined {
continue
}
current := media.Get("mediaText").String()
current = strings.Replace(current, `(prefers-color-scheme: `+old+`)`, `(prefers-color-scheme: `+new+`)`, -1)
media.Set("mediaText", current)
}
}
You could do it using
@custom-media
(Chapter 4 and 4.1) but the recommendation so far has not been implemented in any browser.– Augusto Vasques