在上一章中,我们学习了 element.style —— 它让我们能够读写元素标签上的内联样式。但你一定遇到过这样的情况:

const box = document.querySelector('.box');
console.log(box.style.width); // 输出 ""(空字符串)

明明元素在页面上显示得好好的,宽度也是确定的,为什么 element.style.width 读不到任何东西?

原因很简单:element.style 只能读取 内联样式(即写在 HTML 的 style 属性里的样式)。如果样式来自外部样式表、<style> 标签,或者继承自父元素,element.style 都无能为力。

那么,如何获取元素“真正”的样式呢?答案就是本章的主角 —— getComputedStyle

getComputedStyle 是 CSSOM 中一个极为重要的方法。它能够穿透所有样式来源(内联样式、内部样式表、外部样式表、浏览器默认样式),经过层叠计算后,返回元素最终生效的样式值。无论你是要调试样式冲突,还是要获取元素的实际尺寸,都离不开它。

一、window.getComputedStyle() 的用法与参数

getComputedStyle 是 window 对象上的一个方法,用法非常直接。

基本语法
const style = window.getComputedStyle(element, pseudoElt);

它接受两个参数:

  • element(必需):要获取计算样式的 DOM 元素。

  • pseudoElt(可选):一个字符串,指定要获取的伪元素(如 '::before'、'::after')。对于普通元素,可以省略此参数或传入 null。

返回值

getComputedStyle 返回一个 CSSStyleDeclaration 对象(更准确地说是 CSSStyleProperties 对象,它派生自 CSSStyleDeclaration)。这个对象包含了元素所有 CSS 属性的 已解析值(resolved values)

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

// 两种方式都可以访问属性值
console.log(styles.width);          // "200px"
console.log(styles['font-size']);   // "16px"
console.log(styles.getPropertyValue('background-color')); // "rgb(255, 0, 0)"

访问方式非常灵活:既可以用驼峰命名(styles.backgroundColor),也可以用连字符命名(styles['background-color']),还可以使用 getPropertyValue() 方法。

两个重要的特性

特性一:只读(Read-only)

getComputedStyle 返回的对象是 只读 的。你只能用它来 读取 样式,不能通过它来 设置 样式。如果你想修改样式,需要通过 element.style 或其他方式来操作。

const styles = window.getComputedStyle(box);
styles.color = 'red'; // 无效!这个对象是只读的

特性二:实时(Live)

getComputedStyle 返回的对象是 实时 的。当元素的样式发生变化时(无论是通过 JavaScript 修改,还是通过 CSS 类切换),这个对象会自动更新,不需要重新调用 getComputedStyle。

const styles = window.getComputedStyle(box);
console.log(styles.color); // "rgb(0, 0, 255)"(蓝色)

// 通过其他方式修改样式
box.style.color = 'red';

// 之前获取的 styles 对象自动更新了!
console.log(styles.color); // "rgb(255, 0, 0)"(红色)

这意味着你可以安全地缓存 getComputedStyle 的返回值,它会始终保持最新状态。

关于 defaultView 的说明

在一些旧代码中,你可能会看到这样的写法:

const styles = document.defaultView.getComputedStyle(box);

document.defaultView 通常指向 window 对象,所以 document.defaultView.getComputedStyle 和 window.getComputedStyle 在大多数情况下是等价的。直接使用 window.getComputedStyle 更简洁,也是目前的主流写法。

二、getComputedStyle() 与 element.style 的区别

这是理解 getComputedStyle 最关键的一环。我们把两者的区别梳理清楚:

区别一:只读 vs 可读写

getComputedStyle

element.style

读取样式

可以

可以

设置样式

不可以(只读)

可以

getComputedStyle 是 只读的,只能用来查看样式。element.style 是 可读写的,既能查看也能修改。

区别二:获取的范围不同

getComputedStyle

element.style

内联样式

可以获取

可以获取

样式表中的样式

可以获取

无法获取

继承的样式

可以获取

无法获取

浏览器默认样式

可以获取

无法获取

getComputedStyle 获取的是 所有来源 的样式经过层叠计算后的最终结果。而 element.style 只能获取 内联样式 ——也就是写在 HTML 的 style 属性里的那些样式。

区别三:返回值的格式不同

