- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有以下代码,我想获得元素的所需 CSS 属性(即使样式是由 js 设置的,即对于由 SPA 创建的文件,如 react),而不是计算/应用的。例如 computedStyle.width
应该有一个未定义的值。我怎样才能做到这一点?
let ele = document.querySelector(".hello");
let computedStyle = window.getComputedStyle(ele);
console.log(computedStyle.backgroundColor);
console.log(computedStyle.height);
console.log(computedStyle.width); // <- This should be undefined or ""
.hello {
height: 10px;
background-color: red;
}
<div class="hello">
helloInnerText
</div>
最佳答案
您可以通过检查所有样式表中适用于正在调查的元素的规则来做到这一点。当规则适用时,您有一个 css 属性,它是编写样式表的开发人员对该元素所需的值。
由于更具体的规则优先,因此您必须对照其他适用的规则检查每个规则的特殊性。
请注意,我不建议将其用于生产,因为它相当慢。
请参阅下面代码中的注释:
/* Say, we want to know the width, height, and background-color */
let propertiesWeWant = ['width', 'height', 'background-color', 'color', 'margin', 'font-size'];
let ele = document.querySelector(".hello");
/* First we have to prepare the stylesheets, in order to avoid CORS problems,
* since css rules of external stylesheets cannot be accessed.
* We loop through all stylesheets and inject external sheets into the head,
* so we can read them in the next step.
*/
for(let i = 0; i < document.styleSheets.length; i++){
prepareStylesheet(document.styleSheets[i]);
}
setTimeout(function(){
/* We get all the styles for this element, as found in the stylesheets. */
let givenStyles = getStylesFromStylesheets(ele);
/* And filter the results, so we only have the properties we want. */
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] = "";
}
}
/* prints all given properties.
* Object { width: "1px", height: "4px", "background-color": "pink", color: "turquoise", margin: "", "font-size": "17.5px" }
* */
console.log(propertyList);
},2000);
/* Taken from her: https://discourse.mozilla.org/t/webextensions-porting-access-to-cross-origin-document-stylesheets-cssrules/18359
* If cssRules cannot be accessed because of CORS issues:
* 1. remove the stylesheet
* 2. fetch it using its url
* 3. insert the rules in the header
*/
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;
//document.head.appendChild(style);
if(nextElement === null){
parentNode.appendChild(style);
}
else{
parentNode.insertBefore(style, nextElement);
}
});
}
}
}
/**
* Search through stylesheets for rules that apply to a given element.
* Returns object with css properties name and css property value
*/
function getStylesFromStylesheets(elementToInvestigate){
let givenStyles = {};
//alert(document.styleSheets.length);
for(let i = 0; i < document.styleSheets.length; i++){
let rules = document.styleSheets[i].cssRules;
/* Loop through every rule in the stylesheet and see wether it applies to this element */
for(let j = 0; j < rules.length; j++){
let rule = rules[j];
/* Ignore media rules. Can be added, but needs some logic that you have to write. */
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){
/* If the rule applies to this element, loop through the css properties of this css rule. */
let styles = rule.style;
for(let k = 0; k < styles.length; k++){
/* For each css property, check if it was already added earlier. */
let styleName = styles[k];
let styleValue = styles[styleName];
let newSpecificity = calculateSingle( selector);
if(typeof(givenStyles[styleName]) !== "undefined"){
/* If the property was already added, compare the specificity of the new one to the one added earlier. */
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{
/* Leave givenStyles as it was, since the former tule had higher specificity. */
}
}
else{
/* If the property was not yet seen, add it to the givenStyles. */
givenStyles[styleName] = {
style: styleValue,
specificity: newSpecificity
}
}
}
}
}
}
/* If the element has inline styles, overwrite the found properties since inline always takes precedence. */
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
}
}
}
var inlineStyles;
}
return givenStyles;
}
/* Taken from here and adjusted the output: https://raw.githubusercontent.com/keeganstreet/specificity/master/specificity.js */
/**
* Calculates the specificity of CSS selectors
* http://www.w3.org/TR/css3-selectors/#specificity
*
* Returns specificity: e.g. 0,1,0,0
*/
function calculateSingle(input) {
var selector = input,
findMatch,
typeCount = {
'a': 0,
'b': 0,
'c': 0
},
parts = [],
// The following regular expressions assume that selectors matching the preceding regular expressions have been removed
attributeRegex = /(\[[^\]]+\])/g,
idRegex = /(#[^\#\s\+>~\.\[:\)]+)/g,
classRegex = /(\.[^\s\+>~\.\[:\)]+)/g,
pseudoElementRegex = /(::[^\s\+>~\.\[:]+|:first-line|:first-letter|:before|:after)/gi,
// A regex for pseudo classes with brackets - :nth-child(), :nth-last-child(), :nth-of-type(), :nth-last-type(), :lang()
// The negation psuedo class (:not) is filtered out because specificity is calculated on its argument
// :global and :local are filtered out - they look like psuedo classes but are an identifier for CSS Modules
pseudoClassWithBracketsRegex = /(:(?!not|global|local)[\w-]+\([^\)]*\))/gi,
// A regex for other pseudo classes, which don't have brackets
pseudoClassRegex = /(:(?!not|global|local)[^\s\+>~\.\[:]+)/g,
elementRegex = /([^\s\+>~\.\[:]+)/g;
// Find matches for a regular expression in a string and push their details to parts
// Type is "a" for IDs, "b" for classes, attributes and pseudo-classes and "c" for elements and pseudo-elements
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
});
// Replace this simple selector with whitespace so it won't be counted in further simple selectors
selector = selector.replace(match, Array(length + 1).join(' '));
}
}
};
// Replace escaped characters with plain text, using the "A" character
// https://www.w3.org/TR/CSS21/syndata.html#characters
(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'));
}
}
},
// Matches a backslash followed by six hexadecimal digits followed by an optional single whitespace character
escapeHexadecimalRegex = /\\[0-9A-Fa-f]{6}\s?/g,
// Matches a backslash followed by fewer than six hexadecimal digits followed by a mandatory single whitespace character
escapeHexadecimalRegex2 = /\\[0-9A-Fa-f]{1,5}\s/g,
// Matches a backslash followed by any character
escapeSpecialCharacter = /\\./g;
replaceWithPlainText(escapeHexadecimalRegex);
replaceWithPlainText(escapeHexadecimalRegex2);
replaceWithPlainText(escapeSpecialCharacter);
}());
// Remove anything after a left brace in case a user has pasted in a rule, not just a selector
(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(' '));
}
}
}());
// Add attribute selectors to parts collection (type b)
findMatch(attributeRegex, 'b');
// Add ID selectors to parts collection (type a)
findMatch(idRegex, 'a');
// Add class selectors to parts collection (type b)
findMatch(classRegex, 'b');
// Add pseudo-element selectors to parts collection (type c)
findMatch(pseudoElementRegex, 'c');
// Add pseudo-class selectors to parts collection (type b)
findMatch(pseudoClassWithBracketsRegex, 'b');
findMatch(pseudoClassRegex, 'b');
// Remove universal selector and separator characters
selector = selector.replace(/[\*\s\+>~]/g, ' ');
// Remove any stray dots or hashes which aren't attached to words
// These may be present if the user is live-editing this selector
selector = selector.replace(/[#\.]/g, ' ');
// Remove the negation psuedo-class (:not) but leave its argument because specificity is calculated on its argument
// Remove non-standard :local and :global CSS Module identifiers because they do not effect the specificity
selector = selector.replace(/:not/g, ' ');
selector = selector.replace(/:local/g, ' ');
selector = selector.replace(/:global/g, ' ');
selector = selector.replace(/[\(\)]/g, ' ');
// The only things left should be element selectors (type c)
findMatch(elementRegex, 'c');
// Order the parts in the order they appear in the original selector
// This is neater for external apps to deal with
parts.sort(function(a, b) {
return a.index - b.index;
});
return [0, typeCount.a, typeCount.b, typeCount.c];
};
/**
* Compares two specificities
*
* - it returns false if a has a lower specificity than b
* - it returns true if a has a higher specificity than b
* - it returns true if a has the same specificity than b
*/
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;
};
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;
}
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.4.1/dist/css/bootstrap.min.css" >
<div class="hello-wrapper">
<blockquote id="hello-id" class="hello" style="width:1px; background-color: pink;">
helloInnerText
</blockquote>
</div>
关于javascript - 如何获得所需的元素样式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72718967/
我喜欢调整 目录的样式(例如背景颜色、字体)预订 , Gitbook 风格 HTML 文档。 这可能吗?如果是这样,有人可以善意地指出我可以开始这样做的地方吗? 谢谢你。 最佳答案 两个步骤: 1)
是否可以使用纯 CSS 选择器根据子节点的兄弟节点数量为节点子节点(在我的例子中为 UL)提供不同的属性,特别是高度? 例如,如果一个节点有 1 个子节点,则 UL 的高度是自动的,但是如果该节点有
我正在与 Vala 一起工作,它首先编译为 C,然后正常从 C 编译。 valac 的一项功能(Vala 编译器)是为 .vala 生成“fast-vapi”文件。 fast-vapi 本质上是为 .
我有两个具有 .body 类的 div,但是,一个位于另一个具有 .box 类的 div 中 - 如下所示: 我只想为 .box 内部的 .body 设置样式...但我在下面所
**注意所有 <> 标签已被删除以允许代码显示**我已经玩了好几个小时了,如果不在设计结束时使用解决方法(即 Corel 绘图),我就无法真正让它工作 *在我继续之前, 首先,网站 URL 是 Adv
我从一个服务中接收到一个字符串,该字符串显然使用 UTF-32 编码对其 unicode 字符进行编码,例如:\U0001B000(C 风格的 unicode 编码)。但是,为了在 JSON 中序列化
我在应用程序资源中有一种样式,我想将其应用于许多不同的饼图。样式如下所示: 为了简单起见,我排除了更多的属性。这一切都很好。现在,我的一些馅饼需要有一个不同的“模型
想象一下,我有一个名为“MyCheckBoxStyle”的 CheckBox 自定义样式。 如何制作基于 MyCheckBoxStyle 嵌入自定义 DataGridCheckBoxColumn 样式
我有一个 Button我在 WPF 中开发的样式,如 this question 中所述.我想用这种风格做的另一件事是拥有 Button缩小一点点,使其看起来像被点击一样被点击。现在,转换代码如下所示
我为超链接控件创建了一个样式:
不知道为什么,但我的 typeahead.js 远程自动完成停止工作。我没有更改任何关于 typeahead.js 的代码,但既然它坏了,我一定是错的。你能看看我的site here吗? ?我会创建
有没有办法创建扩展当前样式的样式,即不是特定样式? 我有一个 WPF 应用程序,我在其中创建样式来设置一些属性,例如边框或验证。 现在我想尝试一些主题,看看哪
我正在为一个网站提出问题,并希望 var reltext 中的正确/再试消息具有不同的颜色,即绿色表示正确,红色表示错误,并且每个旁边可能有一个小 png。 有什么想法吗? A local co
我想到达列表的父节点(使用 id 选择器)并使用纯 JavaScript 添加背景颜色来设置其样式。这是我的代码,但不起作用。 var listParentNode; listPare
关闭。此题需要details or clarity 。目前不接受答案。 想要改进这个问题吗?通过 editing this post 添加详细信息并澄清问题. 已关闭 4 年前。 Improve th
过去几天我一直在与这段代码作斗争,我真的不知道该如何处理它。 基本上,当用户将鼠标滚动到主导航菜单中的某个 LI 元素上时,就会运行一个 Javascript 函数,并根据触发该函数的元素将链接放入下
使用这个可爱的 html 和 css 作为指南,我能够在我的照片上显示我的姓名首字母。 这很好,但是,如果图像不存在,我只想显示首字母;如果图像存在,则不应渲染 peron 首字母。 换句话说,当该图
使用这个可爱的 html 和 css 作为指南,我能够在我的照片上显示我的姓名首字母。 这很好,但是,如果图像不存在,我只想显示首字母;如果图像存在,则不应渲染 peron 首字母。 换句话说,当该图
是否有人尝试过将 JButton 设计为看起来像 NetBeans 工具栏按钮?这将只显示一张图片,当您将鼠标悬停在它上面时,会显示 1px 圆形角灰色边框,并且按钮顶部和底部的背景不同......似
在 Ax2012 中使用图表,它们工作正常。但我想更改它在启动时显示的图表类型,例如“样条”图表,而不是默认的“柱状图”图表。 这是我现在拥有的: http://i.stack.imgur.com/R
我是一名优秀的程序员,十分优秀!