浏览器CSSOM:如何获取一个元素的准确位置
顾名思义,CSSOM是CSS的模型,在W3C标准中,它包含两个部分:链式样式表和规则等CSS模型部分(CSSOM),和跟元素视图相关的View部分(CSSOM View)。
CSSOM
首先介绍CSS样式表的模型,也是CSSOM本体。
我们通常创建样式表是通过HTML标签来做到的,我们用style标签和link标签创建样式表,
<style title="Hello">
a {
color:red;
}
</style>
<link rel="stylesheet" title="x" href="data:text/css,p%7Bcolor:blue%7D">
我们创建好样式表后,还可能对他进行一些操作。如果用DOM的角度去理解的话,这些标签在DOM中是一个节点,它们有节点的内容、属性。这两个标签中,有的在属性,有的在子节点。这两个标签遵循DOM节点的操作规则,所以可以使用DOM API去访问。
这样做的后果是我们需要去写很多分支逻辑,并且想要解析CSS代码结构并不是一件简单的事情,所以,这种情况下,我们直接使用CSSOM API去操作它们生成的样式表,这是一个更好的选择。
先了解一下CSSOM API的基本用法,一般来说,我们需要先文档中所有样式表:
document.styleSheets
document的styleSheets属性表示文档中的所有样式表,这是一个只读的列表,我们可以用方括号运算符下标访问样式表,也可以使用item方法来访问,它有length属性表示文档中的样式表数量。
虽然无法使用CSSOM API创建样式表,但是可以修改样式表中的内容:
document.styleSheets[0].insertRule("p { color:pink; }", 0)
document.styleSheets[0].removeRule(0)
更进一步,我们可以获取样式表中特定的规则(Rule),并且对他进行一定操作,具体来说,就是使用它的cssRules属性实现:
document.styleSheets[0].cssRules
这里获取的样式表同样支持item、length和下标运算。
不过这里的Rule就没那么简单了,它可能是CSS的at-rule,也可能是普通的样式规则。不同的样式规则,具有不同的属性。
我们在CSS语法部分,已经整理过at-rule的完整列表,多数at-rule都对应着一个rule类型
- CSSStyleRule
- CSSCharsetRule
- CSSImportRule
- CSSMediaRule
- CSSFontFaceRule
- CSSPageRule
- CSSNamespaceRule
- CSSKeyframesRule
- CSSKeyframeRule
- CSSSupportsRule
CSSStyleRule有两个属性:selectorText 和 style,分别表示一个规则的选择器部分和样式部分。
selector部分是一个字符串,这里显然偷懒了没有设计进一步的选择器模型,我们按照选择器语法设置即可。
style部分是一个样式表,它跟我们元素的style属性是一样的类型,所以我们可以像修改内联样式一样,直接改变属性修改规则中的具体CSS属性定义,也可以使用cssText这样的工具属性。
此外,CSSOM还提供了一个非常重要的方法,来获取一个元素最终经过CSS计算得到的属性:
window.getComputedStyle(elt, pseudoElt);
其中第一个参数就是我们要获取的元素,第二个是可选的,用于选择伪元素。
CSSOM View
CSSOM View 可以视为DOM API的拓展,在原来Element接口上,添加了显式相关API,有可以分为三个部分:窗口部分、滚动部分和布局部分。
窗口API
窗口API用于操作窗口位置、尺寸等。
- moveTo(x, y) 窗口移动到屏幕的特定坐标;
- moveBy(x, y) 窗口移动特定距离;
- resizeTo(x, y) 改变窗口大小到特定尺寸;
- resizeBy(x, y) 改变窗口大小特定尺寸。
窗口API还规定了window.open()第三个参数。
window.open("about:blank", "_blank","width=100,height=100,left=100,right=100" )
一些浏览器出于安全考虑并没有实现,也不是用于移动端。
滚动API
有一点需要注意,在PC时代,浏览器可视区域的滚动和内部元素的滚动关系是比较模糊的。但是在移动时代,两者必须分开看待,两者的性能和行为都有区别。
视口滚动API
元素滚动API
布局API
同样要分为全局API和元素上的API。
全局尺寸信息
- *window.innerHeight, window.innerWidth 这两个属性表示视口的大小。
- window.outerWidth, window.outerHeight 这两个属性表示浏览器窗口占据的大小,很多浏览器没有实现,一般来说这两个属性无关紧要。
- *window.devicePixelRatio 这个属性非常重要,表示物理像素和CSS像素单位的倍率关系,Retina屏这个值是2,后来也出现了一些3倍的Android屏。
window.screen (屏幕尺寸相关的信息)
- window.screen.width, window.screen.height 设备的屏幕尺寸。
- window.screen.availWidth, window.screen.availHeight 设备可渲染的屏幕尺寸
- window.screen.colorDepth, window.screen.pixelDepth 这两个属性是固定值24,应该是为了以后预留。
元素的布局信息
- getClientRects();会返回一个列表,里边包含元素对应的每一个盒所占据的客户端矩形区域。每一个矩形区域可以通过用x,y,width,height来获取它的位置和尺寸。
- getBoundingClientRect():这个API的设计更接近我们脑海中的元素盒的概念,它返回元素对应的所有盒的包裹的矩形区域。
这两个API获取的矩形区域都是相对于视口的坐标,这意味着,这些坐标都是受滚动影响的。
这两个API的兼容性非常好,定义又非常清晰,建议你如果是用JavaScript实现视觉效果时,尽量使用这两个API。
此文章为7月Day31学习笔记,内容来源于极客时间《重学前端》,日拱一卒,每天进步一点点💪💪
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。