通常有两种设置元素样式的方式:

  1. 在 CSS 中创建一个类,并添加它:<div class="...">
  2. 将属性直接写入 style<div style="...">

JS 既可以修改 class,也可以修改 style:

  • 相较于将样式写入 style 属性,应该首选通过 CSS 类的方式来添加样式
  • 仅当类“无法处理”时,才应选择使用 style 属性的方式
    • 如:动态地计算元素的坐标

class

elem.className

calss 是保留字,一般不用作对象的属性,所以使用 className 代替:

  • attribute:class
  • property:className

可读可写:

  • 读:字符串
    • elem.className
    • elem.getAttribute('class')
  • 写:字符串,将替换类中的整个字符串
    • elem.className = "xxx"
    • elem.setAttribute('class', 'xxx')

elem.classList

className 操作字符串,classList 提供了更友好的 calss 操作方式

  • elem.classList.add(...tokens: string[]):添加类
  • elem.classList.remove(...tokens: string[]):移除类
  • elem.classList.toggle(token: string, force?: boolean): boolean
    • force 可选
      • 不传:切换类——如果类不存在就添加类,存在就移除它
      • true:添加,同 add
      • false:移除,同 remove
    • 返回值:现在是否存在令牌
  • elem.classList.contains(token: string): boolean:检查给定类是否存在
  • elem.classList[Symbol.iterator]:迭代器,项为类名字符串

style

elem.style

elem.style 属性是一个对象,它对应于 "style" attribute 中所写的内容

对于多词 multi-word 属性,使用驼峰式 camelCase:

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

对于前缀属性也遵循同样的规则,连字符 - 表示大写:

-moz-border-radius    => elem.style.MozBorderRadius
-webkit-border-radius => elem.style.WebkitBorderRadius

复合样式

对于复合样式,属性值会进行“解包”,并从中推断出对应的值:

document.body.style.margin = '20px'
 
console.log(document.body.style.margin) // 20px
console.log(document.body.style.marginTop) // 20px
console.log(document.body.style.marginLeft) // 20px

重置样式属性

还原到原来的值:

const lastVal = document.body.style.display
document.body.style.display = "none" // 设置新值
 
setTimeout(() => document.body.style.display = lastVal, 1000) // 还原到原来的值

设置为空值:

document.body.style.display = "" // 设置为空值
 
document.body.style.removeProperty('display') // 删除键
  • elem.style.xxx = "":value 为空串
  • elem.style.removeProperty('xxx'):连 key 都删了

两者虽然有差别,但达到的效果基本相同,就相当于没有设置 style.xxx 一样

elem.style.cssText

使用 style.xxx 只能对某个样式属性进行赋值。

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

想要以字符串的形式设置完整的样式,可以使用特殊属性 style.cssText

<div id="div">Button</div>
 
<script>
  div.style.cssText=`color: red !important;
    background-color: yellow;
    width: 100px;
    text-align: center;
  `
 
  console.log(div.style.cssText)
</script>
  • 可读可写,字符串类型
  • 就像是在写 css 或 style 一样
    • 无需驼峰式
    • 可以设置特殊的样式标记,例如 !important
  • 这样的赋值会删除所有现有样式:不是追加,而是覆盖
  • 设置 attribute:elem.setAttribute('style', 'color: red;...') 可达到相同的效果

window.getComputedStyle()

style property 仅对 "style" attribute 值起作用,而没有任何 CSS 级联(cascade),因此无法使用 elem.style 读取来自 CSS 类的任何内容

  • window.getComputedStyle(element: Element, pseudo?: string):获取元素的最终样式,CSS 属性计算过程
    • element:需要被读取样式值的元素
    • pseudo:伪元素,例如 ::before。空字符串或无参数则意味着元素本身
    • 返回值:一个具有样式属性的对象,像 elem.style

注意:

  • 最终样式:单位会被计算为绝对值 px,而不是相对单位 em%
  • 需要完整的属性名
    • 应该总是使用确切属性,如 paddingLeftmarginTopborderTopWidth
    • getComputedStyle(elem).padding 这样的复合值结果是什么,没有标准的规则,不能保证正确的结果
  • 应用于 :visited 链接的样式被隐藏了
    • 这是浏览器的一个限制,防止检测链接是否被访问,进而窥探隐私