jquery 使用JavaScript获取数组中的所有CSS根变量并更改值

68de4m5k  于 2023-06-22  发布在  jQuery
关注(0)|答案(7)|浏览(141)

我在我的项目中使用css根变量来随时动态更改所有元素的颜色。
我的css看起来像

:root{
  --primaryColor:aliceblue;
  --secondaryColor:blue;
  --errorColor:#cc2511;
}

使用CSS

.contentCss {
  background-color: var(--primaryColor);
}

我可以访问JavaScript中的变量,如下所示,以动态更改值

document.documentElement.style.setProperty('--primaryColor', 'green');

它工作正常。我想得到一个数组中的所有变量,并根据它动态地改变每个变量的值。

eqqqjvef

eqqqjvef1#

这个脚本将返回所有样式表中的根变量数组,从域中提供。由于CORS策略,域外的样式表不可访问。

Array.from(document.styleSheets)
  .filter(
    sheet =>
      sheet.href === null || sheet.href.startsWith(window.location.origin)
  )
  .reduce(
    (acc, sheet) =>
      (acc = [
        ...acc,
        ...Array.from(sheet.cssRules).reduce(
          (def, rule) =>
            (def =
              rule.selectorText === ":root"
                ? [
                    ...def,
                    ...Array.from(rule.style).filter(name =>
                      name.startsWith("--")
                    )
                  ]
                : def),
          []
        )
      ]),
    []
  );

注意:低阶样式表中的root:规则将覆盖父root规则。

brc7rcf0

brc7rcf02#

你可以用键声明一个关联数组作为节点属性,然后使用一个函数来设置你的主题:

var primaryColor = document.documentElement.style.getPropertyValue('--primaryColor');
var secondaryColor = document.documentElement.style.getPropertyValue('--secondaryColor');
var errorColor = document.documentElement.style.getPropertyValue('--errorColor');

var themeColors = {}
themeColors["--primaryColor"] = primaryColor;
themeColors["--secondaryColor"] = secondaryColor;
themeColors["--errorColor"] = errorColor;

function setTheme(theme) {
     for (key in theme) {
        let color = theme[key];
        document.documentElement.style.setProperty(key, color);
   }
 }

我使用Atom和Bootstrap的一个工作示例:

var backgroundColor = document.documentElement.style.getPropertyValue('--blue');
        backgroundColor = "#dc3545";

        function setTheme(theme) {
          for (key in theme) {
            let color = theme[key];
            document.documentElement.style.setProperty(key, color);
          }
        }

        var theme = {}
        theme["--blue"] = backgroundColor;

        setTheme(theme);

>>编辑<<

Nadeem在下面的评论中更好地澄清了这个问题,不幸的是,我已经了解到:root可以通过get Window.getComputedStyle()访问,但这不会返回CSS变量声明。
解决这个问题的方法是读取css文件,解析它的变量并将它们填充到一个关联数组中,但即使这样也假设您知道从哪里获得该css文件...

//an associative array that will hold our values
        var cssVars = {};

        var request = new XMLHttpRequest();
        request.open('GET', './css/style.css', true);

        request.onload = function() {
          if (request.status >= 200 && request.status < 400) {
              //Get all CSS Variables in the document
              var matches = request.responseText.match(/(--)\w.+;/gi);

              //Get all CSS Variables in the document
              for(let match in matches) {
                  var property = matches[match];
                  //split the Variable name from its value
                  let splitprop = property.split(":")

                  //turn the value into a string
                  let value = splitprop[1].toString()

                  cssVars[splitprop[0]] = value.slice(0, -1); //remove ;
              }

              // console.log(cssVars);
              // > Object {--primaryColor: "aliceblue", --secondaryColor: "blue", --errorColor: "#cc2511"}

              // console.log(Object.keys(cssVars));
              // > ["--primaryColor", "--secondaryColor", "--errorColor" ]

              setTheme(cssVars)

            } else {
              // We reached our target server, but it returned an error
            }
          };

          request.onerror = function() {
            console.log("There was a connection error");
          };

          request.send();


          function setTheme(theme) {
            var keys = Object.keys(theme)

            for (key in keys) {
              let prop = keys[key]
              let color = theme[keys[key]];

              console.log(prop, color);
              // --primaryColor aliceblue etc...
            }
          }
stszievb

stszievb3#

我今天需要一个类似的解决方案。这里有一个quick one on codepen

