在上一章中,我们学习了 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 中读取样式的核心工具:
基本用法: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。