No this is definitively not the proper way to do this.
The HTMLStyleElement (<style>
) has a .disabled
property for this task:
const button = document.querySelector("button");
const style = document.querySelector("style");
button.onclick = (evt) => style.disabled = !style.disabled;
button { color: red; }
<button>click me to toggle color</button>
And even <link>
elements have that property.
const button = document.querySelector("button");
// creates a <link> element pointing to a stylesheet
// containing the single rule "button { color: red; }"
const link = document.createElement("link");
link.rel = "stylesheet";
link.href = URL.createObjectURL(new Blob([`button { color: red; }`], { type: "text/css" }));
link.onload = (evt) => URL.revokeObjectURL(link.href);
document.head.append(link);
// works with <link> too
button.onclick = (evt) => link.disabled = !link.disabled;
<button>click me to toggle color</button>
An other way would be to add a class on a common ancestor, and check for the presence or absence of such class in every rules, but this will force you to repeat a lot of rules. Might still be useful nevertheless.
const select = document.querySelector("select");
select.onchange = (evt) => {
document.body.classList.remove("shade-auto", "light", "dark");
document.body.classList.add(select.value);
};
document.body.classList.add(select.value);
body.light {
background: white;
color: black;
}
body.light select {
background: #EEE;
color: #222;
}
body.dark {
background: #222;
color: #eee;
}
body.dark select {
color: #eee;
background: #333;
}
@media (prefers-color-scheme: light) {
body.shade-auto {
background: white;
color: black;
}
}
@media (prefers-color-scheme: dark) {
body.shade-auto {
background: #222;
color: #eee;
}
body.shade-auto select {
color: #eee;
background: #333;
}
}
<select>
<option value="shade-auto">Auto (respect OS)</option>
<option value="light">Force Light mode</option>
<option value="dark">Force Dark mode</option>
</select>
Foo bar