HTML 列表通常被认为比较单调,功能有限,因此我们往往忽略了它们广泛的应用。 尽管如此,我们仍然可以使用一些老方法来定制列表,例如移除标记、反转顺序和创建自定义计数器。
然而,在使用列表时,也有一些“新的”知识点,甚至包括潜在的风险需要注意。这些风险大多微不足道,但其发生频率远超你的想象。我们将探讨这些风险,以及一些新的列表用法,甚至是一些改进旧方法的新思路。
需要明确的是,本文讨论的 HTML 元素包括:
<dl></dl>
<menu></menu>
有序列表、无序列表和交互式列表都包含列表项 (<code><li>
),其显示方式取决于列表类型。有序列表 (<ol></ol>
) 在列表项旁边显示数字;无序列表 (<code><ul></ul>
) 和菜单元素 (<menu></menu>
) 在列表项旁边显示项目符号。我们称这些为“列表标记”,甚至可以使用 ::marker
伪元素对其进行样式设置。描述列表使用描述术语 (<dt></dt>
) 和描述细节 (<dd></dd>
),而不是数字或项目符号,通常用于显示元数据和词汇表,但在实际应用中并不常见。
让我们从简单的部分开始——如何正确(至少在我看来)重置列表样式。之后,我们将探讨一些可访问性问题,然后重点介绍难以捉摸的 <menu></menu>
元素,你可能会惊讶地发现……它实际上也是一种列表!
浏览器会自动应用其自身的 User Agent 样式来帮助列表的视觉结构。这有时非常有用!但如果我们想从一个没有样式的空白状态开始,那么我们必须首先重置这些样式。
例如,我们可以很容易地移除列表项旁边的标记。这里没有什么新东西:
/* 清除所有列表标记! */ ol, ul, menu { list-style: none; }
但是现代 CSS 提供了新的方法来帮助我们定位特定的列表实例。假设我们想要清除所有列表的标记,但如果这些列表出现在长篇内容(如文章)中,则保留标记。如果我们结合使用较新的 CSS 伪类函数 :where()
和 :not()
,我们可以隔离这些实例并在这些情况下允许标记:
/* 对于不是文章中的列表... */ :where(ol, ul, menu):not(article :where(ol, ul, menu)) { list-style: none; }
为什么使用 :where()
而不是 :is()
?where()
的特异性始终为零,而 :is()
则采用其选择器列表中最特定元素的特异性。因此,使用 :where()
是一个不太强制性的覆盖方法,并且很容易被自身覆盖。
UA 样式还会应用填充,以将列表项的内容与其标记分隔开。在某些情况下,这是一种不错的默认效果,但如果我们像上面那样已经移除了列表标记,那么我们不妨也清除该填充。这又是 :where()
的另一个用例:
/* 清除所有列表标记! */ ol, ul, menu { list-style: none; }
好的,这将防止无标记的列表项看起来悬浮在空间中。但是我们有点矫枉过正,在所有情况下都去除了填充,包括我们之前在 <article></article>
中隔离的那些。所以,现在那些带有标记的列表有点悬挂在内容框的边缘之外。
请注意,UA 样式会额外向 <menu></menu>
元素应用 40px 的填充。所以我们要做的是防止列表标记“悬挂”在容器外部。我们可以使用 list-style-position
属性来解决这个问题:
或者不……也许这取决于风格偏好?
不幸的是,即使在现代,列表也存在一些可访问性问题。一个问题是应用 list-style: none;
的结果,就像我们在重置 UA 样式时所做的那样。
简而言之,Safari 不会将使用 list-style: none;
样式化的有序和无序列表读取为实际列表,例如使用屏幕阅读器导航内容时。换句话说,移除标记也会移除列表的语义含义。解决方法是在列表上应用 ARIA 列表角色,并在列表项上应用列表项角色,以便屏幕阅读器可以识别它们:
/* 对于不是文章中的列表... */ :where(ol, ul, menu):not(article :where(ol, ul, menu)) { list-style: none; }
奇怪的是,Safari 将此视为一项功能而不是错误。基本上,用户会报告屏幕阅读器宣布了过多的列表(因为开发人员倾向于过度使用它们),所以现在,只有那些具有 role="list"
的列表才会被屏幕阅读器宣布,这实际上并不奇怪。Scott O’Hara 对这一切是如何发生的进行了详细的描述。
第二个可访问性问题不是我们造成的(万岁!)。所以,你知道你应该为没有标题的元素添加 aria-label
吗?好吧,有时对不包含有助于描述列表的标题元素的列表执行相同的操作也是有意义的。
:where(ol, ul, menu) { padding-left: 0; /* 或 padding-inline-start */ }
你绝对不必使用这两种方法。使用标题或 ARIA 标签只是增加了上下文,而不是要求——请务必使用屏幕阅读器测试你的网站,并选择最适合当前情况的用户体验。
在相关的新闻中,Eric Bailey 写了一篇关于为什么以及如何认为 aria-label
是代码异味的文章。
<menu></menu>
也是列表?好的,所以,你可能想知道我一直在代码示例中插入的所有 <menu></menu>
元素。这实际上非常简单;菜单是无序列表,只是它们用于交互式项目。它们甚至在可访问性树中作为无序列表显示。在语义网的早期,我错误地认为菜单类似于 <nav></nav>
,然后认为它们用于上下文菜单(或规范所说的“工具栏”),因为这是 HTML 规范的早期版本所说的。(如果你感兴趣,MDN 对所有与 <menu></menu>
相关的已弃用内容有一个有趣的介绍。)
然而,今天,这是使用菜单的语义方式:
/* 清除所有列表标记! */ ol, ul, menu { list-style: none; }
就我个人而言,我认为 <menu></menu>
有一些很好的用例。最后一个示例显示了一个包含在带标签的 <menu></menu>
元素中的社交分享按钮列表,值得注意的是,“分享文章”标签贡献了大量上下文,有助于描述按钮的功能。菜单绝对必要吗?不。它们是 HTML 里程碑吗?绝对不是。但是,如果你喜欢更少的 <div>,并且你认为组件可以使用 <code>aria-label
来提供额外的上下文,那么它们就在那里。
是的,还有前面提到的 <dl></dl>
(描述列表)元素,但是,MDN 似乎并不认为它们与其他列表相同——它是由术语组成的组列表——而且我不能说我真正见过它们被使用。根据 MDN 的说法,它们应该用于元数据、词汇表和其他类型的键值对。我会避免使用它们,因为所有屏幕阅读器对它们的宣布方式都不同。但是,让我们不要以负面评价结尾。以下是可以使用列表执行的一些非常酷的事情:
以上是关于好ol'HTML列表的较新的知识的详细内容。更多信息请关注PHP中文网其他相关文章!