如何在css中用postcss附加属性



我有以下css:

a, a::after, p + .selector, .selector > .my-selector, .selector::before {
}

我想将[data-123]附加到所有选择器。所以类似于:

a[data-123], a::after[data-123], p[data-123] + .selector[data-123], .selector[data-123] > .my-selector[data-123], .selector::before[data-123] {
}

我如何使用postpass做到这一点,或者有其他方法在运行时实现结果吗?

Vue就是这样做的:

  • 创建一个util文件:
//css-parser.js
import { Root } from "postcss"
import * as postcss from "postcss"
// postcss-selector-parser does have typings but it's problematic to work with.
const selectorParser = require("postcss-selector-parser")
export default postcss.plugin("add-id", options => root => {
const id = options
const keyframes = Object.create(null)
root.each(function rewriteSelector(node) {
if (!node.selector) {
// handle media queries
if (node.type === "atrule") {
if (node.name === "media" || node.name === "supports") {
node.each(rewriteSelector)
} else if (/-?keyframes$/.test(node.name)) {
// register keyframes
keyframes[node.params] = node.params =
node.params + "-" + id
}
}
return
}
node.selector = selectorParser(selectors => {
selectors.each(selector => {
let node = null
// find the last child node to insert attribute selector
selector.each(n => {
// ">>>" combinator
// and /deep/ alias for >>>, since >>> doesn't work in SASS
if (
n.type === "combinator" &&
(n.value === ">>>" || n.value === "/deep/")
) {
n.value = " "
n.spaces.before = n.spaces.after = ""
return false
}
// in newer versions of sass, /deep/ support is also dropped, so add a ::v-deep alias
if (n.type === "pseudo" && n.value === "::v-deep") {
n.value = n.spaces.before = n.spaces.after = ""
return false
}
if (n.type !== "pseudo" && n.type !== "combinator") {
node = n
}
})
if (node) {
node.spaces.after = ""
} else {
// For deep selectors & standalone pseudo selectors,
// the attribute selectors are prepended rather than appended.
// So all leading spaces must be eliminated to avoid problems.
selector.first.spaces.before = ""
}
selector.insertAfter(
node,
selectorParser.attribute({
attribute: id
})
)
})
}).processSync(node.selector)
})
// If keyframes are found in this <style>, find and rewrite animation names
// in declarations.
// Caveat: this only works for keyframes and animation rules in the same
// <style> element.
if (Object.keys(keyframes).length) {
root.walkDecls(decl => {
// individual animation-name declaration
if (/^(-w+-)?animation-name$/.test(decl.prop)) {
decl.value = decl.value
.split(",")
.map(v => keyframes[v.trim()] || v.trim())
.join(",")
}
// shorthand
if (/^(-w+-)?animation$/.test(decl.prop)) {
decl.value = decl.value
.split(",")
.map(v => {
const vals = v.trim().split(/s+/)
const i = vals.findIndex(val => keyframes[val])
if (i !== -1) {
vals.splice(i, 1, keyframes[vals[i]])
return vals.join(" ")
} else {
return v
}
})
.join(",")
}
})
}
})
  • 然后将其用作:
import hashsum from "hash-sum"
import cssParser from "@/utils/css-parser"
const uniqueHash = "data-e-" + hashsum("my-random-hash")
const processCss = (css, hash) => {
const plugins = [cssParser(hash || uniqueHash)]
const result = postcss(plugins).process(css)
return result.css
}

它工作得很好。

最新更新