getComputedStyle 返回的值是 计算后的值。比如:

  • 颜色值会统一转换为 rgb() 或 rgba() 格式。

  • 长度单位会转换为像素值。

  • 百分比会基于父元素计算为具体数值。

而 element.style 返回的是你在 style 属性中写的 原始值

/* 样式表中定义 */
.box { width: 50%; background: blue; }

const box = document.querySelector('.box');

// element.style 什么都读不到(因为样式不在内联中)
console.log(box.style.width); // ""

// getComputedStyle 能读到最终计算值
const styles = window.getComputedStyle(box);
console.log(styles.width); // 假设父容器宽 400px,输出 "200px"
console.log(styles.backgroundColor); // "rgb(0, 0, 255)"
一目了然的对比表

维度

getComputedStyle

element.style

可读性

只读

可读可写

获取内联样式

可以

不可以

获取样式表样式

可以

不可以

获取继承样式

可以

不可以

获取浏览器默认样式

可以

不可以

返回值格式

计算后的值(如 rgb()、像素值)

原始值

是否实时更新

三、获取伪元素样式

getComputedStyle 有一个非常实用的功能:可以获取伪元素(pseudo-element)的样式

伪元素(如 ::before、::after、::marker 等)并不存在于 DOM 中,因此无法通过 element.style 来访问。但通过 getComputedStyle 的第二个参数,我们可以获取它们的计算样式。

基本用法
<style>
    .box::before {
        content: "★";
        color: gold;
        font-size: 24px;
    }
</style>

<div class="box">评分</div>

<script>
    const box = document.querySelector('.box');
    
    // 获取 ::before 伪元素的样式
    const beforeStyles = window.getComputedStyle(box, '::before');
    console.log(beforeStyles.content);   // ""★"" (注意:content 返回带引号的字符串)
    console.log(beforeStyles.color);     // "rgb(255, 215, 0)"
    console.log(beforeStyles.fontSize);  // "24px"
</script>
支持哪些伪元素?

getComputedStyle 可以获取多种伪元素的样式,包括但不限于:::before、::after、::marker、::first-line、::first-letter、::selection。

// 获取 ::after 伪元素
const afterStyles = window.getComputedStyle(element, '::after');

// 获取 ::first-line 伪元素
const firstLineStyles = window.getComputedStyle(element, '::first-line');
注意事项
  • 伪元素选择器字符串支持 双冒号(::before)和 单冒号(:before)两种写法。

  • 如果传入的伪元素在 CSS 中不存在,返回的对象中对应属性的值可能是空字符串或默认值。

  • content 属性返回的值会包含引号,例如 ""★"",需要注意处理。

四、实际应用场景

了解了 getComputedStyle 的用法,我们来看几个实际开发中的典型场景。

场景一:获取元素的实际尺寸

这是最常用的场景之一。当我们需要知道一个元素实际渲染后的宽度或高度时,getComputedStyle 是首选工具。

<style>
    .card {
        width: 80%;
        padding: 20px;
        box-sizing: border-box;
    }
</style>

<div class="card" id="card">内容</div>

<script>
    const card = document.getElementById('card');
    const styles = window.getComputedStyle(card);
    
    // 获取实际宽度(已计算为像素值)
    const width = styles.width;        // 例如 "320px"
    const height = styles.height;      // 例如 "100px"
    
    // 获取 padding 值
    const paddingTop = styles.paddingTop;   // "20px"
    const paddingLeft = styles.paddingLeft; // "20px"
    
    console.log(`卡片实际宽度:${width},内边距:${paddingTop}`);
</script>

提示:getComputedStyle 返回的尺寸值是 解析值(resolved values) 。对于 width 和 height 这类依赖布局的属性,返回的是 使用值(used value) ——也就是元素实际渲染后的像素值。这正是我们想要的“真实尺寸”。

场景二:获取元素的颜色值

当你需要读取元素的颜色(比如为了在 JavaScript 中做颜色判断或处理)时,getComputedStyle 可以帮你拿到标准化的颜色值。

const element = document.querySelector('.title');
const styles = window.getComputedStyle(element);

// 颜色值会被统一转换为 rgb() 或 rgba() 格式
const color = styles.color;  // "rgb(51, 51, 51)"
const bgColor = styles.backgroundColor; // "rgb(255, 255, 255)"

