CSS 操作
CSS 怎么使用呢
CSS 操作
CSS 与 JavaScript 是两个有着明确分工的领域,前者负责页面的视觉效果,后者负责与用户的行为互动。但是,它们毕竟同属网页开发的前端,因此不可避免有着交叉和互相配合。本章介绍如何通过 JavaScript 操作 CSS。
HTML 元素的 style 属性
操作 CSS 样式最简单的方法,就是使用网页元素节点的getAttribute()
方法、setAttribute()
方法和removeAttribute()
方法,直接读写或删除网页元素的style
属性。
上面的代码相当于下面的 HTML 代码。
style
不仅可以使用字符串读写,它本身还是一个对象,部署了 CSSStyleDeclaration 接口(详见下面的介绍),可以直接读写个别属性。
CSSStyleDeclaration 接口
简介
CSSStyleDeclaration 接口用来操作元素的样式。三个地方部署了这个接口。
- 元素节点的
style
属性(Element.style
) CSSStyle
实例的style
属性window.getComputedStyle()
的返回值
CSSStyleDeclaration 接口可以直接读写 CSS 的样式属性,不过,连词号需要变成骆驼拼写法。
上面代码中,style
属性的值是一个 CSSStyleDeclaration 实例。这个对象所包含的属性与 CSS 规则一一对应,但是名字需要改写,比如background-color
写成backgroundColor
。改写的规则是将横杠从 CSS 属性名中去除,然后将横杠后的第一个字母大写。如果 CSS 属性名是 JavaScript 保留字,则规则名之前需要加上字符串css
,比如float
写成cssFloat
。
注意,该对象的属性值都是字符串,设置时必须包括单位,但是不含规则结尾的分号。比如,divStyle.width
不能写为100
,而要写为100px
。
另外,Element.style
返回的只是行内样式,并不是该元素的全部样式。通过样式表设置的样式,或者从父元素继承的样式,无法通过这个属性得到。元素的全部样式要通过window.getComputedStyle()
得到。
CSSStyleDeclaration 实例属性
(1)CSSStyleDeclaration.cssText
CSSStyleDeclaration.cssText
属性用来读写当前规则的所有样式声明文本。
注意,cssText
的属性值不用改写 CSS 属性名。
删除一个元素的所有行内样式,最简便的方法就是设置cssText
为空字符串。
(2)CSSStyleDeclaration.length
CSSStyleDeclaration.length
属性返回一个整数值,表示当前规则包含多少条样式声明。
上面代码中,myDiv
元素的行内样式共包含3条样式规则。
(3)CSSStyleDeclaration.parentRule
CSSStyleDeclaration.parentRule
属性返回当前规则所属的那个样式块(CSSRule 实例)。如果不存在所属的样式块,该属性返回null
。
该属性只读,且只在使用 CSSRule 接口时有意义。
CSSStyleDeclaration 实例方法
(1)CSSStyleDeclaration.getPropertyPriority()
CSSStyleDeclaration.getPropertyPriority
方法接受 CSS 样式的属性名作为参数,返回一个字符串,表示有没有设置important
优先级。如果有就返回important
,否则返回空字符串。
上面代码中,margin
属性有important
优先级,color
属性没有。
(2)CSSStyleDeclaration.getPropertyValue()
CSSStyleDeclaration.getPropertyValue
方法接受 CSS 样式属性名作为参数,返回一个字符串,表示该属性的属性值。
(3)CSSStyleDeclaration.item()
CSSStyleDeclaration.item
方法接受一个整数值作为参数,返回该位置的 CSS 属性名。
上面代码中,0
号位置的 CSS 属性名是color
,1
号位置的 CSS 属性名是background-color
。
如果没有提供参数,这个方法会报错。如果参数值超过实际的属性数目,这个方法返回一个空字符值。
(4)CSSStyleDeclaration.removeProperty()
CSSStyleDeclaration.removeProperty
方法接受一个属性名作为参数,在 CSS 规则里面移除这个属性,返回这个属性原来的值。
上面代码中,删除color
属性以后,字体颜色从红色变成默认颜色。
(5)CSSStyleDeclaration.setProperty()
CSSStyleDeclaration.setProperty
方法用来设置新的 CSS 属性。该方法没有返回值。
该方法可以接受三个参数。
- 第一个参数:属性名,该参数是必需的。
- 第二个参数:属性值,该参数可选。如果省略,则参数值默认为空字符串。
- 第三个参数:优先级,该参数可选。如果设置,唯一的合法值是
important
,表示 CSS 规则里面的!important
。
上面代码执行后,myDiv
元素就会出现蓝色的边框。
CSS 模块的侦测
CSS 的规格发展太快,新的模块层出不穷。不同浏览器的不同版本,对 CSS 模块的支持情况都不一样。有时候,需要知道当前浏览器是否支持某个模块,这就叫做“CSS模块的侦测”。
一个比较普遍适用的方法是,判断元素的style
对象的某个属性值是否为字符串。
如果该 CSS 属性确实存在,会返回一个字符串。即使该属性实际上并未设置,也会返回一个空字符串。如果该属性不存在,则会返回undefined
。
上面代码说明,这个浏览器支持max-width
属性,但是不支持maximum-width
属性。
注意,不管 CSS 属性名的写法带不带连词线,style
属性上都能反映出该属性是否存在。
另外,使用的时候,需要把不同浏览器的 CSS 前缀也考虑进去。
这种侦测方法可以写成一个函数。
CSS 对象
浏览器原生提供 CSS 对象,为 JavaScript 操作 CSS 提供一些工具方法。
这个对象目前有两个静态方法。
CSS.escape()
CSS.escape
方法用于转义 CSS 选择器里面的特殊字符。
上面代码中,该元素的id
属性包含一个#
号,该字符在 CSS 选择器里面有特殊含义。不能直接写成document.querySelector('#foo#bar')
,只能写成document.querySelector('#foo\\#bar')
。这里必须使用双斜杠的原因是,单引号字符串本身会转义一次斜杠。
CSS.escape
方法就用来转义那些特殊字符。
CSS.supports()
CSS.supports
方法返回一个布尔值,表示当前环境是否支持某一句 CSS 规则。
它的参数有两种写法,一种是第一个参数是属性名,第二个参数是属性值;另一种是整个参数就是一行完整的 CSS 语句。
注意,第二种写法的参数结尾不能带有分号,否则结果不准确。
window.getComputedStyle()
行内样式(inline style)具有最高的优先级,改变行内样式,通常会立即反映出来。但是,网页元素最终的样式是综合各种规则计算出来的。因此,如果想得到元素实际的样式,只读取行内样式是不够的,需要得到浏览器最终计算出来的样式规则。
window.getComputedStyle()
方法,就用来返回浏览器计算后得到的最终规则。它接受一个节点对象作为参数,返回一个 CSSStyleDeclaration 实例,包含了指定节点的最终样式信息。所谓“最终样式信息”,指的是各种 CSS 规则叠加后的结果。
上面代码中,得到的背景色就是div
元素真正的背景色。
注意,CSSStyleDeclaration 实例是一个活的对象,任何对于样式的修改,会实时反映到这个实例上面。另外,这个实例是只读的。
getComputedStyle
方法还可以接受第二个参数,表示当前元素的伪元素(比如:before
、:after
、:first-line
、:first-letter
等)。
下面的例子是如何获取元素的高度。
上面代码得到的height
属性,是浏览器最终渲染出来的高度,比其他方法得到的高度更可靠。由于styleObj
是 CSSStyleDeclaration 实例,所以可以使用各种 CSSStyleDeclaration 的实例属性和方法。
有几点需要注意。
- CSSStyleDeclaration 实例返回的 CSS 值都是绝对单位。比如,长度都是像素单位(返回值包括
px
后缀),颜色是rgb(#, #, #)
或rgba(#, #, #, #)
格式。 - CSS 规则的简写形式无效。比如,想读取
margin
属性的值,不能直接读,只能读marginLeft
、marginTop
等属性;再比如,font
属性也是不能直接读的,只能读font-size
等单个属性。 - 如果读取 CSS 原始的属性名,要用方括号运算符,比如
styleObj['z-index']
;如果读取骆驼拼写法的 CSS 属性名,可以直接读取styleObj.zIndex
。 - 该方法返回的 CSSStyleDeclaration 实例的
cssText
属性总是返回空字符串。
CSS 伪元素
CSS 伪元素是通过 CSS 向 DOM 添加的元素,主要是通过:before
和:after
选择器生成,然后用content
属性指定伪元素的内容。
下面是一段 HTML 代码。
CSS 添加伪元素:before
的写法如下。
节点元素的style
对象无法读写伪元素的样式,这时就要用到window.getComputedStyle()
。JavaScript 获取伪元素,可以使用下面的方法。
此外,也可以使用 CSSStyleDeclaration 实例的getPropertyValue
方法,获取伪元素的属性。
StyleSheet 接口
概述
StyleSheet
接口代表网页的一张样式表,包括<link>
元素加载的样式表和<style>
元素内嵌的样式表。
document
对象的styleSheets
属性,可以返回当前页面的所有StyleSheet
实例(即所有样式表)。它是一个类似数组的对象。
如果是<style>
元素嵌入的样式表,还有另一种获取StyleSheet
实例的方法,就是这个节点元素的sheet
属性。
严格地说,StyleSheet
接口不仅包括网页样式表,还包括 XML 文档的样式表。所以,它有一个子类CSSStyleSheet
表示网页的 CSS 样式表。我们在网页里面拿到的样式表实例,实际上是CSSStyleSheet
的实例。这个子接口继承了StyleSheet
的所有属性和方法,并且定义了几个自己的属性,下面把这两个接口放在一起介绍。
实例属性
StyleSheet
实例有以下属性。
(1)StyleSheet.disabled
StyleSheet.disabled
返回一个布尔值,表示该样式表是否处于禁用状态。手动设置disabled
属性为true
,等同于在<link>
元素里面,将这张样式表设为alternate stylesheet
,即该样式表将不会生效。
注意,disabled
属性只能在 JavaScript 脚本中设置,不能在 HTML 语句中设置。
(2)StyleSheet.href
StyleSheet.href
返回样式表的网址。对于内嵌样式表,该属性返回null
。该属性只读。
(3)StyleSheet.media
StyleSheet.media
属性返回一个类似数组的对象(MediaList
实例),成员是表示适用媒介的字符串。表示当前样式表是用于屏幕(screen),还是用于打印(print)或手持设备(handheld),或各种媒介都适用(all)。该属性只读,默认值是screen
。
MediaList
实例的appendMedium
方法,用于增加媒介;deleteMedium
方法用于删除媒介。
(4)StyleSheet.title
StyleSheet.title
属性返回样式表的title
属性。
(5)StyleSheet.type
StyleSheet.type
属性返回样式表的type
属性,通常是text/css
。
(6)StyleSheet.parentStyleSheet
CSS 的@import
命令允许在样式表中加载其他样式表。StyleSheet.parentStyleSheet
属性返回包含了当前样式表的那张样式表。如果当前样式表是顶层样式表,则该属性返回null
。
(7)StyleSheet.ownerNode
StyleSheet.ownerNode
属性返回StyleSheet
对象所在的 DOM 节点,通常是<link>
或<style>
。对于那些由其他样式表引用的样式表,该属性为null
。
(8)CSSStyleSheet.cssRules
CSSStyleSheet.cssRules
属性指向一个类似数组的对象(CSSRuleList
实例),里面每一个成员就是当前样式表的一条 CSS 规则。使用该规则的cssText
属性,可以得到 CSS 规则对应的字符串。
每条 CSS 规则还有一个style
属性,指向一个对象,用来读写具体的 CSS 命令。
(9)CSSStyleSheet.ownerRule
有些样式表是通过@import
规则输入的,它的ownerRule
属性会返回一个CSSRule
实例,代表那行@import
规则。如果当前样式表不是通过@import
引入的,ownerRule
属性返回null
。
实例方法
(1)CSSStyleSheet.insertRule()
CSSStyleSheet.insertRule
方法用于在当前样式表的插入一个新的 CSS 规则。
该方法可以接受两个参数,第一个参数是表示 CSS 规则的字符串,这里只能有一条规则,否则会报错。第二个参数是该规则在样式表的插入位置(从0开始),该参数可选,默认为0(即默认插在样式表的头部)。注意,如果插入位置大于现有规则的数目,会报错。
该方法的返回值是新插入规则的位置序号。
注意,浏览器对脚本在样式表里面插入规则有很多限制。所以,这个方法最好放在try...catch
里使用。
(2)CSSStyleSheet.deleteRule()
CSSStyleSheet.deleteRule
方法用来在样式表里面移除一条规则,它的参数是该条规则在cssRules
对象中的位置。该方法没有返回值。
实例:添加样式表
网页添加样式表有两种方式。一种是添加一张内置样式表,即在文档中添加一个<style>
节点。
另一种是添加外部样式表,即在文档中添加一个<link>
节点,然后将href
属性指向外部样式表的 URL。
CSSRuleList 接口
CSSRuleList 接口是一个类似数组的对象,表示一组 CSS 规则,成员都是 CSSRule 实例。
获取 CSSRuleList 实例,一般是通过StyleSheet.cssRules
属性。
CSSRuleList 实例里面,每一条规则(CSSRule 实例)可以通过rules.item(index)
或者rules[index]
拿到。CSS 规则的条数通过rules.length
拿到。还是用上面的例子。
注意,添加规则和删除规则不能在 CSSRuleList 实例操作,而要在它的父元素 StyleSheet 实例上,通过StyleSheet.insertRule()
和StyleSheet.deleteRule()
操作。
CSSRule 接口
概述
一条 CSS 规则包括两个部分:CSS 选择器和样式声明。下面就是一条典型的 CSS 规则。
JavaScript 通过 CSSRule 接口操作 CSS 规则。一般通过 CSSRuleList 接口(StyleSheet.cssRules
)获取 CSSRule 实例。
CSSRule 实例的属性
(1)CSSRule.cssText
CSSRule.cssText
属性返回当前规则的文本,还是使用上面的例子。
如果规则是加载(@import
)其他样式表,cssText
属性返回@import 'url'
。
(2)CSSRule.parentStyleSheet
CSSRule.parentStyleSheet
属性返回当前规则所在的样式表对象(StyleSheet 实例),还是使用上面的例子。
(3)CSSRule.parentRule
CSSRule.parentRule
属性返回包含当前规则的父规则,如果不存在父规则(即当前规则是顶层规则),则返回null
。
父规则最常见的情况是,当前规则包含在@media
规则代码块之中。
(4)CSSRule.type
CSSRule.type
属性返回一个整数值,表示当前规则的类型。
最常见的类型有以下几种。
- 1:普通样式规则(CSSStyleRule 实例)
- 3:
@import
规则 - 4:
@media
规则(CSSMediaRule 实例) - 5:
@font-face
规则
CSSStyleRule 接口
如果一条 CSS 规则是普通的样式规则(不含特殊的 CSS 命令),那么除了 CSSRule 接口,它还部署了 CSSStyleRule 接口。
CSSStyleRule 接口有以下两个属性。
(1)CSSStyleRule.selectorText
CSSStyleRule.selectorText
属性返回当前规则的选择器。
注意,这个属性是可写的。
(2)CSSStyleRule.style
CSSStyleRule.style
属性返回一个对象(CSSStyleDeclaration 实例),代表当前规则的样式声明,也就是选择器后面的大括号里面的部分。
CSSStyleDeclaration 实例的cssText
属性,可以返回所有样式声明,格式为字符串。
CSSMediaRule 接口
如果一条 CSS 规则是@media
代码块,那么它除了 CSSRule 接口,还部署了 CSSMediaRule 接口。
该接口主要提供media
属性和conditionText
属性。前者返回代表@media
规则的一个对象(MediaList 实例),后者返回@media
规则的生效条件。
window.matchMedia()
基本用法
window.matchMedia()
方法用来将 CSS 的Media Query
条件语句,转换成一个 MediaQueryList 实例。
上面代码中,变量mdl
就是 mediaQueryList 的实例。
注意,如果参数不是有效的MediaQuery
条件语句,window.matchMedia
不会报错,依然返回一个 MediaQueryList 实例。
MediaQueryList 接口的实例属性
MediaQueryList 实例有三个属性。
(1)MediaQueryList.media
MediaQueryList.media
属性返回一个字符串,表示对应的 MediaQuery 条件语句。
(2)MediaQueryList.matches
MediaQueryList.matches
属性返回一个布尔值,表示当前页面是否符合指定的 MediaQuery 条件语句。
下面的例子根据mediaQuery
是否匹配当前环境,加载相应的 CSS 样式表。
(3)MediaQueryList.onchange
如果 MediaQuery 条件语句的适配环境发生变化,会触发change
事件。MediaQueryList.onchange
属性用来指定change
事件的监听函数。该函数的参数是change
事件对象(MediaQueryListEvent 实例),该对象与 MediaQueryList 实例类似,也有media
和matches
属性。
上面代码中,change
事件发生后,存在两种可能。一种是显示宽度从600像素以上变为以下,另一种是从600像素以下变为以上,所以在监听函数内部要判断一下当前是哪一种情况。
MediaQueryList 接口的实例方法
MediaQueryList 实例有两个方法MediaQueryList.addListener()
和MediaQueryList.removeListener()
,用来为change
事件添加或撤销监听函数。
注意,MediaQueryList.removeListener()
方法不能撤销MediaQueryList.onchange
属性指定的监听函数。