如果你已经写过一些前端代码,一定对这样的操作不陌生:

document.querySelector('.btn').style.color = 'red';

或者这样:

const styles = window.getComputedStyle(document.querySelector('.box'));
console.log(styles.width);

这些代码背后,有一个你可能听说过但未必深入了解的概念—— CSS 对象模型(CSS Object Model,简称 CSSOM)

简单来说,CSSOM 是浏览器将 CSS 样式信息组织成的一种数据结构,同时也是一组允许 JavaScript 与之交互的 API。它就像是 CSS 世界的“地图”——浏览器用这张地图来理解样式,而我们开发者则可以通过这张地图提供的“入口”来动态读取和修改样式。

本文作为 CSSOM 系列的第一章,将带你从零开始建立对 CSSOM 的完整认知。

一、CSSOM 与 DOM:形似神不同的两兄弟

要理解 CSSOM,最好的方式是从你已经熟悉的 DOM(Document Object Model,文档对象模型) 入手。

DOM 是什么?

DOM 是浏览器将 HTML 文档解析后生成的树形结构。它把网页的每一个标签、每一段文本都抽象为一个个节点(Node),并通过父子关系组织成一棵树。通过 DOM API,我们可以用 JavaScript 增删改查页面上的任何元素。

简单说:DOM 管的是“有什么内容”

CSSOM 是什么?

CSSOM 则是浏览器将 CSS 样式解析后生成的另一个树形结构。它把每一条样式规则、每一个选择器都组织成可供程序访问的对象。通过 CSSOM API,我们可以用 JavaScript 读取和修改页面的样式信息。

简单说:CSSOM 管的是“长什么样”

它们的关系

DOM 和 CSSOM 是 两个独立的数据结构,各自承担不同的职责:

维度

DOM

CSSOM

管理对象

HTML 内容与结构

CSS 样式与规则

核心作用

描述“页面上有什么”

描述“页面长什么样”

典型操作

增删改查元素

读取/修改样式

但两者又密不可分。浏览器在渲染页面时,会 将 DOM 树和 CSSOM 树合并为一棵渲染树(Render Tree) ,然后基于渲染树来计算布局和绘制像素。

记忆口诀: DOM 管“骨架”,CSSOM 管“衣服”,两者合在一起,才构成一个完整的“人”。

二、CSSOM 在浏览器渲染流程中的位置

理解了 CSSOM 是什么,我们再来看看它在浏览器“从 HTML 到屏幕像素”的整个流程中处于什么位置。

关键渲染路径(Critical Rendering Path)

浏览器从收到 HTML 到最终在屏幕上显示页面,大致经历以下步骤:

1. 处理 HTML 标记 → 构建 DOM 树
2. 处理 CSS 标记 → 构建 CSSOM 树
3. 合并 DOM + CSSOM → 构建渲染树
4. 布局(Layout)→ 计算每个节点的位置和大小
5. 绘制(Paint)→ 将像素绘制到屏幕上

CSSOM 的构建发生在第二步。浏览器在解析 HTML 的过程中,如果遇到 <link> 标签引用了外部样式表,或者遇到 <style> 标签中的内联样式,就会开始解析 CSS 代码。

CSSOM 树的构建过程

CSS 的解析过程和 HTML 类似,也遵循“字节 → 字符 → 令牌 → 节点 → 对象模型”的流程:

  • 浏览器读取 CSS 文件的原始字节。

  • 将字节按编码转换为字符。

  • 将字符解析为 CSS 令牌(如选择器、属性名、属性值等)。

  • 将令牌转换为带有层级关系的节点。

  • 最终链接成一棵 CSSOM 树。

为什么 CSSOM 是树形结构?

CSSOM 之所以是树形结构,是因为 CSS 样式具有 继承性 和 层叠性。举个例子:

body { font-size: 16px; }
p { color: blue; }
p span { color: red; }

浏览器在计算某个 <span> 元素的最终样式时,会从最通用的规则(如 body 的字体大小)开始,逐层向下应用更具体的规则(如 p span 的颜色)。这种“从通用到具体”的继承和覆盖关系,天然适合用树形结构来表示。

一个值得注意的细节

浏览器在构建 CSSOM 的过程中,不会渲染任何已处理的内容。也就是说,即便 DOM 已经解析完毕,只要 CSSOM 还没构建完成,页面就不会显示——这就是为什么 CSS 会被视为“渲染阻塞资源”。

三、为什么需要动态操作 CSS?

在传统静态网页时代,样式是固定的,CSS 写好是什么样就是什么样。但在现代 Web 应用中,动态样式操作 已经成为标配。

