Chrome 中的自定义状态伪类

Avatar of Šime Vidas
Šime Vidas

DigitalOcean 为您旅程的每个阶段提供云产品。立即开始使用 200 美元的免费额度!

网络平台上“自定义”功能的数量正在不断增加。我们有自定义属性 (--my-property)、自定义元素 (<my-element>) 和自定义事件 (new CustomEvent('myEvent'))。在某个时刻,我们甚至可能会获得 自定义媒体查询 (@media (--my-media))。

但这还不是全部!您可能错过了它,因为它没有在 Google 的 “Chrome 90 新功能” 文章中提及(公平地说,声明式 Shadow DOM 在此版本中抢尽风头),但 Chrome 刚刚添加了对另一种“自定义”功能的支持:自定义状态伪类 (:--my-state)。

内置状态

在讨论自定义状态之前,让我们快速了解一下为内置 HTML 元素定义的内置状态。 CSS 选择器模块 和 HTML 标准的 “伪类”部分 指定了许多可用于匹配不同状态下元素的伪类。以下伪类在当今的浏览器中都得到了广泛的支持

用户操作
:hover 鼠标光标悬停在元素上
:active 用户正在激活元素
:focus 元素具有焦点
:focus-within 元素具有或包含焦点
位置
:visited 用户已访问过链接
:target 元素是页面 URL 片段的目标
输入
:disabled 表单元素已禁用
:placeholder-shown 输入元素显示占位符文本
:checked 复选框或单选按钮已选中
:invalid 表单元素的值无效
:out-of-range 输入元素的值在 指定范围之外
:-webkit-autofill 浏览器已自动填充输入元素
其他
:defined 自定义元素已注册

注意:为简洁起见,省略了一些伪类,并且某些描述没有提及所有可能的用例。

自定义状态

与内置元素类似,自定义元素也可以具有不同的状态。使用自定义元素的网页可能希望为这些状态设置样式。自定义元素可以通过其宿主元素上的 CSS 类 (class 属性) 公开其状态,但这被 认为是一种反模式

Chrome 现在支持用于向自定义元素添加内部状态的 API。这些自定义状态通过自定义状态伪类公开给外部页面。例如,使用 <live-score> 元素的页面可以为该元素的自定义 --loading 状态声明样式。

live-score {
  /* default styles for this element */
}

live-score:--loading {
  /* styles for when new content is loading */
}

让我们向 <labeled-checkbox> 元素添加 --checked 状态

自定义状态伪类 规范包含一个完整的代码示例,我将使用它来解释 API。此功能的 JavaScript 部分位于自定义元素的类定义中。在构造函数中,为自定义元素创建了一个“元素内部”对象。然后,可以在内部 states 对象上设置和取消设置自定义状态。

请注意,ElementInternals API 确保自定义状态对于外部是 只读的。换句话说,外部页面无法修改自定义元素的内部状态。

class LabeledCheckbox extends HTMLElement {
  constructor() {
    super();

    // 1. instantiate the element’s “internals”
    this._internals = this.attachInternals();

    // (other code)
  }

  // 2. toggle a custom state
  set checked(flag) {
    if (flag) {
      this._internals.states.add("--checked");
    } else {
      this._internals.states.delete("--checked");
    }
  }

  // (other code)
}

网页现在可以通过相同名称的自定义伪类为自定义元素的内部状态设置样式。在我们的示例中,--checked 状态通过 :--checked 伪类公开。

labeled-checkbox {
  /* styles for the default state */
}

labeled-checkbox:--checked {
  /* styles for the --checked state */
}
在 Chrome 中试用演示

此功能尚未成为标准

浏览器供应商在过去 三年 中一直在讨论如何通过自定义伪类公开自定义元素的内部状态。Google 的 自定义状态伪类 规范仍然是 WICG 托管的“非正式草案”。该功能在 W3C TAG 进行了 设计审查,并已 移交给 CSS 工作组。在 Chrome 的“发布意图”讨论中,Mounir Lamouri 写道

看起来此功能得到了良好的支持。听起来,只要它没有得到广泛发布,网页开发人员就很难从中受益,但希望 Firefox 和 Safari 也会遵循并实现它。必须有人首先实现它,并且鉴于没有预见的向后不兼容的更改,因此先走一步似乎是安全的。

现在我们必须等待 Firefox 和 Safari 中的实现。浏览器错误已提交 (Mozilla #1588763WebKit #215911),但尚未引起太多关注。