【问题标题】:Get all css root variables in array using javascript and change the values使用javascript获取数组中的所有css根变量并更改值
【发布时间】:2018-07-23 10:30:05
【问题描述】:

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

我的 CSS 看起来像

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

在css中使用

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

我可以如下访问javascript中的变量以动态更改值

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

它工作正常。我想获取数组中的所有变量,并据此动态更改每个变量的值。

【问题讨论】:

    标签: javascript jquery css css-selectors css-variables


    【解决方案1】:

    这是另一个打字稿,我继续 RLoniello 提到的工作。它还将其输出为 JS 对象,即将 --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);
    };

    【讨论】:

      【解决方案2】:

      此脚本将返回所有样式表中的根变量数组,由域提供。由于 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 规则。

      【讨论】:

        【解决方案3】:

        我今天需要一个类似的解决方案。这是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));
        

        【讨论】:

          【解决方案4】:

          如果您知道您的所有变量都将放在 :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)
          }
          &lt;p&gt;Some text&lt;/p&gt;

          【讨论】:

          • 有趣的解决方案,很干净,我考虑过使用.cssRules[0],但我发现只读取了第一个:root元素。如果您有多个来自不同来源的文件,比如本地和 CDN,则只会读取第一个。
          • @RLoniello 是的,您可能会注意到我使用了0 索引,如果您按照它们进行操作,您会看到我采用了第一个 CSS 文件和该 CSS 文件中的第一条规则......所以你可以对另一个做同样的事情,你唯一需要知道的是顺序和索引......这是一个小缺点:)但是如果你知道你的 CSS 文件就不会成为问题;)
          • @RLoniello 使用console.log 和document.styleSheets 看看里面有什么,你就会明白;)
          • 是的,我明白了 :) 请注意 CDN 样式表的加载顺序。 :P
          • @RLoniello 是的,如果你很容易得到订单......但如果不是你可以使代码更复杂,你可以循环遍历所有样式以获取变量..所以几乎相同的事情我已经完成了,但是所有的样式.. 你只需要添加一个if else 来检查样式是否是一个变量(它应该以-- 开头)
          【解决方案5】:

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

          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...
                      }
                    }
          

          【讨论】:

          • 假设我在 css 中有 200 个变量,所以我必须写这一行 var primaryColor = document.documentElement.style.getPropertyValue('--primaryColor'); 200 次。我想要动态的。
          猜你喜欢
          • 1970-01-01
          • 2015-10-11
          • 2012-09-17
          • 1970-01-01
          • 2011-10-29
          • 1970-01-01
          • 2011-08-25
          • 2021-05-06
          • 1970-01-01
          相关资源
          最近更新 更多