
获取元素样式: 遍历样式表,找到适用于目标元素的规则,并提取样式属性。
function getStylesFromStylesheets(elementToInvestigate) {
let givenStyles = {};
for (let i = 0; i < document.styleSheets.length; i++) {
let rules = document.styleSheets[i].cssRules;
for (let j = 0; j < rules.length; j++) {
let rule = rules[j];
if (typeof(rule.selectorText) === "undefined") {
continue;
}
let split = rule.selectorText.split(",");
for(let l = 0; l < split.length; l++){
let selector = split[l];
let elements = document.querySelectorAll(selector);
let applies = false;
for (let k = 0; k < elements.length; k++) {
if (elements[k] === elementToInvestigate) {
applies = true;
break;
}
}
if (applies === true) {
let styles = rule.style;
for (let k = 0; k < styles.length; k++) {
let styleName = styles[k];
let styleValue = styles[styleName];
let newSpecificity = calculateSingle( selector);
if (typeof(givenStyles[styleName]) !== "undefined") {
let earlierSelector = givenStyles[styleName].selector;
let earlierSpecificity = givenStyles[styleName].specificity;
let newHasMoreSpecificity = compareSpecifities( newSpecificity, earlierSpecificity);
if (newHasMoreSpecificity === true) {
givenStyles[styleName] = {
style: styleValue,
specificity: newSpecificity
}
}
} else {
givenStyles[styleName] = {
style: styleValue,
specificity: newSpecificity
}
}
}
}
}
}
if (elementToInvestigate.style.length > 0) {
for (let j = 0; j < elementToInvestigate.style.length; j++) {
let styleName = elementToInvestigate.style[j];
let styleValue = elementToInvestigate.style[styleName];
givenStyles[styleName] = {
style: styleValue,
specificity: [1, 1, 1, 1] //not needed here
}
}
}
}
return givenStyles;
}计算 CSS 选择器优先级: 使用 calculateSingle 函数计算 CSS 选择器的优先级。该函数基于 CSS 规范,将选择器优先级表示为一个四元组 [a, b, c, d],其中 a 代表 ID 选择器的数量,b 代表类选择器、属性选择器和伪类选择器的数量,c 代表元素选择器和伪元素选择器的数量。
function calculateSingle(input) {
var selector = input,
findMatch,
typeCount = {
'a': 0,
'b': 0,
'c': 0
},
parts = [],
attributeRegex = /([[^]]+])/g,
idRegex = /(#[^#s+>~.[:)]+)/g,
classRegex = /(.[^s+>~.[:)]+)/g,
pseudoElementRegex = /(::[^s+>~.[:]+|:first-line|:first-letter|:before|:after)/gi,
pseudoClassWithBracketsRegex = /(:(?!not|global|local)[w-]+([^)]*))/gi,
pseudoClassRegex = /(:(?!not|global|local)[^s+>~.[:]+)/g,
elementRegex = /([^s+>~.[:]+)/g;
findMatch = function(regex, type) {
var matches, i, len, match, index, length;
if (regex.test(selector)) {
matches = selector.match(regex);
for (i = 0, len = matches.length; i < len; i += 1) {
typeCount[type] += 1;
match = matches[i];
index = selector.indexOf(match);
length = match.length;
parts.push({
selector: input.substr(index, length),
type: type,
index: index,
length: length
});
selector = selector.replace(match, Array(length + 1).join(' '));
}
}
};
(function() {
var replaceWithPlainText = function(regex) {
var matches, i, len, match;
if (regex.test(selector)) {
matches = selector.match(regex);
for (i = 0, len = matches.length; i < len; i += 1) {
match = matches[i];
selector = selector.replace(match, Array(match.length + 1).join('A'));
}
}
},
escapeHexadecimalRegex = /\[0-9A-Fa-f]{6}s?/g,
escapeHexadecimalRegex2 = /\[0-9A-Fa-f]{1,5}s/g,
escapeSpecialCharacter = /\./g;
replaceWithPlainText(escapeHexadecimalRegex);
replaceWithPlainText(escapeHexadecimalRegex2);
replaceWithPlainText(escapeSpecialCharacter);
}());
(function() {
var regex = /{[^]*/gm,
matches, i, len, match;
if (regex.test(selector)) {
matches = selector.match(regex);
for (i = 0, len = matches.length; i < len; i += 1) {
match = matches[i];
selector = selector.replace(match, Array(match.length + 1).join(' '));
}
}
}());
findMatch(attributeRegex, 'b');
findMatch(idRegex, 'a');
findMatch(classRegex, 'b');
findMatch(pseudoElementRegex, 'c');
findMatch(pseudoClassWithBracketsRegex, 'b');
findMatch(pseudoClassRegex, 'b');
selector = selector.replace(/[*s+>~]/g, ' ');
selector = selector.replace(/[#.]/g, ' ');
selector = selector.replace(/:not/g, ' ');
selector = selector.replace(/:local/g, ' ');
selector = selector.replace(/:global/g, ' ');
selector = selector.replace(/[()]/g, ' ');
findMatch(elementRegex, 'c');
parts.sort(function(a, b) {
return a.index - b.index;
});
return [0, typeCount.a, typeCount.b, typeCount.c];
};比较优先级: 使用 compareSpecifities 函数比较两个 CSS 选择器的优先级。
function compareSpecifities(aSpecificity, bSpecificity) {
for (var i = 0; i < 4; i += 1) {
if (aSpecificity[i] < bSpecificity[i]) {
return false;
} else if (aSpecificity[i] > bSpecificity[i]) {
return true;
}
}
return true;
};获取期望样式: 遍历完成后,givenStyles 对象将包含目标元素的期望样式。
let propertiesWeWant = ['width', 'height', 'background-color', 'color', 'margin', 'font-size'];
let ele = document.querySelector(".hello");
let givenStyles = getStylesFromStylesheets(ele);
let propertyList = {};
for(let i = 0; i < propertiesWeWant.length; i++){
let property = propertiesWeWant[i];
if(typeof(givenStyles[property]) !== "undefined"){
propertyList[property] = givenStyles[property].style;
}
else{
propertyList[property] = "";
}
}
console.log(propertyList);<!DOCTYPE html>
<html>
<head>
<title>获取元素期望样式</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/<a class="__cf_email__" data-cfemail="96f4f9f9e2e5e2e4f7e6d6a5b8a2b8a7" href="/cdn-cgi/l/email-protection">[email protected]</a>/dist/css/bootstrap.min.css" >
<style>
blockquote{
margin:7px;
border-left: 10000px;
}
#hello-id.hello{
height: 1px;
}
#hello-id{
height: 2px;
}
html #hello-id{
height: 3px;
color: green;
}
#hello-id.hello{
height: 4px;
color: turquoise;
}
.hello-wrapper .hello {
height: 5px;
background-color: blue;
}
.hello {
height: 5px;
background-color: red;
}
#bogus.bogus{
height: 6px;
background-color: orange;
}
</style>
</head>
<body>
<div class="hello-wrapper">
<blockquote id="hello-id" class="hello" style="width:1px; background-color: pink;">
helloInnerText
</blockquote>
</div>
<script>
let propertiesWeWant = ['width', 'height', 'background-color', 'color', 'margin', 'font-size'];
let ele = document.querySelector(".hello");
for(let i = 0; i < document.styleSheets.length; i++){
prepareStylesheet(document.styleSheets[i]);
}
setTimeout(function(){
let givenStyles = getStylesFromStylesheets(ele);
let propertyList = {};
for(let i = 0; i < propertiesWeWant.length; i++){
let property = propertiesWeWant[i];
if(typeof(givenStyles[property]) !== "undefined"){
propertyList[property] = givenStyles[property].style;
}
else{
propertyList[property] = "";
}
}
console.log(propertyList);
},2000);
function prepareStylesheet(sheet){
try {
sheet.cssRules;
} catch (e) {
if (e.name === 'SecurityError') {
let nextElement = sheet.ownerNode.nextSibling;
let parentNode = sheet.ownerNode.parentNode;
sheet.ownerNode.parentNode.removeChild(sheet.ownerNode);
fetch(sheet.href).then(resp => resp.text()).then(css => {
let style = document.createElement('style');
style.innerText = css;
if(nextElement === null){
parentNode.appendChild(style);
}
else{
parentNode.insertBefore(style, nextElement);
}
});
}
}
}
function getStylesFromStylesheets(elementToInvestigate) {
let givenStyles = {};
for (let i = 0; i < document.styleSheets.length; i++) {
let rules = document.styleSheets[i].cssRules;
for (let j = 0; j < rules.length; j++) {
let rule = rules[j];
if (typeof(rule.selectorText) === "undefined") {
continue;
}
let split = rule.selectorText.split(",");
for(let l = 0; l < split.length; l++){
let selector = split[l];
let elements = document.querySelectorAll(selector);
let applies = false;
for (let k = 0; k < elements.length; k++) {
if (elements[k] === elementToInvestigate) {
applies = true;
break;
}
}
if (applies === true) {
let styles = rule.style;
for (let k = 0; k < styles.length; k++) {
let styleName = styles[k];
let styleValue = styles[styleName];
let newSpecificity = calculateSingle( selector);
if (typeof(givenStyles[styleName]) !== "undefined") {
let earlierSelector = givenStyles[styleName].selector;
let earlierSpecificity = givenStyles[styleName].specificity;
let newHasMoreSpecificity = compareSpecifities( newSpecificity, earlierSpecificity);
if (newHasMoreSpecificity === true) {
givenStyles[styleName] = {
style: styleValue,
specificity: newSpecificity
}
}
} else {
givenStyles[styleName] = {
style: styleValue,
specificity: newSpecificity
}
}
}
}
}
}
if (elementToInvestigate.style.length > 0) {
for (let j = 0; j < elementToInvestigate.style.length; j++) {
let styleName = elementToInvestigate.style[j];
let styleValue = elementToInvestigate.style[styleName];
givenStyles[styleName] = {
style: styleValue,
specificity: [1, 1, 1, 1] //not needed here
}
}
}
}
return givenStyles;
}
function calculateSingle(input) {
var selector = input,
findMatch,
typeCount = {
'a': 0,
'b': 0,
'c': 0
},
parts = [],
attributeRegex = /([[^]]+])/g,
idRegex = /(#[^#s+>~.[:)]+)/g,
classRegex = /(.[^s+>~.[:)]+)/g,
pseudoElementRegex = /(::[^s+>~.[:]+|:first-line|:first-letter|:before|:after)/gi,
pseudoClassWithBracketsRegex = /(:(?!not|global|local)[w-]+([^)]*))/gi,
pseudoClassRegex = /(:(?!not|global|local)[^s+>~.[:]+)/g,
elementRegex = /([^s+>~.[:]+)/g;
findMatch = function(regex, type) {
var matches, i, len, match, index, length;
if (regex.test(selector)) {
matches = selector.match(regex);
for (i = 0, len = matches.length; i < len; i += 1) {
typeCount[type] += 1;
match = matches[i];
index = selector.indexOf(match);
length = match.length;
parts.push({
selector: input.substr(index, length),
type: type,
index: index,
length: length
});
selector = selector.replace(match, Array(length + 1).join(' '));
}
}
};
(function() {
var replaceWithPlainText = function(regex) {
var matches, i, len, match;
if (regex.test(selector)) {
matches = selector.match(regex);
for (i = 0, len = matches.length; i < len; i += 1) {
match = matches[i];
selector = selector.replace(match, Array(match.length + 1).join('A'));
}
}
},
escapeHexadecimalRegex = /\[0-9A-Fa-f]{6}s?/g,
escapeHexadecimalRegex2 = /\[0-9A-Fa-f]{1,5}s/g,
escapeSpecialCharacter = /\./g;
replaceWithPlainText(escapeHexadecimalRegex);
replaceWithPlainText(escapeHexadecimalRegex2);
replaceWithPlainText(escapeSpecialCharacter);
}());
(function() {
var regex = /{[^]*/gm,
matches, i, len, match;
if (regex.test(selector)) {
matches = selector.match(regex);
for (i = 0, len = matches.length; i < len; i += 1) {
match = matches[i];
selector = selector.replace(match, Array(match.length + 1).join(' '));
}
}
}());
findMatch(attributeRegex, 'b');
findMatch(idRegex, 'a');
findMatch(classRegex, 'b');
findMatch(pseudoElementRegex, 'c');
findMatch(pseudoClassWithBracketsRegex, 'b');
findMatch(pseudoClassRegex, 'b');
selector = selector.replace(/[*s+>~]/g, ' ');
selector = selector.replace(/[#.]/g, ' ');
selector = selector.replace(/:not/g, ' ');
selector = selector.replace(/:local/g, ' ');
selector = selector.replace(/:global/g, ' ');
selector = selector.replace(/[()]/g, ' ');
findMatch(elementRegex, 'c');
parts.sort(function(a, b) {
return a.index - b.index;
});
return [0, typeCount.a, typeCount.b, typeCount.c];
};
function compareSpecifities(aSpecificity, bSpecificity) {
for (var i = 0; i < 4; i += 1) {
if (aSpecificity[i] < bSpecificity[i]) {
return false;
} else if (aSpecificity[i] > bSpecificity[i]) {
return true;
}
}
return true;
};
</script>
</body>
</html>本教程介绍了一种获取元素期望 CSS 样式的方法,通过遍历样式表并结合 CSS 选择器优先级,可以提取开发者在样式表或内联样式中定义的原始样式。虽然该方法存在性能问题,但在某些特定场景下,例如需要分析元素样式来源或进行样式调试时,仍然具有一定的价值。 在实际应用中,需要根据具体情况权衡性能和准确性,选择合适的方案。
以上就是获取元素期望样式的教程的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号