<div class="box" style="border: solid 1px red !important;">
会为所有border缩写相关的属性返回important
// These all return "important"
box.style.getPropertyPriority('border'));
box.style.getPropertyPriority('border-top-width'));
box.style.getPropertyPriority('border-bottom-width'));
box.style.getPropertyPriority('border-color'));
box.style.getPropertyPriority('border-style'));
let myRules = document.styleSheets[0].cssRules,
p = document.querySelector('p');
for (i of myRules) {
if (i.type === 1) {
p.innerHTML += `<code>${i.selectorText}</code><br>`;
}
}
let myRules = document.styleSheets[0].cssRules,
p = document.querySelector('.output');
for (i of myRules) {
if (i.type === 7) {
for (j of i.cssRules) {
p.innerHTML += `<code>${j.keyText}</code><br>`;
}
}
}
let myRules = document.styleSheets[0].cssRules,
p = document.querySelector('.output');
for (i of myRules) {
if (i.type === 4) {
p.innerHTML += `<code>${i.conditionText}</code><br>`;
// (max-width: 800px)
}
}
let myRules = document.styleSheets[0].cssRules,
p = document.querySelector('.output');
for (i of myRules) {
if (i.type === 7) {
for (j of i.cssRules) {
p.innerHTML += `<code>${j.keyText}</code><br>`;
}
}
}
// Read the current value (0%)
document.styleSheets[0].cssRules[6].cssRules[0].keyText;
// Change the value to 10%
document.styleSheets[0].cssRules[6].cssRules[0].keyText = '10%'
// Read the new value (10%)
document.styleSheets[0].cssRules[6].cssRules[0].keyText;
还可以查到keyframe的name:
let myRules = document.styleSheets[0].cssRules,
p = document.querySelector('.output');
for (i of myRules) {
if (i.type === 7) {
p.innerHTML += `<code>${i.name}</code><br>`;
}
}
let myRules = document.styleSheets[0].cssRules,
p = document.querySelector('.output');
for (i of myRules) {
if (i.type === 7) {
for (j of i.cssRules) {
p.innerHTML += `<code>${j.style.color}</code><br>`;
}
}
}
// Grab the style rules for the body and main elements
let myBodyRule = document.styleSheets[0].cssRules[1].style,
myMainRule = document.styleSheets[0].cssRules[2].style;
// Set the bg color on the body
myBodyRule.setProperty('background-color', 'peachpuff');
// Get the font size of the body
myBodyRule.getPropertyValue('font-size');
// Get the 5th item in the body's style rule
myBodyRule.item(5);
// Log the current length of the body style rule (8)
myBodyRule.length;
// Remove the line height
myBodyRule.removeProperty('line-height');
// log the length again (7)
myBodyRule.length;
// Check priority of font-family (empty string)
myBodyRule.getPropertyPriority('font-family');
// Check priority of margin in the "main" style rule (!important)
myMainRule.getPropertyPriority('margin');
原文链接:https://css-tricks.com/an-introduction-and-guide-to-the-css-object-model-cssom/
前言
如果你写了一段时间的JS了,大概率是接触过通过js去处理DOM(Document Objectl Model)了。DOM是很多用于操作页面上元素的API。 但其实除了DOM之外,还有一不被常人所知的CSSOM(CSS Object Model)。也可能你已经用过它了但其实并没有注意到。 在这篇文章中,我将列举许多CSSOM中最重要的特性,以一些常见的开始,然后逐渐列举一些不著名的但是实用的特性。
什么是CSSOM?
根据MDN的定义:
MDN的解释是基于W3C官方对CSSOM的定义来解释的。W3C文档是一个相当好的去熟悉CSSOM的方式,但是很难从中找到有用的代码片段去调用CSSOM的api。
MDN相对好很多,但是仍然有很多地方是缺失的。 因此在这个博文中,我将尽我的最大努力去创建有用的代码示例和demo,从而可以直观的搞清楚学明白CSSOM的这些api。
文章将首先从对于前端来说很常见的一些api。这些常见的特性常常被混淆成DOM的api,但它们其实是CSSOM。
通过element.style修改行内样式
通过JavaScript最基础的修改和获取CSS属性的方式是style对象,或者property,它对于所有HTML元素都使用。 比如这个例子:
大多数人都用过这个语法。可以通过这个语法去添加或者修改页面上任意对象的CSS:
在这个例子中,我将背景色改为了lightblue。当然,background是是缩写。如果想修改background-color属性呢?对于任何有连字符的属性来说,只需将其转为驼峰格式即可:
通常来说,缩写属性直接小写单词就行,对于连字符属性需要通过驼峰获取。 有一个例外,那就是float属性,因为float是js中的一个保留字符串,需要通过cssFloat(或styleFloat <=ie8)。 这一点和HTML中对for属性的获取很像,通过getAttribute()获取属性的话,需要标记它为"htmlFor"。
这里有一个通过CSSOM动态修改body背景色的demo:https://codepen.io/impressivewebs/pen/mQbqGR
通过JavaScript去定义一个CSS属性和它的值是非常简单的。 但是通过这种直接访问style对象的方式有一个很大的限制:只能修改元素的行内样式,换句话说就是必须在标签的style属性上定义。
该怎么去理解这句话呢?
上面的例子中,我给body定义了一个行内样式,然后我在控制台打印出了相同的样式。 这是正常的,但是如果我尝试读取元素的另一个属性的话,它什么都不会返回给我们-除非我预先在css中定义或者预先在js中定义过。
这里有个demo:https://codepen.io/impressivewebs/pen/LXPewe 通过css样式表是无法获取的。
结果为:The current background color is:
但是如果在body标签上为它的style属性有设置,是可以获取的:
结果为:The current background color is: lightblue
虽然通过显示设置或者直接用element.style可以设置,但是其实这样是很笨拙的,接下来我们来看一些很有用的通过js去读取和修改css的技术。
在
<style></style>
中定义能获取到吗? 不能。 仅适用于在标签style属性上定义的值,style标签上和css文件中都没有用。在
<style></style>
中定义,获取不到。在p标签上的style属性声明,可以获取到。
获得普通元素的计算样式
可以通过
window.getComputedStyle()
方法去读取任意元素的CSS属性。 例如我们上面通过document.body.style.color
无法读取color属性,可以改写为:但是对于一些缩写属性来说,通过window.getComputedStyle()查询到的属性比较有趣。
window.getComputedStyle()查询到的结果,是“过于仁慈的双胞胎”。 如果说element.style给你太少的话,那么window.getComputedStyle(element)就是对你爱的太深,给你太多太多。
这里有一个demo:https://codepen.io/impressivewebs/pen/XyWKJE
这里例子中,background是一个”lightblue“这样的单值,而window.getComputedStyle()给了太多太多,把background缩写属性的所有值都返回了回来。 多余的返回回来的这些默认值,往往是这些css属性的初始值(默认值)。
下面这个例子展示了background、animation、flex通过window.getComputed()获取的结果: https://codepen.io/impressivewebs/pen/OaJXjR
同样,对于类似width和height的属性,它揭露出元素的计算维度,不管这些值在CSS中有没有明确的定义,就像下面的demo这样:![image](https://user-images.githubusercontent.com/19262750/83999890-42418480-a996-11ea-8594-56d941ace5c2.png)
某种程度上相当于读取window.innerWidth的值,除了这是指定元素的指定属性的计算css,而不仅仅是一个window或者viewport的测量值。
通过window.getComputedStyle(),有几种不同的获取属性的方式。我们已经看了一种通过点语法和驼峰属性名的方式。其实还有另外两种:
第二种方式会警告。 建议通过第三种:1.不转换为驼峰获取属性值。 2. 不用转换为cssFloat获取值
获得伪元素的计算样式
有一个知者甚少的关于window.getComputedStyle()的小知识点:可以查询到伪元素的样式。 比如你看到下面这样的代码:
注意第二个参数null。 Firefox4之前的兼容代码和降级代码会有这样的写法。但是在现代的浏览器中,不再需要这样写了。
第二个可选的参数现在用于声明:我在获取一个伪元素的计算CSS。
看一下下面的代码:
通过下面的代码,我可以获得.box元素的伪元素的计算样式:
可以参考这个demo: https://codepen.io/impressivewebs/pen/YRXzdm
不仅仅可以获得 ::before,::after这种常见的伪元素,还可以获得类似::first-line这种伪元素的计算样式:
可以参考这个demo:https://codepen.io/impressivewebs/pen/rQVajQ
这里有一个firefox正常其他浏览器出bug的使用::placeholder的方式:
https://codepen.io/impressivewebs/pen/ZmGGXG
需要注意的是,浏览器在获取不存在的(但是有效的)浏览器不支持的伪元素时,会有不同的表现,比如自定义的伪元素(::banana)
https://codepen.io/impressivewebs/pen/VVLLgx
::banana, firefox不打印,chrome打印出默认值。
CSSStyleDeclaration API
前面我展示了如何通过style对象或者是window.getComputedStyle()去获取属性,它们两个其实都是通过CSSStyleDeclaration interface去暴露出去的。
用其他话说,下面的代码返回的,都是document.body元素的CSSStyleDeclaration对象:
看下面的截屏,你可以看到:style大多是空的,而window.getComputedStyle()是都有值的。![image](https://user-images.githubusercontent.com/19262750/84097535-7c169780-aa37-11ea-99e4-3da5649d612a.png)
但是window.getComputedStyle()得到的值,是只读(read-only)的。 element.style得到的值,setter和getter是都有的,但是遗憾的是这些值仅仅影响document的inline style。
setProperty(),getPropertyValue()和item()
如果你通过上面的几种方式之一暴露出了CSSStyleDeclaration对象,会有很多有用的方法去读取和修改这些值。 再强调一遍,getComputedStyle()是只读的,但是通过style属性得到的属性既有setter,也有getter。 考虑以下的代码:
在这个例子中,我们用了3个style的方法:
使用removeProperty()
除了上面的3个setProperty(), getPropertyValue()和item(),CSSStyleDeclaration还暴露了两个其他的方法。 代码和demo中,我将使用removeProperty()方法:
通过js移除一个css属性: https://codepen.io/impressivewebs/pen/dQoBZq
获取和设置属性的优先级
还有一个很有趣的方法,叫做getPropertyPriority()。
https://codepen.io/impressivewebs/pen/EOjqKd
box.style.setProperty('font-family', 'Georgia, serif', 'important');
设置了!important,可以设置成空或者空字符串去没有important优先级。如果我有以下的代码:
会为所有border缩写相关的属性返回important
CSSStyleSheet Interface
inline样式不常用,computed style常用但是会有困扰。
还有一个很好好用的查询样式表的api:CSSStyleSheet。 从document的样式表查询信息的最简方式是通过styleSheets属性。
可以这样查看当前页面有多少样式表:
可以通过这样去得到样式表的引用:
cssRules是最有用的属性。 cssRules中包括了block声明,at-rule和media rules等等。 在后面的章节中,我将详细介绍如何通过stylesheet object去读取和修改样式。
与Stylesheet Object一起工作
https://codepen.io/impressivewebs/pen/VVemNb
type为1的意思是:STYLE _RULE。 其他的type类型分别为:IMPORT_RULE(3), MEDIA_RULE(4),KEYFRAMES_RULE(7)等等。
seletcorText是规则关联的选择器。它是可写的属性。 如果我想修改a:hover为a:hover, a:active,可以这样写:
https://codepen.io/impressivewebs/pen/oQbYKZ
通过CSSOM获取@media规则
https://codepen.io/impressivewebs/pen/MzyeWd
还可以查到媒体查询的查询条件:conditionText/mediaText
https://codepen.io/impressivewebs/pen/OaNXgo
通过CSSOM获取@Keyframes规则
https://codepen.io/impressivewebs/pen/MzybxL
from和to代表的是0%和100%。
还可以查到keyframe的name:
https://codepen.io/impressivewebs/pen/oQxWGg
可以打印出帧动画的颜色:
https://codepen.io/impressivewebs/pen/jQqmXp
增加和删除CSS声明
可以通过insertRule()和deleteRule()去增删规则。
https://codepen.io/impressivewebs/pen/QJNMgN
insertRule的第二个参数是可选的,用来标记插入的位置,默认从头部0位置插入,类似数组的unshift操作。
https://codepen.io/impressivewebs/pen/OaNjxL
重访CSSStyleDeclaration API
https://codepen.io/impressivewebs/pen/aQZvXB
CSS Typed Object Model...未来?
CSS Typed OM