如何更改 CSS: JavaScript 中的根颜色变量

好的,我正在为我的网页创建一个允许用户改变主题的系统。我希望通过将所有颜色作为变量来实现这一点,并且颜色设置在 CSS 的: root 部分。

我想做的是通过 JavaScript 改变这些颜色。我查了查怎么做到的,但是我尝试过的方法都不管用。这是我目前的代码:

CSS:

:root {
--main-color: #317EEB;
--hover-color: #2764BA;
--body-color: #E0E0E0;
--box-color: white;
}

约翰逊:

(设置主题的代码,只需点击一个按钮就可以运行)-我没有麻烦将: root change 添加到其他2个主题中,因为它在 Dark 主题中不起作用

function setTheme(theme) {
if (theme == 'Dark') {
localStorage.setItem('panelTheme', theme);
$('#current-theme').text(theme);
$(':root').css('--main-color', '#000000');
}
if (theme == 'Blue') {
localStorage.setItem('panelTheme',  'Blue');
$('#current-theme').text('Blue');
alert("Blue");
}
if (theme == 'Green') {
localStorage.setItem('panelTheme', 'Green');
$('#current-theme').text('Green');
alert("Green");
}
}

(加载 html 时运行的代码)

function loadTheme() {
//Add this to body onload, gets the current theme. If panelTheme is empty, defaults to blue.
if (localStorage.getItem('panelTheme') == '') {
setTheme('Blue');
} else {
setTheme(localStorage.getItem('panelTheme'));
$('#current-theme').text(localStorage.getItem('panelTheme'));
}
}

它显示了警报,但实际上并没有改变任何东西。有人能告诉我正确的方向吗?

94128 次浏览

Thank you @pvg for providing the link. I had to stare at it for a little to understand what was going on, but I finally figured it out.

The magical line I was looking for was this:

document.documentElement.style.setProperty('--your-variable', '#YOURCOLOR');

That did exactly what I wanted it to do, thank you very much!

old jquery magic still working too

$('#yourStyleTagId').html(':root {' +
'--your-var: #COLOR;' +
'}');

To use the values of custom properties in JavaScript, it is just like standard properties.

// get variable from inline style
element.style.getPropertyValue("--my-variable");


// get variable from wherever
getComputedStyle(element).getPropertyValue("--my-variable");


// set variable on inline style
element.style.setProperty("--my-variable", 4);

For those who want to modify the actual style sheet the following works:

var sheet = document.styleSheets[0];
sheet.insertRule(":root{--blue:#4444FF}");

More info at here: https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleSheet/insertRule

I came here looking how to toggle the :root color-scheme with JavaScript, which sets the browser to dark mode (including the scroll bars) like this:

:root {
color-scheme: dark;
}

using the @Daedalus answer above, this is how I implemented my dark mode detection from user preference:

    const userPrefersDarkMode = window.matchMedia('(prefers-color-scheme: dark)').matches;
const preferredTheme = userPrefersDarkMode ? 'dark' : 'light';
document.documentElement.style.setProperty("color-scheme", preferredTheme);


or with saved toggle:

    const savedTheme = localStorage.getItem('theme');
if (savedTheme == 'dark') {
thisTheme = 'light'
}
else {
thisTheme = 'dark'; // the default when never saved is dark
}
document.documentElement.style.setProperty("color-scheme", thisTheme);
localStorage.setItem('theme', thisTheme);

see also the optional meta tag in the header:

<meta name="color-scheme" content="dark light">

Read only, retrieve all CSS --root rules in an array, without using .getComputedStyle().

This may allow to retrieve values before full DOM content load, to create modules that use global root theme variables, but not via CSS. (canvas context...)

/* Retrieve all --root CSS variables
*  rules into an array
*  Without using getComputedStyle (read string only)
*  On this example only the first style-sheet
*  of the document is parsed
*/
console.log(


[...document.styleSheets[0].rules]
.map(a => a.cssText.split(" ")[0] === ":root" ?
a.cssText.split("{")[1].split("}")[0].split("--") : null)
.filter(a => a !== null)[0]
.map(a => "--"+a)
.slice(1)


)
:root {
--gold: hsl(48,100%,50%);
--gold-lighter: hsl(48,22%,30%);
--gold-darker: hsl(45,100%,47%);
--silver: hsl(210,6%,72%);
--silver-lighter: hsl(0,0%,26%);
--silver-darker: hsl(210,3%,61%);
--bronze: hsl(28,38%,67%);
--bronze-lighter: hsl(28,13%,27%);
--bronze-darker: hsl(28,31%,52%);
}

TL;DR

A solution to the problem could be the below code:

const headTag = document.getElementsByTagName('head')[0];
const styleTag = document.createElement("style");


styleTag.innerHTML = `
:root {
--main-color: #317EEB;
--hover-color: #2764BA;
--body-color: #E0E0E0;
--box-color: white;
}
`;
headTag.appendChild(styleTag);

Explanation:

Although @Daedalus answer with document.documentElement does the job pretty well, a slightly better approach is to add the styling into a <style> HTML tag (solution proposed).

If you add document.documentElement.style then all the CSS variables are added into the html tag and they are not hidden:

CSS style inline to html

On the other hand, with the proposed code:

const headTag = document.getElementsByTagName('head')[0];
const styleTag = document.createElement("style");


styleTag.innerHTML = `
:root {
--main-color: #317EEB;
--hover-color: #2764BA;
--body-color: #E0E0E0;
--box-color: white;
}
`;
headTag.appendChild(styleTag);

the HTML tag will be cleaner and if you inspect the HTML tag you can also see the :root styling as well.

HTML tag without styles

I think this is cleaner and easier to remember. to set/get css variables to/from :root

const root = document.querySelector(':root');


// set css variable
root.style.setProperty('--my-color', 'blue');


// to get css variable from :root
const color = getComputedStyle(root).getPropertyValue('--my-color'); // blue

Example: setting multiple variables all at once

const setVariables = vars => Object.entries(vars).forEach(v => root.style.setProperty(v[0], v[1]));
const myVariables = {
'--color-primary-50': '#eff6ff',
'--color-primary-100': '#dbeafe',
'--color-primary-200': '#bfdbfe',
'--color-primary-300': '#93c5fd',
'--color-primary-400': '#60a5fa',
'--color-primary-500': '#3b82f6',
'--color-primary-600': '#2563eb',
'--color-primary-700': '#1d4ed8',
'--color-primary-800': '#1e40af',
'--color-primary-900': '#1e3a8a',
};
setVariables(myVariables);
/*My style*/
:root {
--hl-color-green: green;
}


/*My update*/
* {
--hl-color-green: #0cc120;
}