首页 > 解决方案 > 如何为新样式表生成 CSS 变量值

问题描述

我正在开发一个项目,用户可以从颜色输入中选择颜色并使用 CSS 变量动态创建自己的主题。我希望用户能够使用他们选择的值下载整个 CSS 文件。

我的问题:下载的 CSS 文件不显示实际颜色值,但显示变量名称。

NOT WANTED

pre[class*="language-"] {
  background: var(--block-background);
}

代替

WANTED OUTPUT

pre[class*="language-"] {
  background: #0D2831;
}

我知道我可以通过执行以下操作来获取 CSS 属性值。

const styles = getComputedStyle(document.documentElement)
const value = String(styles.getPropertyValue('--block-background')).trim()

我想我会创建一个函数,循环遍历我的所有 CSS 变量并获取相应的属性值,然后将它们添加到新样式表中供用户下载,但我在此过程中迷路了。我目前有两个 CSS 文件,一个main.css和一个prism.css. 该main.css文件在根目录中保存页面样式和所有 CSS 变量。该prism.css文件包含我希望用户能够下载的主题。

我正在尝试找到一种方法来创建一个新样式表,该样式表包含prism.css文件中的所有内容,但具有实际的颜色十六进制代码而不是 CSS 变量名称作为给定 CSS 属性的值。

索引.js

import { colors } from './colorHelper'

const inputs = [].slice.call(document.querySelectorAll('input[type="color"]'));

const handleThemeUpdate = (colors) => {
  const root = document.querySelector(':root');
  const keys = Object.keys(colors);
  keys.forEach(key => {
    root.style.setProperty(key, colors[key]);
  });
}

inputs.forEach((input) => {
  input.addEventListener('change', (e) => {
    e.preventDefault()
    const cssPropName = `--${e.target.id}`;
    document.styleSheets[2].cssRules[3].style.setProperty(cssPropName, e.target.value)
    handleThemeUpdate({
      [cssPropName]: e.target.value
    });
    console.log(`${cssPropName} is now ${e.target.value}`)
  });
});


const cssRules = document.styleSheets[2].cssRules;
for (var i = 0; i < cssRules.length; i++) {
  // Finds css variable names
  const regexp = /(?:var\(--)[a-zA-z\-]*(?:\))/

  let cssVariables = cssRules[i].cssText.matchAll(regexp)
  cssVariables = Array.from(cssVariables).join()

  console.log(cssVariables)
}

colorHelper.js

const colorSelect = {
  'Line Highlights': {
    'highlight-background': '#F7EBC6',
    'highlight-accent': '#F7D87C'
  },
  'Inline Code': {
    'inline-code-color': '#DB4C69',
    'inline-code-background': '#F9F2F4'
  },
  'Code Blocks': {
    'block-background': '#0D2831',
    'base-color': '#5C6E74',
    'selected-color': '#b3d4fc'
  },
  'Tokens': {
    'comment-color': '#93A1A1',
    'punctuation-color': '#999999',
    'property-color': '#990055',
    'selector-color': '#669900',
    'operator-color': '#a67f59',
    'operator-background': '#FFFFFF',
    'variable-color': '#ee9900',
    'function-color': '#DD4A68',
    'keyword-color': '#0077aa'
  }
}

const colorNames = []
const colors = {}

Object.keys(colorSelect).map(key => {
  const group = colorSelect[key]
  Object.keys(group).map(color => {
    colorNames.push(color)
    colors[color] = group[color]
  })
})

export { colorSelect, colorNames, colors }

棱镜.css

pre[class*="language-"],
code[class*="language-"] {
  color: var(--base-color);
  font-size: 13px;
  text-shadow: none;
  font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
  direction: ltr;
  text-align: left;
  white-space: pre;
  word-spacing: normal;
  word-break: normal;
  line-height: 1.5;
  -moz-tab-size: 4;
  -o-tab-size: 4;
  tab-size: 4;
  -webkit-hyphens: none;
  -moz-hyphens: none;
  -ms-hyphens: none;
  hyphens: none;
}
pre[class*="language-"]::selection,
code[class*="language-"]::selection,
pre[class*="language-"]::mozselection,
code[class*="language-"]::mozselection {
  text-shadow: none;
  background: var(--selected-color);
}

