如何在 Javascript 中获取元素及其子元素的所有计算 css 属性
How get all computed css properties of element and its children in Javascript
我正在尝试在 python 中设置一项服务,使用 pdfKit
从 html 个文件创建一个 pdf 文件。
所以基本上我会将我的元素作为字符串发送,并期望服务器向 return 它的 pdf 版本发送,但为了准确表示,我还需要发送一个 css 文件元素.
我该怎么做?仅使用元素及其所有子元素的相关样式属性和选择器生成 JSON / 对象。尊重层次结构,不重复。有类似的问题,但它们已经过时并且往往不考虑子元素。
我在想也许有一种方法可以从这个元素创建一个新的 DOM 然后获取根 css?
这是我想出的办法,基本上是传递要提取样式的元素及其子元素,它会 return 将样式表作为字符串传递给您。在 运行 片段之前打开您的控制台,您将看到 console.log
.
的输出
因为我想支持每个元素的提取,即使是那些没有选择器的元素,我不得不用专门为它们生成的唯一 uuid 替换每个元素 id,以便于输出的样式。这种方法的问题在于,如果您使用 id 进行样式设置或用户交互,您将在调用 extractCSS
.
后在相关元素上失去此类功能
但是,一旦您的 pdfKit
进程完成生成,使用我要传递的 oldId
来更改回来是非常简单的。只需调用 swapBackIds
传递由函数编辑的 elements
return。如果取消注释我的代码片段中的调用,您可以看到行为的差异:#root
粉红色背景会消失,因为样式针对元素 id
.
总而言之,您需要:
- 用你想提取的元素调用
extractCSS
- 使用
res.stylesheet
生成您的 pdf
- 用
res.elements
调用 swapBackIds
// Generate an unique id for your element
// From
function uuidv4 () {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
}
// Flatten an array
//
function flatten(arr) {
return arr.reduce(function (flat, toFlatten) {
return flat.concat(Array.isArray(toFlatten) ? flatten(toFlatten) : toFlatten);
}, []);
}
function recursiveExtract (element) {
var id = uuidv4()
var oldId = element.id
var computed = window.getComputedStyle(element)
var style = computed.cssText
// Now that we get the style, we can swap the id
element.setAttribute('id', id)
// The children are not a real array but a NodeList, we need to convert them
// so we can map over them easily
var children = Array.prototype.slice.call(element.children)
return [{ id: id, style: style, oldId: oldId }].concat(children.map(recursiveExtract))
}
function extractCSS (element) {
if (!element) { return { elements: [], stylesheet: '' } }
var raw = recursiveExtract(element)
var flat = flatten(raw)
return {
elements: flat,
stylesheet: flat.reduce(function (acc, cur) {
var style = '#' + cur.id + ' {\n' + cur.style + '\n}\n\n'
return acc + style
}, '')
}
}
var pdfElement = document.querySelector('#root')
var res = extractCSS(pdfElement)
console.log(res.stylesheet)
function swapBackIds (elements) {
elements.forEach(function (e) {
var element = document.getElementById(e.id)
element.setAttribute('id', e.oldId)
})
}
swapBackIds(res.elements)
#root {
background-color: pink;
}
.style-from-class {
background-color: red;
width: 200px;
height: 200px;
}
.style-from-id {
background-color: green;
width: 100px;
height: 100px;
}
<div id="root">
<span>normal</span>
<span style="background: blue">inline</span>
<div class="style-from-class">
style-class
</div>
<div class="style-from-id">
style-id
<div style="font-size: 10px">a very nested</div>
<div style="font-size: 12px; color: white">and another</div>
</div>
</div>
<div id="ignored-sibling">
</div>
let para = document.querySelector('p');
let compStyles = window.getComputedStyle(para);
para.textContent = 'My computed font-size is ' + compStyles.getPropertyValue('font-size') + ',\nand my computed background is ' + compStyles.getPropertyValue('background') + '.';
p {
width: 400px;
margin: 0 auto;
padding: 20px;
font: 2rem/2 sans-serif;
text-align: center;
background: purple;
color: white;
}
<p>Hello</p>
您可以使用 getComputedStyle
方法来获取样式的计算值 属性
我正在尝试在 python 中设置一项服务,使用 pdfKit
从 html 个文件创建一个 pdf 文件。
所以基本上我会将我的元素作为字符串发送,并期望服务器向 return 它的 pdf 版本发送,但为了准确表示,我还需要发送一个 css 文件元素.
我该怎么做?仅使用元素及其所有子元素的相关样式属性和选择器生成 JSON / 对象。尊重层次结构,不重复。有类似的问题,但它们已经过时并且往往不考虑子元素。
我在想也许有一种方法可以从这个元素创建一个新的 DOM 然后获取根 css?
这是我想出的办法,基本上是传递要提取样式的元素及其子元素,它会 return 将样式表作为字符串传递给您。在 运行 片段之前打开您的控制台,您将看到 console.log
.
因为我想支持每个元素的提取,即使是那些没有选择器的元素,我不得不用专门为它们生成的唯一 uuid 替换每个元素 id,以便于输出的样式。这种方法的问题在于,如果您使用 id 进行样式设置或用户交互,您将在调用 extractCSS
.
但是,一旦您的 pdfKit
进程完成生成,使用我要传递的 oldId
来更改回来是非常简单的。只需调用 swapBackIds
传递由函数编辑的 elements
return。如果取消注释我的代码片段中的调用,您可以看到行为的差异:#root
粉红色背景会消失,因为样式针对元素 id
.
总而言之,您需要:
- 用你想提取的元素调用
extractCSS
- 使用
res.stylesheet
生成您的 pdf
- 用
res.elements
调用
swapBackIds
// Generate an unique id for your element
// From
function uuidv4 () {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
}
// Flatten an array
//
function flatten(arr) {
return arr.reduce(function (flat, toFlatten) {
return flat.concat(Array.isArray(toFlatten) ? flatten(toFlatten) : toFlatten);
}, []);
}
function recursiveExtract (element) {
var id = uuidv4()
var oldId = element.id
var computed = window.getComputedStyle(element)
var style = computed.cssText
// Now that we get the style, we can swap the id
element.setAttribute('id', id)
// The children are not a real array but a NodeList, we need to convert them
// so we can map over them easily
var children = Array.prototype.slice.call(element.children)
return [{ id: id, style: style, oldId: oldId }].concat(children.map(recursiveExtract))
}
function extractCSS (element) {
if (!element) { return { elements: [], stylesheet: '' } }
var raw = recursiveExtract(element)
var flat = flatten(raw)
return {
elements: flat,
stylesheet: flat.reduce(function (acc, cur) {
var style = '#' + cur.id + ' {\n' + cur.style + '\n}\n\n'
return acc + style
}, '')
}
}
var pdfElement = document.querySelector('#root')
var res = extractCSS(pdfElement)
console.log(res.stylesheet)
function swapBackIds (elements) {
elements.forEach(function (e) {
var element = document.getElementById(e.id)
element.setAttribute('id', e.oldId)
})
}
swapBackIds(res.elements)
#root {
background-color: pink;
}
.style-from-class {
background-color: red;
width: 200px;
height: 200px;
}
.style-from-id {
background-color: green;
width: 100px;
height: 100px;
}
<div id="root">
<span>normal</span>
<span style="background: blue">inline</span>
<div class="style-from-class">
style-class
</div>
<div class="style-from-id">
style-id
<div style="font-size: 10px">a very nested</div>
<div style="font-size: 12px; color: white">and another</div>
</div>
</div>
<div id="ignored-sibling">
</div>
let para = document.querySelector('p');
let compStyles = window.getComputedStyle(para);
para.textContent = 'My computed font-size is ' + compStyles.getPropertyValue('font-size') + ',\nand my computed background is ' + compStyles.getPropertyValue('background') + '.';
p {
width: 400px;
margin: 0 auto;
padding: 20px;
font: 2rem/2 sans-serif;
text-align: center;
background: purple;
color: white;
}
<p>Hello</p>
您可以使用 getComputedStyle
方法来获取样式的计算值 属性