返回资讯中心
外部精选
软件工程
#开发者实时流

Firefox Nightly 153 测试 headingoffset 属性,可动态调整标题层级

来源标题:Overriding Heading Levels with the Headingoffset HTML Attribute

Firefox Nightly 153 在 dom.headingoffset.enabled 标志后引入了 headingoffset HTML 属性,用于改变标题元素(h1–h6)的级别。该属性的值会与标题原始级别相加,并支持通过嵌套容器向下传递。目前该特性仅在 Firefox Nightly 中提供,需所有浏览器支持后才可实际使用。

Hacker News 最新ibobev2026/11/2 · 2 天前14 分钟阅读

以下正文由 AI 翻译自 Hacker News 最新(原文版权归原站所有),可能存在偏差,重要内容请以原文为准。

有些场景下我们可能需要改变标题的级别(<h1>–<h6>)。举个例子,我们创建了一个带有 <h1> 的组件,但随后在另一个上下文中使用该组件时,它需要是 <h2>。我知道,我知道,这正是组件 props 的用途,但 headingoffset HTML 属性是另一种选择。

另一个例子:标题层级是错的,但我们对 HTML 没有完全的控制权。headingoffset 也许能解决这个问题,取决于我们能访问到哪些 HTML。

Firefox Nightly 153 在 dom.headingoffset.enabled 标志后面发布了 headingoffset,所以我们还有很长的路要走,而且在所有浏览器都支持它之前它并不能真正投入使用,但现在很值得一看。

headingoffset 示例

其实挺简单的:

<h1 headingoffset="2">1 + 2 = Heading 3</h1>

它也会向下传递:

<div headingoffset="3">
  <h1>3 + 1 = Heading 4</h1>
  <h2>3 + 2 = Heading 5</h2>
</div>

所以……是数学?

没错!我们只需把 headingoffset 的值加到标题的级别上,即使标题嵌套在多个带有 headingoffset 值的容器中,甚至标题自身也带有 headingoffset 值,也是如此:

<div headingoffset="2">
  <div headingoffset="3">
    <h1>2 + 3 + 1 = Heading 6</h1>
    <h2>2 + 3 + 2 = Heading 7</h2>
    <h3 headingoffset="1">2 + 3 + 3 + 1 = Heading 9</h3>
  </div>
</div>

等等,7?Heading 7?还有 Heading 9?没错!

事实上,headingoffset 接受 0 到 8 的整数。不过,标题级别上限为 9,所以如果我们给 <h6> 加上 headingoffset=8,它不会变成 Heading 14,而且我实在想不出我们为什么需要那样。

<!-- Heading level capped at 9 -->
<h6 headingoffset="8">Heading 9</h6>

怀疑?我们可以(也应该)用 DevTools 验证:

为 headingoffset 标题设置样式

要为受 headingoffset 影响的标题设置样式,使其在视觉上与新的语义含义相匹配,我们需要用 :heading() 伪类函数(它选择具有指定计算标题级别的标题,无论元素实际是什么)替换元素选择器(<h1>–<h6>)。

<div headingoffset="2">
  <h1>2 + 1 = Heading 3</h1>
</div>
h3 {
  /* 不会选中该标题,因为它是 <h1> */
}

:heading(3) {
  /* 会选中该标题,因为它计算为 Heading 3 */
}

headingreset

headingreset 属性的作用与你想的完全一样。它移除 headingoffset 的影响,使标题元素(<h1>–<h6>)决定标题级别。它基本上就是 headingoffset 的氪星石。

一个合适的使用场景是确保 headingoffset 不会影响主文档之外的标题(例如 <aside> 和模态 <dialog> 中的标题):

<div headingoffset="2">
  <h1>2 + 1 = Heading 3</h1>
  <dialog headingreset>
    <h1>Heading 1</h1>
  </dialog>
</div>

但如果一个元素同时使用了 headingreset 和 headingoffset 呢?在这种情况下,headingreset 会切断任何外部影响;不过,应用于同一元素的 headingoffset 仍会生效。在下面的例子中,外层的 headingoffset=2 被 headingreset 取消,而 headingoffset=3 加到 <h1> 上,结果是 Heading 4:

<div headingoffset="2"><!-- Cancelled -->
  <h1 headingoffset="3" headingreset>1 + 3 = Heading 4</h1>
</div>

aria-level 在这里起什么作用?

aria-level 属性会覆盖标题的级别,无论它们是否受 headingoffset 影响。和 headingoffset 一样,aria-level 的上限也是 9。

此外,aria-level 也可以用在非标题元素上,把它们变成标题。我想不出这样做的实际理由,但大概会是这样:

<div role="heading" aria-level="1">Heading 1</div>

归根结底,headingoffset 是累加的,而 aria-level 是决定性的,并且直接应用于标题。

使用 headingoffset

我有时很难追踪标题层级,尤其是在大型网页上,当这些网页由多个文件包含组成时更是如此。我想这就是为什么 DevTools 里要有无障碍功能,对吧?不过,使用太多 headingoffset、在不同文件中使用它们,和/或在 DOM 树中更靠上的位置(离它们影响的标题更远)使用它们,都会让追踪层级变得更加困难。就个人而言,我会谨慎使用 headingoffset 和 headingreset,但 HTML 注释可以提供一些清晰度:

<!-- Main document -->
{% include "component.html" %}
<div headingoffset="1">
  {% include "component.html" %}
</div>
<!-- component.html -->
<div>
  <!-- headingoffset may influence this heading -->
  <h1>Heading</h1>
</div>

或者……

我突发奇想的一个点子:复现文档大纲算法(那个从未存在过的算法),它本会让所有标题元素平等。取而代之的是,标题的级别本应由它们在 <section> 等分区元素中嵌套的深度来决定。我记不清为什么它没有实现了,但我确实认为 headingoffset 可以用来实现同样的累加效果:

<h1>Heading 1</h1>
<div headingoffset="1">
  <h1>Heading 2</h1>
  <div headingoffset="1">
    <h1>Heading 3</h1>
    <div headingoffset="1">
      <h1>Heading 4</h1>
      <div headingoffset="1">
        <h1>Heading 5</h1>
        <div headingoffset="1">
          <h1>Heading 6</h1>
        </div>
      </div>
    </div>
  </div>
</div>

欢迎分享你的想法!

正文由 探How 从来源站点 RSS 同步,内容未经改写;遇到排版缺失或需要图片、视频时请以原文为准。

打开原文
去社区讨论 →