Skip to main content

DOM与样式

elem.className 与 elem.classList

className

对于修改元素的样式,首选修改类名的方式修改样式。

elem.className 对应于标签的 class attribute,如果我们修改一个 DOM 节点对象的 className 属性,那么会对标签的 class attribute 内容进行直接替换。

classList

elem.classList 是一个类数组,可以获取到一个元素的多个类名。

const div = document.createElement("div");
div.className = "class1 class2 class3";

div.classList; // ["class1", "class2", "class3"]

此时 div.classList 的结构如下:

0: "class1"
1: "class2"
2: "class3"
length: 3
value: "class1 class2 class3"

该类数组上还有如下方法。

方法说明
elem.classList.add(class)给当前元素添加指定类名
elem.classList.remove(class)给当前元素移除指定类名
elem.classList.toggle(class)如果类名存在则移除,类名不存在则添加
elem.classList.contains(class)判断是否还有某个类名
elem.classList.replace(oldClass, newClass)将旧类名替换为新类名
elem.classList.forEach(callback, thisArg)遍历 classList

修改 DOM 元素样式

elem.style

elem.style 是一个只读对象,我们修改 elem.style 上的属性,等价于给对应标签通过 style attribute 添加内联样式。

比如,elem.style.width = "100px" 等价于 <div id="elem" style="width: 100px;"></div>

elem.style 对象上的样式属性都是以驼峰命名方式存在的。

background-color  => elem.style.backgroundColor
z-index => elem.style.zIndex
border-left-width => elem.style.borderLeftWidth

如果你想删除(重制)一个内联样式,你可以将 elem.style 上相应的属性赋值为空字符串。

注意事项
  • 使用 elem.style.xxx 添加某个内联样式时注意不要忘记将 CSS 单位添加到值上
  • 对于一些简写属性,比如 elem.style.margin,我们对其赋值后,浏览器会推断出 elem.style.marginLeft/Right/Top/Bottom 的值

elem.style.cssText

我们不能像这样 elem.style = "color: red; width: 100px" 设置完整的属性,因为 div.style 是一个对象,并且它是只读的。

但是我们可以使用 elem.style.cssText 来读写标签上的 style attribute

elem.style.cssText = `
color: red !important;
background-color: yellow;
width: 100px;
text-align: center;
`;

我们很少使用这个属性,因为这样的赋值会重制整个内联样式。

我们也可以使用 elem.setAttribute("style") 来实现相同效果。

elem.setAttribute("style", `
color: red !important;
background-color: yellow;
width: 100px;
text-align: center;
`);

读取 DOM 元素样式计算值

window.getComputedStyle

window.getComputedStyle(element[, pseudo])

elem.style 的作用仅仅是对一个元素的内联样式进行读写。如果我们想要获取到一个元素所有层叠样式的 计算值 则可以使用 window.getComputedStyle 方法。

<body>
<style>
div {
color: green;
font-size: 1.15rem;
}
</style>

<div style="color: red">Hello World</div>
<div>Hello World</div>
</body>

<script>
const elems = document.querySelectorAll("div");
window.getComputedStyle(elems[0]).color; // 'rgb(255, 0, 0)' 红色
window.getComputedStyle(elems[1]).color; // 'rgb(0, 128, 0)' 绿色
window.getComputedStyle(elems[1]).fontSize; // '18.4px'
</script>
什么是样式的计算值?

比如我们给根元素设置了 font-size: 2rem,这样的相对单位的取值,最终会被浏览器解析为 px 单位的数值,这个就是计算值,在 Chrome 开发者工具中选中某个元素后,切换到 Computed 就可以查看这个元素所有样式的计算值了。

该方法还有第二个可选参数,用于指定某个元素的 伪元素 或者 伪类,这样我们就可以获取某个元素的 伪元素 或者 伪类 的计算样式了。

<body>
<style>
div::after {
content: "123";
color: green;
font-size: 1.15rem;
}

div:hover {
color: red;
}
</style>

<div>Hello World</div>
</body>

<script>
const elem = document.querySelector("div");
window.getComputedStyle(elem, "::after").content; // '123'
window.getComputedStyle(elem, ":hover").color; // 'rgb(0, 0, 0)' 黑色
</script>
关于元素的伪类

上面的例子中,div:hovercolor 计算值依旧是黑色,原因是执行该行代码时,我们的鼠标并没有悬浮在 div 元素之上,如果我们悬浮在 div 元素之上,再执行该行元素,那么 color 计算值就会变成红色。

由于隐私问题,链接的 :visited 伪类样式被隐藏了。

不要直接读取 width 和 height 属性

如果你想获取一个元素的尺寸,请可以使用 clientWidthoffsetWidth(后面会讲到)。

如果你直接使用 window.getComputedStyle(elem).width,那么对于一个内联元素来说取值可能就是 auto,并且如果元素具有滚动条,那么 width 实际上还会减去滚动条的宽度,因为本质上我们使用该方法读取的是 content 的 width 和 height,而且这个还和 box-sizing 的取值有关。