// could pass in an array of specific stylesheets for optimization
function getAllCSSVariableNames(styleSheets = document.styleSheets){
   var cssVars = [];
   // loop each stylesheet
   for(var i = 0; i < styleSheets.length; i++){
      // loop stylesheet's cssRules
      try{ // try/catch used because 'hasOwnProperty' doesn't work
         for( var j = 0; j < styleSheets[i].cssRules.length; j++){
            try{
               // loop stylesheet's cssRules' style (property names)
               for(var k = 0; k < styleSheets[i].cssRules[j].style.length; k++){
                  let name = styleSheets[i].cssRules[j].style[k];
                  // test name for css variable signiture and uniqueness
                  if(name.startsWith('--') && cssVars.indexOf(name) == -1){
                     cssVars.push(name);
                  }
               }
            } catch (error) {}
         }
      } catch (error) {}
   }
   return cssVars;
}

function getElementCSSVariables (allCSSVars, element = document.body, pseudo){
   var elStyles = window.getComputedStyle(element, pseudo);
   var cssVars = {};
   for(var i = 0; i < allCSSVars.length; i++){
      let key = allCSSVars[i];
      let value = elStyles.getPropertyValue(key)
      if(value){cssVars[key] = value;}
   }
   return cssVars;
}

var cssVars = getAllCSSVariableNames();
console.log(':root variables', getElementCSSVariables(cssVars, document.documentElement));
yv5phkfx

yv5phkfx4#

如果你知道你所有的变量都将被放在:root中,并且它是你第一个CSS文件中的第一个声明,你可以尝试这样做,你会得到一个Object中的所有变量:

var declaration = document.styleSheets[0].cssRules[0];
var allVar = declaration.style.cssText.split(";");

var result = {}
for (var i = 0; i < allVar.length; i++) {
  var a = allVar[i].split(':');
  if (a[0] !== "")
    result[a[0].trim()] = a[1].trim();
}

console.log(result);
var keys = Object.keys(result);
console.log(keys);

//we change the first variable
document.documentElement.style.setProperty(keys[0], 'green');

//we change the variable  --secondary-color
document.documentElement.style.setProperty(keys[keys.indexOf("--secondary-color")], 'red');
:root {
  --primary-color: aliceblue;
  --secondary-color: blue;
  --error-color: #cc2511
}

p {
  font-size: 25px;
  color: var(--primary-color);
  border:1px solid var(--secondary-color)
}
<p>Some text</p>
jogvjijk

jogvjijk5#

这是另一个 typescript ,我继续RLoniello提到的工作。它还将其输出为JS对象,即converts --font-family:“Verdana”到fontFamily:Verdana.

const CssKeyToJsKey = (key: string) =>
    key.replace('--', '').replace(/-./g, (x) => x.toUpperCase()[1]);

const getAllCSSVariableNames = (styleSheets: StyleSheetList = document.styleSheets) => {
    const cssVars = [];

    Array.from(styleSheets).forEach((styleSheet) => {
        Array.from(styleSheet.cssRules).forEach((rule) => {
            if (!rule || !rule['style']) {
                return;
            }

            Array.from(rule['style']).forEach((style: string) => {
                if (style.startsWith('--') && cssVars.indexOf(style) == -1) {
                    cssVars.push(style);
                }
            });
        });
    });

    return cssVars;
};

const getElementCSSVariables = (
    allCSSVars: Array<string>,
    element: HTMLElement = document.body,
    pseudo: string | undefined = ''
) => {
    const elStyles = window.getComputedStyle(element, pseudo);
    const cssVars = {};

    allCSSVars.forEach((key) => {
        const value = elStyles.getPropertyValue(key);

        if (value) {
            cssVars[CssKeyToJsKey(key)] = value;
        }
    });

    return cssVars;
};

export const getAllCSSVariables = (): Record<string, string> => {
    const cssVars = getAllCSSVariableNames();

    return getElementCSSVariables(cssVars, document.documentElement);
};
mxg2im7a

mxg2im7a6#

不使用.getComputedStyle()Map到命名对象

/* Retrieve all --root CSS variables
*  rules into a named Object
*  Without using getComputedStyle (read string only)
*/
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.split(": "))
   .filter(a => a[0] !== " ")
   .reduce((a, v) => ({ ...a, [v[0].slice(1)] : v[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%);
}
hgc7kmma

hgc7kmma7#

这里有一个函数式方法来获取所有:root CSS变量,如果你使用更严格的TypeScript配置,这些变量不会抛出类型错误:

const rootCssVariables: string[] = Array.from(document.styleSheets)
  .flatMap((styleSheet: CSSStyleSheet) => Array.from(styleSheet.cssRules))
  .filter(
    (cssRule: CSSRule): cssRule is CSSStyleRule =>
      cssRule instanceof CSSStyleRule && cssRule.selectorText === ':root',
  )
  .flatMap((cssRule: CSSStyleRule) => Array.from(cssRule.style))
  .filter((style: string) => style.startsWith('--'))

console.log(rootCssVariables)
// e.g. ['--background-color', '--text-color', etc...]

相关问题