@media print {
  pre[class*="language-"],
  code[class*="language-"] {
    text-shadow: none;
  }
}

pre[class*="language-"] {
  padding: 1em;
  margin: .5em 0;
  overflow: auto;
  background: var(--block-background);
}
:not(pre) > code[class*="language-"] {
  padding: .1em .3em;
  border-radius: .3em;
  color: var(--inline-code-color);
  background: var(--inline-code-background);
}

/* Tokens */

.namespace {
  opacity: .7;
}
.token.comment,
.token.prolog,
.token.doctype,
.token.cdata {
  color: var(--comment-color);
}
.token.punctuation {
  color: var(--punctuation-color);
}
.token.property,
.token.tag,
.token.boolean,
.token.number,
.token.constant,
.token.symbol,
.token.deleted {
  color: var(--property-color);
}
.token.selector,
.token.attr-name,
.token.string,
.token.char,
.token.builtin,
.token.inserted {
  color: var(--selector-color);
}
.token.operator,
.token.entity,
.token.url,
.language-css .token.string,
.style .token.string {
  color: var(--operator-color);
  background: var(--operator-background);
}
.token.atrule,
.token.attr-value,
.token.keyword {
  color: var(--keyword-color);
}
.token.function {
  color: var(--function-color);
}
.token.regex,
.token.important,
.token.variable {
  color: var(--variable-color);
}
.token.important,
.token.bold {
  font-weight: bold;
}
.token.italic {
  font-style: italic;
}
.token.entity {
  cursor: help;
}

/* Line highlighting */

pre[data-line] {
  position: relative;
}
pre[class*="language-"] > code[class*="language-"] {
  position: relative;
  z-index: 1;
}
.line-highlight {
  position: absolute;
  left: 0;
  right: 0;
  padding: inherit 0;
  margin-top: 1em;
  background: var(--highlight-background);
  box-shadow: inset 5px 0 0 var(--highlight-accent);
  z-index: 0;
  pointer-events: none;
  line-height: inherit;
  white-space: pre;
}

我有三个样式表。

style.css将 CSS 变量保存在根目录中

normalize.css

prism.css包含语法高亮的样式。这是我希望用户下载的样式表,但我想为他们提供每个变量的实际十六进制值,而不是 CSS 属性的变量名称。

我的 HTML 中的样式表顺序

 <link rel="stylesheet" type="text/css" href="./style.css">
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/8.0.1/normalize.css"
    integrity="sha256-WAgYcAck1C1/zEl5sBl5cfyhxtLgKGdpI3oKyJffVRI=" crossorigin="anonymous" />
  <link href="./themes/prism.css" rel="stylesheet" />

编辑

我试图遍历样式表并获取 CSS 变量名称,但其中一些返回为空字符串。

这就是我所做的

const cssRules = document.styleSheets[2].cssRules;
for (var i = 0; i < cssRules.length; i++) {
  const regexp = /(?:var\(--)[a-zA-z\-]*(?:\))/

  let cssVariables = cssRules[i].cssText.matchAll(regexp)
  cssVariables = Array.from(cssVariables)

  console.log(cssVariables)
} 

这是控制台中的结果

var(--base-color) 
var(--selected-color) 
<empty string>
var(--block-background)
var(--inline-code-color)
<empty string>
var(--comment-color)
var(--punctuation-color)
var(--property-color) 
var(--selector-color)
var(--operator-color)
var(--keyword-color) 
var(--function-color)
var(--variable-color) 
<empty string> 
var(--highlight-background)

然后我试图在.replace()之后进行链接,trim()但这似乎也不起作用。

标签: javascriptcss

解决方案


您可以将文件下载为文本,然后查找并替换变量。

例如:

var s = `pre[class*="language-"] {
  background: var(--block-background);
}`

const variables = {"block-background":"#0D2831"};

Object.keys(variables).forEach(key => {
  s = s.replace("var(--"+key+")", variables[key]); 
});

console.log(s);


推荐阅读