什么是CSSOM
CSS对象模型是一组允许从JavaScript处理CSS的API。它很像DOM,但对于CSS而不是HTML。它允许用户动态地读取和修改CSS样式。
通过element.style获取和设置内联样式
使用JavaScript操作或访问CSS属性和值的最基本方法是通过元素的style
属性进行操作:
1 | document.body.style.background = 'lightblue'; |
这是使用JavaScript操作或获取CSS属性和值的简单方法。但是style以这种方式使用属性需要注意:这只适用于元素的内联样式。
如果元素没有定义内联样式,即时有一个外部样式文件,获取不存在的样式属性时将得不到任何东西:
1 | console.log(document.body.cssFloat) // "" |
这显然有一些显着的局限性,所以让我们看一些使用JavaScript阅读和操作样式的更有用的技术。
获取计算样式
可以使用以下window.getComputedStyle()
方法读取元素上任何CSS属性的计算CSS值:
1 | widnow.getComputedStyle(document.body).background |
计算属性将会得到最终的样式结果,包括浏览器默认的样式,这可能会得到太多东西了,(⊙o⊙)…!
有几种不同的方法可以使用window.getComputedStyle()
:
1 | // dot notation, same as above |
获取伪元素的计算样式
一个鲜为人知的小问题window.getComputedStyle()
是,它允许您检索伪元素的样式信息。你会经常看到这样的window.getComputedStyle()
声明:
1 | window.getComputedStyle(document.body, ":before").width; |
第二个可选参数允许我指定我正在访问伪元素的计算CSS。
CSSStyleDeclaration
不管是通过style
还是window.getComputedStyle
,它返回的都是CSSStyleDeclaration
对象,后者是只读的。
setProperty(), getPropertyValue() 和 item()
考虑如下代码:
1 | let box = document.querySelector('.box'); |
setProperty(css属性名,css属性值)
getPropertyValue(css属性名)
item(index)
:上图item(0)
为color
、item(1)
为font-family
,item(2)
如果没有的话返回””
removeProperty()
1 | box.style.setProperty('font-size', '1.5em'); |
获取和设置属性的优先级
1 | box.style.setProperty('font-family', 'Georgia, serif', 'important'); |
当setProperty
增加第三个参数important
时,font-family
将会有!important
权重。
我要强调的是,这些方法可以与已经直接放在HTML元素style属性上的任何内联样式一起使用。所以,如果我有以下HTML:
1 | <div class="box" style="border: solid 1px red !important;"> |
其他子属性也将会有!important
权重。
1 | // These all return "important" |
CSSStyleSheet接口
从样式表访问信息的最简单方法是使用document
开放的styleSheets
属性,例如,下面的行使用该length属性来查看当前页面具有多少样式表:
1 | document.styleSheets.length; // 1 |
我可以使用从零开始的索引来引用任何文档的样式表:
1 | document.styleSheets[0]; |
它将返回CSSStyleSheet
对象,里面最有用的是cssRules
属性,此属性提供该样式表中包含的所有CSS规则(包括声明块,规则,媒体规则等)的列表。在下面的部分,我们将详细介绍该API的操作。
cssRules(CSSRuleList) -> (CSSStyleRule) -> type, cssText, selectorText, style(CSSStyleDeclaration),…
使用样式表对象
下面使用样式表对象遍历选择器:
1 | let myRules = document.styleSheets[0].cssRules, |
注意:cssRules是对象。
type
类型:
1
: STYLE_RULE3
: IMPORT_RULE4
: MEDIA_RULE5
: KEYFRAMES_RULE
完整类型请参考:https://developer.mozilla.org/en-US/docs/Web/API/CSSRule#Type_constants
其中selectorText
是可写属性,所以我们可以动态修改:
1 | for (i of myRules) { |
使用CSSOM访问@media规则
假如有如下属性:
1 | @media (max-width: 800px) { |
可以通过conditionText
获取:
1 | let myRules = document.styleSheets[0].cssRules, |
使用CSSOM访问@keyframes规则
假如有如下属性:
1 | @keyframes exampleAnimation { |
可以通过keyText
获取:
1 | for (i of myRules) { |
您会注意到我的原始CSS使用from并to作为第一个和最后一个关键帧,但keyText属性计算这些0%和100%。keyText也可以设置值。在我的示例样式表中,我可以像这样硬编码:
1 | // Read the current value (0%) |
访问@keyframes规则时可用的另一个属性是name:
1 | let myRules = document.styleSheets[0].cssRules, |
我在这里要提到的最后一件事是能够获取单个关键帧内的特定样式。这是一些带有演示的示例代码:
1 | let myRules = document.styleSheets[0].cssRules, |
增加或删除CSSDeclarations规则
通过insertRule()
增加规则:
1 | let myStylesheet = document.styleSheets[0]; |
insertRule()
第一个参数是样式字符串,第二个参数是表示您希望插入规则的位置或索引。如果未包括此项,则默认为0(意味着规则将插入规则集合的开头)。如果索引恰好大于rules对象的长度,则会抛出错误。
通过deleteRule()
删除规则:
1 | let myStylesheet = document.styleSheets[0]; |
该方法接受一个参数,该参数表示我要删除的规则的索引,参数传入的索引值必须小于cssRules对象的长度,否则将引发错误。
重新访问CSSStyleDeclaration API
记住,CSSRule
下的style
属性返回CSSStyleDeclaration
属性:
1 | // Grab the style rules for the body and main elements |
CSSDOM的未来?
在我在本文中考虑过的所有内容之后,我不得不打破这样的消息,即有一天我们所知道的CSSOM可能已经过时了。
这是因为称为CSS Typed OM的东西,它是Houdini项目的一部分。虽然有些人已经注意到新的Typed OM与目前的CSSOM相比更加冗长,但Eric Bidelman在本文中概述的好处包括:
- 更少的错误
- 算术运算和单位转换
- 更好的性能
- 错误处理
- CSS属性名称始终是字符串
有关这些功能的完整详细信息和语法的一瞥,请务必查看完整的文章。
在撰写本文时,CSS Typed OM仅在Chrome中受支持。