从静态到动态

静态 CSS 的局限在于:样式在页面加载时就已确定,无法根据用户行为或环境变化做出响应。而通过 JavaScript 操作 CSSOM,我们可以实现:

1. 响应用户交互

当用户点击按钮、悬停元素或输入内容时,动态改变样式以提供即时反馈。例如,表单输入框在验证失败时自动变红:

const input = document.querySelector('input');
input.addEventListener('blur', function() {
    if (this.value.length < 6) {
        this.style.borderColor = 'red';
    }
});

2. 实现主题切换

用户点击“暗色模式”开关时,整个页面的配色方案一键切换。这可以通过切换 CSS 类或修改 CSS 自定义属性(CSS Variables)来实现。

3. 响应式增强

根据设备屏幕尺寸、视口大小或网络状况动态调整样式,实现比纯 CSS 媒体查询更精细的控制。

4. 复杂动画与过渡

CSS 可以完成基础的过渡和动画,但对于需要根据用户操作实时计算路径、速度或状态的复杂动画,JavaScript 的介入不可或缺。

两种动态方式

通过 JavaScript 操作样式,主要有两条路径:

  • 操作内联样式(element.style.xxx):直接修改元素的 style 属性,影响范围小、优先级高,适合局部调整。

  • 操作样式表规则(通过 CSSOM API):修改或增删样式表中的规则,影响范围广,适合全局性的样式变更。

这两种方式各有适用场景,我们会在后续章节中详细展开。

四、CSSOM 的基本组成:模型 + 视图

在 W3C 标准中,CSSOM 实际上包含 两个部分

第一部分:CSSOM(狭义)

这是 CSSOM 的 核心模型部分,负责描述和管理样式表(Stylesheet)与样式规则(Rule)。通过这一部分的 API,我们可以:

  • 获取文档中所有的样式表(document.styleSheets)。

  • 读取和修改样式表中的具体规则(insertRule()、deleteRule())。

  • 获取某个元素经过层叠计算后的最终样式(getComputedStyle())。

这部分 API 让我们能够 从 JavaScript 层面“操控”CSS 本身,而不仅仅是操控单个元素的样式。

第二部分:CSSOM View

CSSOM View 可以看作是 DOM API 在 视图(显示)层面的扩展。它在原有的 Window、Document、Element 等接口上,添加了与页面显示相关的功能。

CSSOM View 主要包含三个子部分:

1. 窗口 API

控制浏览器窗口的位置和尺寸:

// 移动窗口到指定位置
window.moveTo(100, 100);
// 调整窗口大小
window.resizeTo(800, 600);

2. 滚动 API

读取和操纵视口及元素的滚动状态:

// 读取滚动位置
console.log(window.scrollX, window.scrollY);
// 滚动到指定位置
window.scrollTo({ top: 0, left: 0, behavior: 'smooth' });
// 将元素滚动到可见区域
document.querySelector('.footer').scrollIntoView({ behavior: 'smooth' });

3. 布局 API

获取元素在页面中的尺寸和位置信息(如 getBoundingClientRect() 等)。

两者的关系

简单来说:

  • CSSOM(狭义) :管的是“样式规则怎么写”——修改样式表、获取计算样式。

  • CSSOM View:管的是“页面怎么看”——窗口大小、滚动位置、元素布局。

在实际开发中,CSSOM View 的使用频率往往更高——因为我们更多时候需要的是获取元素位置、控制滚动这类与“视图”相关的操作,而不是动态修改样式表本身。

五、小结

本章我们建立了对 CSSOM 的基础认知,梳理了四个核心要点:

  1. CSSOM 与 DOM 的关系:两者是独立但协作的数据结构,DOM 管内容,CSSOM 管样式,合并后形成渲染树。

  2. CSSOM 在渲染流程中的位置:它构建于 DOM 之后、渲染树之前,是“关键渲染路径”中不可或缺的一环。

  3. 动态操作 CSS 的意义:从静态样式到动态交互,CSSOM 让页面能够根据用户行为和环境变化实时响应。

  4. CSSOM 的两大组成部分:狭义 CSSOM(管理样式表与规则)+ CSSOM View(管理窗口、滚动与布局)。

理解 CSSOM,不仅有助于你写出更优雅的动态样式代码,更能帮助你深入理解浏览器的工作原理,从而写出性能更优的 Web 应用。

在接下来的章节中,我们将逐一深入这些 API 的具体用法,从获取样式表到操作样式规则,从 getComputedStyle 到 CSSOM View 的滚动与布局——一步步掌握用 JavaScript 驾驭 CSS 的全部能力。