// 可以进一步解析为数值使用
const rgbMatch = color.match(/\d+/g);
if (rgbMatch) {
    const [r, g, b] = rgbMatch.map(Number);
    console.log(`R:${r}, G:${g}, B:${b}`);
}
场景三:检测元素是否隐藏

判断一个元素是否真正可见,不能只看它有没有 display: none —— 还可能有 visibility: hidden、opacity: 0,或者父元素隐藏导致它被隐藏。getComputedStyle 可以帮你获取最终的计算结果。

function isElementVisible(element) {
    const styles = window.getComputedStyle(element);
    // 检查多个可能导致不可见的属性
    return styles.display !== 'none' && 
           styles.visibility !== 'hidden' && 
           parseFloat(styles.opacity) > 0;
}

const box = document.querySelector('.box');
console.log(isElementVisible(box) ? '可见' : '不可见');
场景四:调试样式冲突

当你的样式没有按预期生效时,getComputedStyle 是排查问题的利器。

const problematic = document.querySelector('.problem');
const styles = window.getComputedStyle(problematic);

// 查看最终生效的样式值
console.log('最终颜色:', styles.color);
console.log('最终字体大小:', styles.fontSize);
console.log('最终外边距:', styles.margin);

// 对比你期望的值,找出是哪里被覆盖了

在浏览器开发者工具中,你当然可以在 Elements 面板的 Styles 标签里看到计算后的样式。但 getComputedStyle 的优势在于,你可以在 JavaScript 中 编程式地 获取这些信息,用于自动化测试、动态逻辑判断等场景。

场景五:获取伪元素的动态内容

如果你用 ::before 或 ::after 来显示一些动态信息(比如通过 content: attr(data-xxx)),可以通过 getComputedStyle 读取这些内容。

<style>
    .status::before {
        content: attr(data-status);
    }
</style>

<div class="status" data-status="在线">用户</div>

<script>
    const statusEl = document.querySelector('.status');
    const beforeStyles = window.getComputedStyle(statusEl, '::before');
    const statusText = beforeStyles.content; // ""在线""
    // 注意去掉引号
    const actualText = statusText.replace(/^["']|["']$/g, '');
    console.log('状态:', actualText); // "在线"
</script>

五、两个重要的注意事项

注意一:颜色值返回 rgb/rgba 格式

getComputedStyle 返回的颜色值会被序列化为 rgb() 或 rgba() 格式。即使你在 CSS 中写的是 red、#ff0000 或 hsl(0, 100%, 50%),最终返回的都是 rgb(255, 0, 0)。

// CSS: .box { color: red; }
const styles = window.getComputedStyle(box);
console.log(styles.color); // "rgb(255, 0, 0)",不是 "red"
注意二:安全限制 —— 已访问链接的样式

出于隐私安全考虑,浏览器不会返回已访问链接(:visited)的真实计算样式。这是为了防止恶意网站通过检测链接颜色来窥探用户的浏览历史。如果你尝试获取一个已访问链接的样式,浏览器会返回未访问状态下的样式值。

六、小结

本章我们完整学习了 getComputedStyle 的用法,这是 CSSOM 中读取样式的核心工具:

  1. 基本用法:window.getComputedStyle(element, pseudoElt) 返回一个包含元素所有 CSS 属性 已解析值 的 CSSStyleDeclaration 对象。返回值是 只读 的,但 实时 更新。

 2. 与 element.style 的区别:getComputedStyle 能获取所有来源的样式(内联、样式表、继承、浏览器默认),而 element.style 只能获取内联样式。getComputedStyle 只读,element.style 可读写。

 3. 获取伪元素样式:通过第二个参数传入伪元素选择器(如 '::before'),可以获取伪元素的计算样式。

 4. 实际应用场景:获取元素真实尺寸、读取颜色值、检测元素是否可见、调试样式冲突、读取伪元素动态内容等。

至此,我们完成了 CSSOM 读取样式部分的学习。从 document.styleSheets 获取样式表,到 cssRules 操作规则,到 element.style 操作内联样式,再到 getComputedStyle 获取计算样式——你已经掌握了 CSSOM 读取与操作的完整工具链。在下一章中,我们将进入 CSSOM View 的世界,学习与窗口、滚动和布局相关的 API。