关于 <dl> 元素(2021)
- #HTML
- #语义化
- #前端开发
- #无障碍
- #Hacker News
引言
<dl> 元素,即描述列表(description list),是一种被低估的 HTML 元素。它用于表示名称-值对的列表。这是一种常见的 UI 模式,同时具有难以置信的灵活性。例如,你可能在网页上见过这样的布局……
这些例子都展示了名称-值对的列表。你可能还见过描述住宿设施、列出月租金明细或技术术语词汇表的名称-值对列表。这些都可以用 <dl> 元素来表示。那么它长什么样呢?
描述列表的结构
我刚才说的“<dl>”实际上是指三个独立的元素:<dl>、<dt> 和 <dd>。
我们从一个 <dl> 开始。这是描述列表1,类似于使用 <ul> 表示无序列表或 <ol> 表示有序列表。
<dl>
</dl>
接下来,我们要添加一个名称-值对。我们将使用 <dt>(description term 的缩写)作为名称,使用 <dd>(description detail 的缩写)作为值2。
<dl>
<dt>Title</dt>
<dd>Designing with Web Standards</dd>
</dl>
要向列表中添加另一个名称-值对,我们再添加一个 <dt> 和 <dd>:
<dl>
<dt>Title</dt>
<dd>Designing with Web Standards</dd>
<dt>Publisher</dt>
<dd>New Riders Pub; 3rd edition (October 19, 2009)</dd>
</dl>
但是等等——如果我的一个术语对应多个值呢?例如,这本书有多个作者怎么办?没问题!一个 <dt> 可以有多个 <dd>:
<dl>
<dt>Title</dt>
<dd>Designing with Web Standards</dd>
<dt>Author</dt>
<dd>Jeffrey Zeldman</dd>
<dd>Ethan Marcotte</dd>
<dt>Publisher</dt>
<dd>New Riders Pub; 3rd edition (October 19, 2009)</dd>
</dl>
对于大多数基本用例,描述列表结构还有最后一点要介绍:如果我想出于样式原因将 <dt> 及其 <dd> 包裹起来怎么办?在这种情况下,规范允许你将 <dt> 和它的 <dd> 包裹在一个 <div> 中:
<dl>
<div>
<dt>Title</dt>
<dd>Designing with Web Standards</dd>
</div>
<div>
<dt>Author</dt>
<dd>Jeffrey Zeldman</dd>
<dd>Ethan Marcotte</dd>
</div>
<div>
<dt>Publisher</dt>
<dd>New Riders Pub; 3rd edition (October 19, 2009)</dd>
</div>
</dl>
像这样的包装 <div> 是唯一可以包裹这些 <dt>/<dd> 组的元素。就是这样!这就是描述列表的结构,HTML 中用于标记名称-值组列表的语义方式!
为什么我们需要语义?
在我们了解 <dl>、<dt> 和 <dd> 元素之前,我的团队总是使用嵌套的 <div> 来实现这种模式。它看起来像这样:
<div class="book-details">
<div class="book-details--item">
<div class="book-details--label"> Title </div>
<div class="book-details--value"> Designing with Web Standards </div>
</div>
<div class="book-details--item">
<div class="book-details--label"> Author </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"> Publisher </div>
<div class="book-details--value"> New Riders Pub; 3rd edition (October 19, 2009) </div>
</div>
</div>
这包含了关于这本书的所有信息,对吧?如果像嵌套 <div> 这样的东西就能完成工作,我们为什么还需要为名称-值组列表提供语义呢?
在确定某个模式是否适合使用语义元素时,我发现问这样一个问题很有帮助:“如果计算机能够识别这个模式,我们可能获得哪些好处(即使是理论上的)?”在这种情况下,如果浏览器能够以某种方式识别出名称-值组列表,我们能获得什么提升?
这个问题的答案各不相同。我经常倡导网页无障碍,所以我的第一反应往往是屏幕阅读器如何解读这种模式。我立刻就能想到屏幕阅读器用户可以从识别这种模式中获得几个好处:
- 屏幕阅读器可以告诉用户列表中有多少个名称-值组。
- 屏幕阅读器可以告诉用户他们在列表中的位置。
- 屏幕阅读器可以将列表视为一个块,如果用户不感兴趣,可以跳过它。
所有这些都使得列表比嵌套的 <div> 更易于使用,因为嵌套的 <div> 会将列表中的每个名称和值视为独立的文本节点。
如果你能想到用户设备识别模式后带来的几个即使是理论上的好处,那么这个模式很可能就是拥有相关语义的有力候选。
值得一提的是,这些屏幕阅读器体验不是假设性的——在大多数浏览器/屏幕阅读器组合中,使用 <dl> 确实能给屏幕阅读器用户带来这些好处。然而,必须承认,对于 <dl> 元素的支持尚未普及。你可能会认为屏幕阅读器的降级体验——将列表视为独立文本节点——对你的用例来说不够充分,从而选择使用 <ul> 之类的元素,直到支持得到改善。
再来一个例子!
我最喜欢的例子是《龙与地下城》的人物属性块,这简直就是“哎呀!全是名称-值对!”真的,光在这个属性块中,你能看到多少个适合使用 <dl> 的地方?我自己数出了五个可能的描述列表。
下面是我选择如何标记它的方式:
<div>
<h1>Kobold</h1>
<small>Small humanoid (kobold), lawful evil</small>
<dl>
<div>
<dt>Armor Class</dt>
<dd>12</dd>
</div>
<div>
<dt>Hit Points</dt>
<dd>5 (2d6 - 2)</dd>
</div>
<div>
<dt>Speed</dt>
<dd>30 ft.</dd>
</div>
</dl>
<dl aria-label="Ability Scores">
<div>
<dt>STR</dt>
<dd>7 (-2)</dd>
</div>
<div>
<dt>DEX</dt>
<dd>15 (+2)</dd>
</div>
<div>
<dt>CON</dt>
<dd>9 (-1)</dd>
</div>
<div>
<dt>INT</dt>
<dd>8 (-1)</dd>
</div>
<div>
<dt>WIS</dt>
<dd>7 (-2)</dd>
</div>
<div>
<dt>CHA</dt>
<dd>8 (–1)</dd>
</div>
</dl>
<dl aria-label="Proficiencies">
<div>
<dt>Senses</dt>
<dd>Darkvision 60 ft.</dd>
<dd>Passive Perception 8</dd>
</div>
<div>
<dt>Languages</dt>
<dd>Common</dd>
<dd>Draconic</dd>
</div>
<div>
<dt>Challenge</dt>
<dd>1/8 (25 XP)</dd>
</div>
</dl>
<dl aria-label="Traits">
<div>
<dt>Sunlight Sensitivity</dt>
<dd> While in sunlight, the kobold has disadvantage on attack rolls, as well as on Wisdom (Perception) checks that rely on sight. </dd>
</div>
<div>
<dt>Pack Tactics</dt>
<dd> The kobold has advantage on an attack roll against a creature if at least one of the kobold's allies is within 5 ft. of the creature and the ally isn't incapacitated. </dd>
</div>
</dl>
<h2 id="actions">Actions</h2>
<dl aria-labelledby="actions">
<div>
<dt>Dagger</dt>
<dd> <i>Melee Weapon Attack:</i> +4 to hit, reach 5 ft., one target. <i>Hit:</i> (1d4 + 2) piercing damage. </dd>
</div>
<div>
<dt>Sling</dt>
<dd> <i>Ranged Weapon Attack:</i> +4 to hit, reach 30/120 ft., one target. <i>Hit</i>: (1d4 + 2) bludgeoning damage. </dd>
</div>
</dl>
</div>
这只是你可以选择标记该属性块的一种方式。我喜欢用这个演示,因为它真的展示了描述列表模式可以多么灵活——能力值列表(STR、DEX 等)和攻击列表看起来非常不同,但描述列表模式却都能涵盖。
要点
- 名称-值对(有时是名称-值组)列表是 Web 上常见的模式,部分原因是它们的灵活性。
- HTML 允许我们使用三个元素的组合来标记这些列表:
<dl>(描述列表元素,包裹整个名称-值对列表)、<dt>(描述术语元素,表示名称-值对中的名称)和<dd>(描述详情元素,表示名称-值对中的值)。 - 为这类模式赋予语义,能让用户设备获得所需信息,从而策划出有用、可用的体验——这些方式往往是我们开发者意想不到的。
- 要了解更多关于描述列表以及允许/不允许的内容,我推荐 MDN 上关于
<dl>的文档,或者直接查阅规范!
评论