关于 <dl> 元素(2021)
TL;DR · AI 摘要
HTML 的 <dl> 元素用于表示名称-值对列表,具有语义化优势,优于嵌套 div 布局,在无障碍访问方面提升用户体验。
核心要点
- <dl> 元素由 <dt> 和 <dd> 构成,支持一个术语多个值的结构
- 使用语义化标签比嵌套 div 更利于无障碍访问和浏览器识别
- 可将 <dt>/<dd> 组包裹于 <div> 中进行样式控制
结构提纲
按章节快速跳转。
思维导图
用一张图看清主题之间的关系。
查看大纲文本(无障碍 / 无 JS 友好)
- HTML <dl> 元素
- 基本结构
- <dl> 容器
- <dt> 名称
- <dd> 值
- 高级特性
- 多值支持
- 包装容器
- 优势
- 无障碍访问
- 语义清晰
金句 / Highlights
值得收藏与分享的关键句。
<dl> 元素代表一组名称-值对,非常灵活实用。
一个 <dt> 可以拥有多个 <dd>,适用于多作者等场景。
语义化标签比嵌套 div 更有利于无障碍访问和浏览器识别。
引言
[](https://benmyers.dev/blog/on-the-dl/#introduction) <dl>,或称 _描述列表_ 元素,被严重低估了。
它用于表示一组 名称–值对。这是一种常见的 UI 模式,同时又具有 _极高的_ 可扩展性。例如,你可能在现实世界中见过这些布局……
每个示例都展示了一组(或多组)名称–值对。你也可能见过用于描述住宿设施、列出每月租金明细或技术术语词典的名称–值对列表。这些都可以使用 <dl> 元素来表示。
那么它看起来是什么样的呢?
描述列表的结构
[](https://benmyers.dev/blog/on-the-dl/#the-anatomy-of-a-description-list) 我一直在说“<dl>”,但实际上我指的是三个独立的元素:<dl>、<dt> 和 <dd>。
我们从 <dl> 开始。这是 _描述列表_,类似于使用 <ul> 表示无序列表或使用 <ol> 表示有序列表。
<dl>
</dl>很酷。
接下来,我们要添加一个名称–值对。我们将使用 <dt>(即 _描述项_)作为名称,并使用 <dd>(即 _描述详情_)作为值。note 2
<dl>
<dt>标题</dt>
<dd>设计 Web 标准</dd>
</dl>要在列表中添加另一个名称–值对,只需再添加一个 <dt> 和 <dd>:
<dl>
<dt>标题</dt>
<dd>设计 Web 标准</dd>
<dt>出版商</dt>
<dd>New Riders 出版社;第三版(2009年10月19日)</dd>
</dl>但等等——如果我有一个有多个值的项怎么办?比如这本书有多个作者?
这也没问题!一个 <dt> 可以有多个 <dd>:
<dl>
<dt>标题</dt>
<dd>设计 Web 标准</dd>
<dt>作者</dt>
<dd>Jeffrey Zeldman</dd>
<dd>Ethan Marcotte</dd>
<dt>出版商</dt>
<dd>New Riders 出版社;第三版(2009年10月19日)</dd>
</dl>对于大多数基本用例来说,描述列表结构的最后一部分是:如果我想为了样式原因将 <dt> 和它的 <dd> 包裹起来该怎么办?
在这种情况下,规范允许你将 <dt> 和其对应的 <dd> 包裹在一个 <div> 中:
<dl>
<div>
<dt>标题</dt>
<dd>设计 Web 标准</dd>
</div>
<div>
<dt>作者</dt>
<dd>Jeffrey Zeldman</dd>
<dd>Ethan Marcotte</dd>
</div>
<div>
<dt>出版商</dt>
<dd>New Riders 出版社;第三版(2009年10月19日)</dd>
</div>
</dl>像这样的包装 <div> 是唯一可以包裹那些 <dt> / <dd> 组的元素。
就是这样!这就是描述列表的结构,HTML 中语义化标记名称–值组列表的方式!
我们为什么需要这种语义呢?
[](https://benmyers.dev/blog/on-the-dl/#why-do-we-need-semantics-for-this-anyways) 在我们了解 <dl>、<dt> 和 <dd> 元素之前,我的团队经常使用嵌套的 <div> 来实现这种模式。它看起来像这样:
<div class="book-details">
<div class="book-details--item">
<div class="book-details--label">
标题
</div>
<div class="book-details--value">
设计 Web 标准
</div>
</div>
<div class="book-details--item">
<div class="book-details--label">
作者
</div>
<div class="book-details--value">
Jeffrey Zeldman
</div>
<div class="book-details--value">
Ethan Marcotte
</div>
</div>
<div class="book-details--item">
<div class="book-details--label">
出版商
</div>
<div class="book-details--value">
New Riders 出版社;第三版(2009年10月19日)
</div>
</div>
</div>这个结构包含了关于这本书的所有信息,对吧?那为什么我们需要为名称–值对列表引入语义呢?难道不能用一系列嵌套的 <div> 来完成吗?
在判断某个模式是否适合使用语义元素时,我发现问自己一个问题很有帮助:“如果计算机能够识别这种模式,我们能获得哪些好处——即使是理论上的?” 在这种情况下,如果浏览器能够识别出名称–值对列表,我们又能得到什么提升呢?
这个问题的答案会因人而异。我花了很多时间倡导网页无障碍访问,因此我的第一反应是屏幕阅读器如何解释这种模式。我能想到几个屏幕阅读器用户可能从中受益的地方:
- 屏幕阅读器可以告诉用户列表中有多少个名称–值对。
- 屏幕阅读器可以告诉用户当前在列表中的位置。
- 屏幕阅读器可以把整个列表当作一个整体,让用户跳过它,如果他们对此不感兴趣的话。
所有这些都能让列表比一系列嵌套的 <div> 更好用,因为后者会把列表中的每个名称和值都当作独立的文本节点处理。
如果你能想到哪怕是一些理论上来自设备识别该模式的好处,那么这个模式就很可能值得赋予一些语义。
值得一提的是,这些屏幕阅读器体验并非假设——它们确实是屏幕阅读器用户在大多数浏览器和屏幕阅读器组合中真正获得的好处 见 a11ysupport.io。当然,目前 <dl> 元素的支持尚未普及。你可能会认为屏幕阅读器的回退行为——将列表视为独立文本节点——对你的情况不够理想,因此选择使用 <ul> 直到支持改善。
好吧,好吧,最后一个例子!
[](https://benmyers.dev/blog/on-the-dl/#okay-okay-one-last-example) 我最喜欢的示例,真正让我觉得惊艳的那个例子,就是《龙与地下城》(Dungeons & Dragons)的属性面板,它实际上就是“所有都是名称–值对”的典型代表!
真的,光看这个属性面板,你能看到多少个 <dl> 的候选对象?
我个人数了五个可能的描述列表。这是我的标记方式:
<div>
<h1>狗头人</h1>
<small>小型类人生物(狗头人),守序邪恶</small>
<dl>
<div>
<dt>护甲等级</dt>
<dd>12</dd>
</div>
<div>
<dt>生命值</dt>
<dd>5(2d6 - 2)</dd>
</div>
<div>
<dt>移动速度</dt>
<dd>30英尺</dd>
</div>
</dl>
<dl aria-label="能力值">
<div>
<dt>力量</dt>
<dd>7(-2)</dd>
</div>
<div>
<dt>敏捷</dt>
<dd>15(+2)</dd>
</div>
<div>
<dt>体质</dt>
<dd>9(-1)</dd>
</div>
<div>
<dt>智力</dt>
<dd>8(-1)</dd>
</div>
<div>
<dt>感知</dt>
<dd>7(-2)</dd>
</div>
<div>
<dt>魅力</dt>
<dd>8(–1)</dd>
</div>
</dl>
<dl aria-label="熟练项">
<div>
<dt>感官</dt>
<dd>黑暗视觉 60 英尺</dd>
<dd>被动察觉 8</dd>
</div>
<div>
<dt>语言</dt>
<dd>通用语</dd>
<dd>龙语</dd>
</div>
<div>
<dt>挑战等级</dt>
<dd>1/8(25经验值)</dd>
</div>
</dl>
<dl aria-label="特性">
<div>
<dt>阳光敏感</dt>
<dd>
在阳光下时,狗头人在攻击检定中以及依赖视觉的感知检定中均受到劣势。
</dd>
</div>
<div>
<dt>群体战术</dt>
<dd>
若狗头人的一个盟友在目标 5 英尺内且未被禁用,则狗头人对目标的攻击检定具有优势。
</dd>
</div>
</dl>
<h2 id="actions">行动</h2>
<dl aria-labelledby="actions">
<div>
<dt>匕首</dt>
<dd>
<i>近战武器攻击:</i>命中加4,触及5英尺,单个目标。<i>命中:</i>(1d4 + 2)穿刺伤害。
</dd>
</div>
<div>
<dt>弹弓</dt>
<dd>
<i>远程武器攻击:</i>命中加4,射程30/120英尺,单个目标。<i>命中:</i>(1d4 + 2)钝击伤害。
</dd>
</div>
</dl>
</div>这只是标记该属性面板的一种方式。
我喜欢这个例子作为演示,因为它真正展示了描述列表模式有多么灵活——能力值(如力量、敏捷等)和攻击列表看起来完全不同,但描述列表模式却能涵盖它们。
总结
[](https://benmyers.dev/blog/on-the-dl/#takeaways) 名称–值对(或在某些情况下是名称–值组)的列表是一种常见的网页模式,部分原因在于其灵活性。HTML 允许我们使用三个元素的组合来标记这些列表:
- `<dl>`,即 _描述列表_ 元素,用于包裹整个名称–值对列表
- `<dt>`,即 _描述术语_ 元素,表示名称–值对中的名称
- `<dd>`,即 _描述详情_ 元素,表示名称–值对中的值
赋予这类模式语义,可以为用户的设备提供所需的信息,以构建有用且可用的体验——通常是我们开发者意想不到的方式。
想了解更多关于描述列表的内容及其允许或不允许的用法,我推荐查阅 MDN 上关于 `<dl>` 的文档,或者直接查看规范!
- * *
脚注
[](https://benmyers.dev/blog/on-the-dl/#footnotes)
- 在 HTML5 之前,这被称为 _定义列表_。这是因为
<dl>最初仅用于表示术语及其定义的词汇表。 | [回到 [1]](https://benmyers.dev/blog/on-the-dl/#fn-ref-1)
- 以前分别被称为 _定义术语_ 和 _定义详情_ 元素。 | [回到 [2]](https://benmyers.dev/blog/on-the-dl/#fn-ref-2)
- * *