"我应该使用<section> 还是<article> 元素?"每当我需要在一个容器元素中分组内容时,我都不得不问自己这个问题,次数多得不正常。
我在Twitter上的一次谈话促使我研究这个问题,并最终写下了这篇文章。在与Grace Snow的对话中,我分享了我喜欢使用的编写HTML的方法。我喜欢先写出我的HTML结构(方框),而不写内容,以确保我在写HTML的时候不会考虑到造型问题。然后她发现,在我真诚地尝试语义化的过程中,我对section 和article 元素的使用可能存在问题。
事实证明,要在section 和article 之间做出选择,我们需要我们的内容。事实上,为了确定我们的内容是否已经缩小到这两个,我们需要我们的内容。
我们可以建立一个心理模型,通过考虑我们的内容,确保我们每次都做出最好的决定。
让我们深入了解一下吧!
文件语义
HTML向用户设备传递两种相关但不同的信息。第一个是视觉表现信息,它告诉设备如何默认显示文档。
第二种被称为语义信息,或者简单地说,语义。它传达了文件中的*"含义",即每个元素的目的和它们之间的关系。在这个意义上,规范会说,一个元素"代表 "着什么。因此,当你在规范中看到"代表 "*时,随之而来的是元素中嵌入的语义信息。
h1 这个元素揭示了这两组信息的存在。 h1 元素的视觉表现信息,当浏览器遇到时,就是为什么它看起来是粗体的,而且字体大小比文档的其他部分大。 h1 所代表的语义信息是,它是该部分的最高级别标题。
有视力的用户可以通过观察视觉效果,从浏览器等设备中摸索出语义。对于标题,我们可以根据字体大小和重量的不同进行区分,如果是列表,则可以根据是否有子弹头标记或编号标记进行区分。对于不依赖视觉的用户来说,语义只能通过选项或设备来获取,这些选项或设备允许他们要求以其他可能不是视觉的方式宣布语义信息。这些选项和设备通常被称为辅助技术。
HTML规定了一些向浏览器传达隐含意义的元素,浏览器可以将其提取到可访问性API中,使其可用于辅助技术,而辅助技术反过来又将这种意义解释给用户。这种意义使用户对他们所访问的网页有一个健康的感觉,如文件结构和导航帮助,或者在本案例中,文件结构和导航帮助。
然而,并不是只有直接包裹文本内容的元素才携带语义信息。旨在分组其他元素的元素也携带一些意义;在某些情况下,它可能是我们想要传达的意义。
我的分组是否发挥了语义作用?
我们心智模式的第一步是质疑,像我们将要做的那样对内容进行分组,对于文档结构来说是否有意义。分解开来,我会以这种方式问自己。
- 这个区块的内容是否有可能有一些共同点,从而在一起阅读时为我的文档结构增加一些意义?
- 如果我向一个人描述我的文件结构,而不向他们展示,我是否会提到有那个特别的分组区域,以便他们欣赏文件结构?
如果这些问题的答案是 "不",那么你可能会遇到这样的情况:<div> ,就像斯科特-奥哈拉指出的那样,可能是合适的。阅读Scott的文章可以帮助你进一步检查你的分组所起的作用,甚至制定一套比我更好的问题。我不打算在这篇文章中介绍<div> ,因为斯科特已经充分地介绍了这个问题。我只想说,首先,你必须确认你所做的分组是受文档结构影响的。如果是的话,你就可以继续进一步询问,以确定它是一个<article> 还是<section> 。
要明确的是,我并不是说分组必须只受到文档结构的影响,你才开始考虑<article> 或<section> 。只要它是可能的原因之一就足够了。例如,你分组中的内容有可能共享一个独特的设计或语言,同时又影响到文档的语义。
我的分组发挥什么语义作用?
我们现在已经决定,分组的内容在描述文档方面有一些功能。下一步是确定article 或section 元素已经承载的语义中,哪一个最准确地描述了你的分组内容在文档结构中所要发挥的功能。
HTML规范说什么
让我们看看HTML的主要权威来源,并开始形成我们对section 和article 元素及其固有语义的理解。
文档、页面、应用程序或网站中的一个完整或自足的构成,并且原则上可独立分发或重复使用,例如,在辛迪加。这可以是一个论坛帖子,一篇杂志或报纸文章,一个博客条目,一个用户提交的评论,一个互动的小部件或小工具,或任何其他独立的内容项目。
关于section 元素,《HTML生活标准》是这样定义的。
section元素代表一个文件或应用程序的通用部分。在这种情况下,一个章节是一个内容的主题分组,通常有一个标题...章节的例子是章节,标签式对话框中的各种标签页,或论文中的编号章节。一个网站的主页可以被分成介绍、新闻项目和联系信息等部分。
为了帮助进一步缩小范围,规范对何时使用section 元素提供了这样的线索。
.....
链接的规范给出了相当详尽的例子。然而,可以说,这种选择似乎有很大的主观性。作者必须主动决定他们想出的特定组是否是 "完整的 "和 "可独立分发的",在这种情况下,选择的是article ,或者是 "内容的主题分组",在这种情况下,选择的是section 。 让我们考虑一些任务。
如果你要建立一个像Smashing杂志那样的博客,你会用哪些元素来包装登陆页面中包含所有博客文章预告列表的部分?在这个被包裹的部分中,什么元素会包裹每个博客文章的预告?如果你点击其中一个博文预告,并登陆到扩展的文章页面,哪些元素会包裹住这篇博文?
如果你要建立Twitter,你会不会把每条送入用户时间线的推文包装在一个article ,因为它们是 "自成一体 "和 "原则上可独立发布 "的?或者你会把它们包装在一个section ,因为它们是 "一个应用程序的通用部分"?或者说,在这种情况下,div 在语义上是合适的?还是以Twitter为例,你的时间线容器是整个Twitter应用程序的section ,还是你的时间线是Twitter应用程序中的article ?或者说,一切都只是蛋糕,而没有什么是真实的。
我们将回到这里,将我们的心理模型应用于这两种情况。
了解规格的含义
我认为,看似混乱的原因是我们的心理模型。至少对我来说是这样的。
article 元素并不是根据一篇书面文章而命名的。我错误地认为它是,也许你也可能是。我只是从字面上得知有一个article 元素的存在,并认为博客文章在网络上是如此重要,以至于WHATWG决定制作一个专门用来包装像这样的博客文章的元素。我觉得这很直观,但我错了。我想这就是网络标准存在的原因。直觉并不总是统一的。
事实证明,在《牛津英语词典》和其他词典中,文章这个词的定义之一是 "一个特定的项目或独立的东西"。这就是规范中使用article 元素的意义。它就在规范对article 元素的定义中,但正如我所说,这不是我通常使用 "文章 "一词的方式。事实上,字典给 "文章 "的第一个定义是书面作品。
因此,虽然规范清楚地说明了它的使用意义,但我们仍然不这样认为。
为了使它更能调整我们的想法,Bruce Lawson给出了理解文章元素的最好的轶事。
我给出了我一贯的答案:不要把
<article>,不仅仅是一篇报纸文章或一篇博客文章,而是一件衣服--一个可以在另一种情况下重新使用的独立实体。因此,你的裤子是一篇文章,你可以用不同的衣服来穿;你的衬衫是一篇文章,可以用不同的裤子来穿;你的及膝漆皮细靴是一篇文章(你不会只穿其中之一,对吗?)
这意味着article ,代表的是可以从文档中取出来的内容,离开紧邻的内容,丢在别的地方,比如说另一个页面上,并且在分组的时候仍然完全有意义。
同样,你可以用一篇文章,如台灯(一个独立的内容组),来改善你的客厅的美感,它将与你的沙发、电视控制台、窗帘等(直接的周边内容)相得益彰。然而,如果你把你的台灯带到你的房间,它只是放在你的床边或你的工作站,它仍然可以被识别为一个完整的灯。
另一方面,section 元素代表了"内容的主题分组",这意味着section 是一个更大的群体的一部分,如果没有这个群体,它不一定能单独站立起来,有完整的意义。它可能单独存在,但在你内容的整体主题中,它不太可能是独立的。正如规范中所说的,"章节的例子可以是章节、标签式对话框中的各种标签页,或者论文中的编号章节。一个网站的主页可以被分成介绍、新闻条目和联系信息等部分"。
这就是为什么section ,通常会有一个标题,提供一种呼唤,让人知道这个部分与大文件的哪一部分有关。
让我们回到我们的灯的比喻上。我们的台灯本身作为一个项目是有意义的,但在现实中,它有不同的部分,在技术上可以分开,但实际上不应该。我可以把灯的伞状罩子拿掉,把灯泡拿掉,把底座拿掉,再把直立的支架拿掉。它们合在一起,构成了一盏灯,但是,拆开来,又不完全是。如果你看到一盏灯的伞形罩,你很可能会想:"这是什么来的?它的其他部分在哪里?"如果你看到的是灯泡,你可能会想,"这是去哪里的?"
让我们对一些内容进行分组
一个博客网站的登陆页
首先,让我们以一个博客网站为例。我们的博客是Smashing杂志。让我们来看看我们的登陆页面。
以下是我们登陆页面的主要区域。
- 带有网站导航的页眉。
- 主要区域。
- 带有主题导航的页脚。
<header>
<nav>
<!-- Website navigation goes here -->
</nav>
</header>
<main>
<!-- We would group the content that should go here -->
</main>
<footer>
<nav>
<!-- Topic navigation goes here -->
</nav>
</footer>
这些组已经有了代表它们的元素。因此,我们不会在section 和article 之间决定这些。
在我们的主要内容中,这些是可识别的组。
- 精选文章。
- 通讯订阅,
- 组件和指南。
- 最新的帖子。
- 粉碎的产品和服务。
- Smashing会议,
- 来自社区成员的外部文章。
应该用什么元素来包装这些分组的内容呢?让我们运用我们的心理模型。对于这些内容组中的每一个,我们都遵循这个心理模型。
- 对这些内容进行分组,是否起到了可能有助于解释我的文档结构的作用?
- 如果它没有,那么我可以用一个
div。 - 如果有,就扮演一个角色,然后继续考虑这个角色是否符合一个
section或一个article。
- 如果它没有,那么我可以用一个
- 它在我的文档结构中起到了什么作用?
- 这个组的内容在主题上是否相关,从而有助于理解我的文件的大纲?如果是,那么它就可能是一个
section。 - 这个组的内容是否包含我可以拿出来重新分配到其他页面的内容,而它并不完全与我的文件主题和大纲相关?如果是,那么它就可能是一个
article。
- 这个组的内容在主题上是否相关,从而有助于理解我的文件的大纲?如果是,那么它就可能是一个
我鼓励你拿起一张纸,在继续看我的分组之前,先做你的分组。这样,我们就可以比较我们如何看待每个内容组在我们页面上的作用。
现在让我们为我们的Smashing杂志建立一个骨架分组。
- 精选文章
它在我的文档结构中起作用吗?是的。什么作用?它是我的登陆页面上的内容大纲的一部分。结论:section。 - 通讯订阅
它在我的文件结构中发挥了作用吗?嗯。嗯,它不完全是在我的登陆页面的中心主题内,所以我对这个问题很怀疑。我只想说 "不"。评语:div。 - 组件和指南
它在我的文档结构中起作用吗?是的。什么作用?它是我的登陆页面上内容大纲的一部分。判决:section。 - 最新文章
它在我的文件结构中发挥了作用吗?是的。什么作用?它是我的登陆页面上的内容大纲的一部分。判决:section。 - 粉碎产品和产品
它在我的文件结构中发挥了作用吗?是的。什么作用?它是我的登陆页面上的内容大纲的一部分。判决:section。 - Smashing会议
它在我的文件结构中起作用吗?是的。什么作用?它是我的登陆页面上的内容大纲的一部分。裁定:section。 - 来自社区成员的外部文章
它在我的文件结构中起作用吗?是的。什么作用?它是我的登陆页面上的内容大纲的一部分。判决:section。
这是我的Smashing杂志登陆页面现在的样子。
<header>
<nav>
<!-- Website navigation -->
</nav>
</header>
<main>
<section>
<!-- Selected articles -->
</section>
<div>
<!-- Newsletter subscription -->
</div>
<section>
<!-- Components and guides -->
</section>
<section>
<!-- Latest posts -->
</section>
<section>
<!-- Smashing products and offerings -->
</section>
<section>
<!-- Smashing conferences -->
</section>
<section>
<!-- External articles from community members -->
</section>
</main>
<footer>
<nav>
<!-- Topic navigation -->
</nav>
</footer>
我们都可能以不同的方式判定一些项目所扮演的角色。例如,"通讯订阅 "区域。我不会在我的文件大纲中列出 "通讯订阅",我也不会在意在我访问的页面的文件大纲中遇到它。然而,如果是Substack,一个通讯的平台,我肯定会看到订阅通讯的区域会是一个section 。虽然我在这里使用了一个div ,它也可以是一个aside ,但是,当然,这不是我们今天在这里的原因。关键是我们如何判断我们的内容,指导我们的决定。
我想我的观点是,如果你审视并证明你希望你的内容组在每个案例中扮演的角色,你的决定就会稍微好一点。你会有意识地努力使你的网络内容对用户和其他会遇到你的技术债务的开发者来说是可以理解的。
博客网站上的一篇文章
所以,我们从 "选定的文章 "区域点击了一篇博客文章,并将这篇文章扩展到它自己的页面。你正在阅读的这篇具体的博客文章,它是如何分组的呢?同样,这里是我们的基础模板。
<header>
<nav>
<!-- Website navigation -->
</nav>
</header>
<main>
<!-- This article is wrapped here -->
</main>
<footer>
<nav>
<!-- Topic navigation -->
</nav>
</footer>
你是否把它包在一个article ,你是否把它包在一个section ,或者也许是一个div ?
你会把这篇文章本身分成更小的组别吗?也许是一堆section,或者是几个article?这篇文章中是否有可重新分发的部分,或者是你会暴露在文件大纲中的部分?
我不会说我得出的结果,但我很想知道你会使用什么。请记下你的答案,因为我们将在以后重新讨论这个问题。
一个网络应用。推特
那么,我们还有一个练习,一个网络应用,特别是Twitter。
- 时间线容器是整个Twitter应用的
section,还是你的时间线是Twitter应用中的article,或者是div? - 你是否会把每条送入用户时间线的推文包裹在一个
article,因为它们是 "独立的","原则上是可以独立分发的"?或者你会把它们包装在一个section,因为它们是 "一个应用程序的通用部分"?或者说,在这种情况下,div在语义上是合适的?
如果我运用心理模型,下面是我将如何做的方式。
我的时间线是我的文件大纲的一部分,然而,在某种程度上,它可以独立分布。我可以把我的时间线拿出来,它可以很好地独立存在。这似乎是可行的section 或article 。因此,我进一步质疑,我的真正意图是什么?我是想让它发挥再传播的功能,还是作为我的应用程序的一部分?如果你使用Twitter,你会同意你的时间线更像是你的主页的一个组成部分,而不是可重新分配的。在这里,我将退而求其次,选择一个section 。
对于我的时间线中的每条推文,它将是一个article 。这是因为每条推文在主题上与我的时间线中的下一条推文没有联系,以至于我可以说它可以成为一个大纲的一部分。因此,推文不是section。它们是 "自成一体的","原则上是可以独立分发的"。你甚至可以点击一条推文,进入一个新的世界,有评论和引用推文,以及更多。
真的,而且确实,如果你走过Twitter页面的div-soup,嵌套其中,有一个漂亮的漂亮的section ,就坐在那里,因为它应该是。这个section 保存着你的时间线。而如果你继续深入到section ,再往下看一份div,你可以看到一个article ,里面放着每条推文。我承认,当我发现我的想法与Twitter的做法一致时,我在这里发出了一声小小的尖叫。
对Twitter的检查还表明,divs的存在并不意味着语义被牺牲或丧失。
嵌套sections和articles以及其他组别
你可以将这些元素嵌套在彼此之间。在看了Twitter的例子之后,你可能已经明白了这一点。
div在这个例子中,articles和sections可以相互嵌套而不一定会破坏可访问性。如果你运用心理模型,你可以质疑你即将进行的每一个嵌套,并进行相应的分组。
以这篇博文为例。当我在几段前询问时,我没有回答我将如何包装它。这里是我可以做的。
我可以把你正在阅读的这篇文章全部包裹在一个article 。然后我再把这篇文章的大块内容进一步嵌套到section,因为我希望每一部分都能真正划分开来,便于理解。到目前为止,这就是你正在阅读的这篇博文的模样。
<header>
<nav>
<!-- Website navigation -->
</nav>
</header>
<main>
<article>
<h1>Article versus section: Making your choice count in the larger context of accessibility</h1>
<section>
<h2>Quick summary</h2>
<!-- paragraphs go here -->
</section>
<section>
<h2>Introduction</h2>
<!-- paragraphs go here -->
</section>
<section>
<h2>Document Semantics</h2>
<!-- paragraphs go here -->
</section>
<section>
<h2>Does my grouping play a semantic role?</h2>
<!-- paragraphs go here -->
</section>
<section>
<h2>What semantic role does my grouping play?</h2>
<!-- paragraphs go here -->
<h3>What the HTML specs say</h3>
<!-- paragraphs go here -->
<h3>Understanding what the specs mean</h3>
<!-- paragraphs go here -->
</section>
<section>
<h2>Let's group some content</h2>
<!-- paragraphs go here -->
<h3>A bog website landing page</h3>
<!-- paragraphs go here -->
<h3>An article post on a blog website</h3>
<!-- paragraphs go here -->
<h3>A web application: Twitter</h3>
<!-- paragraphs go here -->
</section>
<section>
<h2>Nesting sections AND articles</h2>
<!-- paragraphs go here -->
</section>
<!-- Rest of article continues here -->
</article>
</main>
<footer>
<nav>
<!-- Topic navigation -->
</nav>
</footer>
注意到我是如何给我的sections适当的标题的,因为我已经决定使用section ?记住,规范中说section ,通常应该有一个标题。另外,请记住,如果你认为section,那么你就应该在你的文档纲要中加以说明。因此,一个标题将提供在大纲中的文本。
如果有需要,你的section和article可以有其他的分组内容。例如,你可以有一个header 来存放你的章节的标题,或者有一个footer 来存放关于一个章节的信息,如相关文件的链接等。如果你愿意,这篇文章的 "进一步阅读 "区域可以被包裹在footer 。
至于main ,你只能在层次正确的情况下使用它,也就是说,如果它是html 、body 、div 或form 的直接子女。在任何情况下,你都被限制使用一个以上没有hidden 属性的main 元素。
section 和article 是如何被揭露的
到目前为止,我们已经研究了如何对内容进行分组,但只是从开发人员的角度来看。我们的分组是如何暴露给读者的呢?
section 以及浏览器中的article
浏览器会生成一个可访问性树,你可以用开发者工具来检查。你可以打开开发者工具,激活检查器,并导航到可及性标签。
Firefox、Chrome和Microsoft Edge同样在可及性树上显示article 和section 元素各自的roles。article 元素在可访问性树上有 "文章 "的role 。section 元素有 "section "的role 。这意味着,浏览器准确地识别了我们的内容分组所代表的内容。
然而,虽然浏览器正确地理解了我们的内容分组所代表的内容,但用户并没有得到任何有关的特别提示。因此,articles和sections是无法感知的,也无法通过浏览器上的键盘进行其他导航。如果页面是有风格的,那么你的设计所提供的视觉线索就可以暗示内容的分组。但是,在焦点上没有默认的下划线或轮廓,就像你在链接上得到的那样。
**注意:**我应该简要地指出,我们(Manuel和我)在浏览器显示section 元素具有 "section "的角色时有点被绊倒了,因为在aria无障碍定义中,section的ariarole 与HTMLsection 元素不同。section "的ria角色是一个抽象的角色,不应该被作者/开发者使用。因此,请不要在你的HTML中设置role="section" 属性。总之,看起来浏览器可能在使用他们自己内部的可访问性术语。这一结论尤其得到以下事实的支持:例如,在Firefox中,图像具有 "图形 "的角色,但ria没有任何被称为图形的角色。也许更有见识的人一定能够解释发生了什么。然而,预期的行为是正确的。
section 而 在读屏器中article
读屏器读取可访问性API,然后正确处理这些元素。有几个读屏器在使用。值得庆幸的是,AccessibilityOZ记录了屏幕阅读器是如何处理分段元素的,在写这篇文章时,这似乎仍然是准确的。
article 在读屏器中
当分组内容被包裹在一个article ,不同的屏幕阅读器对它的处理方式也不同。
在可感知性方面,AccessibilityOz记录了JAWS、Talkback on Android和VoiceOver在遇到 "文章 "时宣布进入和退出。NVDA和Narrator并没有宣布article 。
我专门在NVDA和Narrator上进行了测试,因为我使用的是Windows笔记本电脑,而article ,没有公布。Manuel也很好心地帮助在VoiceOver和Talkback上进行了测试,如果在你浏览页面时遇到了article ,就会宣布。
我打探了一下,发现NVDA允许你打开选项,宣布article 的存在。只是默认情况下是关闭的。我不确定非开发者用户会多频繁地定制这个选项。
关于导航,使用Narrator的用户不能跳转到article ,因为它是不可感知的。使用NVDA的用户,如果激活了公布article的选项,就不能跳转到article 。对此没有快捷方式。只有在穿越页面时遇到它才会被宣布。JAWS有一个专门的快捷键,可以通过按O键在页面上移动articles。VoiceOver用户可以通过快捷键(VO + Shift + 左/右箭头)跳过articles。
虽然有些用户会得到article 宣布的存在,但其他用户不会。所以,这种体验并不统一。我也曾想过,宣布一个article ,是否有任何实际用途。我不确定当我听到宣布我在一个网页上的 "文章中 "时,我会把它理解为 "在一个独立的、可再分配的和自成一体的内容中"。这听起来更像是我在一个 "书面作品 "中。反正我也没有能力去检验这个,所以这真的只是我自己的想法。
那么问题来了,我的页面的用户从在article 中对内容进行语义分组中得到了什么直接的好处?在我将我的分组正确地包裹在article 中之后,它对我的用户有什么转化? 如果没有,为什么我不应该直接使用div 来代替呢?布鲁斯-劳森(Bruce Lawson)的文章《为什么你应该选择HTML5article 而不是section 》充分涵盖了这一点。苹果WatchOS的Reader会留意article 元素,以适当地决定在iWatch上显示什么。虽然这不是网络标准特别规定的使用情况,但也许我们会看到设备制造商采取这种做法的趋势。因此,如果你在设计页面时考虑到WatchOS,这将是使用article ,至少比div 的一个额外理由。
但我还是想知道,是否还有其他直接有利于用户的理由。我为什么要跳过一个网页上的所有articles?为什么要像JAWS和Voiceover允许的那样,在没有上下文的情况下跳过网页上的独立项目?所以我做了一些调查,以下是我发现的关于辅助技术对文章角色的规定功能。
一篇文章可以被嵌套形成一个讨论,辅助技术可以注意文章的嵌套,以帮助用户跟随讨论...
...当嵌套文章时,子文章代表与父文章的内容有关的内容。例如,在一个接受用户提交的评论的网站上的网络日志条目,可以将评论作为文章嵌套在网络日志条目的文章中。
...当用户导航到一个被指定为
article的元素时,通常拦截标准键盘事件的辅助技术 应该切换到文档浏览模式,而不是把键盘事件传递给网络应用程序。辅助技术可以提供一个功能,允许用户浏览任何嵌套的article元素的层次结构。
遗憾的是,我无法直接重现这种行为。在VoiceOver上用快捷方式跳过articles,只是宣布 "文章,文章,文章"。他们似乎没有实现允许用户浏览嵌套文章的层次结构的功能,否则我无法让它发挥作用。
然而,如果使用嵌套式article,也无伤大雅,因为这样做是合适的。如果屏幕阅读器制造商实现了这一建议的行为,你的页面就已经是最好的了,并为之做好了准备。考虑到这是某种面向未来的做法。
section 在读屏器中
在分组内容被包裹在一个section ,屏幕阅读器对待它的态度更加一致。
就可感知性而言,所有的屏幕阅读器都不会宣布进入或退出section 。这也意味着在导航方面,没有办法从一个section 到另一个。
将section 扩展为可导航的region
section 的不可察觉性只是一种默认行为。因此,我们可以定制我们的section ,并使用WAI-ARIA(Web Accessibility Initiative - Accessible Rich Internet Applications)将其展示给屏幕阅读器用户。
以下是从MDN文档中摘录的关于WAI-ARIA是什么以及它的作用的摘要。
(Web Accessibility Initiative - Accessible Rich Internet Applications)是由W3C编写的一份规范,定义了一组额外的HTML属性,可应用于元素,以提供额外的语义,并在缺乏无障碍性的地方提高无障碍性...
意味着,虽然您可能已经在编写语义化的HTML,但您可以定制并提供更多的语义化含义
在这个特定的案例中,我们更关心的是ARIA所提供的地标角色类别,即为应用程序或文档提供导航背景的角色。为了更好地理解,WAI-ARIA提供的地标的定义是这样的。
用户可能希望快速访问的页面上的一种类型的区域。这种区域的内容与页面上其他区域的内容不同,与特定的用户目的相关,如导航、搜索、浏览主要内容等。
通过地标role,我们可以为非视力正常的用户提供视力正常(和完全非残疾)的用户在我们的页面上会有的关键体验:首先扫描或略过一个页面,然后决定将注意力集中在哪里。
对于section 的具体情况和预期的语义,我们打算传递给用户;即其中的内容在主题上是相关的或有一个中心思想,region 的特定role 是我们关注的。
作为一个标志性的角色,一个region ,是由w3c打算的。
一个可感知的
section,包含与特定的、作者指定的目的有关的内容,并且足够重要,用户很可能希望能够轻松地导航到该部分,并将其列在页面的摘要中。
我们可以把我们页面的特定sections变成regions计算,以使屏幕阅读器用户更容易跳到页面的那一部分。这对有很多内容的页面特别有用,而不是用户可能出现在页面上的主要原因。
要创建一个region ,有两件事要做。首先,通过在元素的开头标签中包括属性-值配对role="region" ,使你的元素成为一个区域。其次,你给你的区域一个可访问的名字。然而,如果你的分组元素是一个section ,你只需要做第二件事。这是因为如果你的section 元素有一个可访问的名字,那么它就有一个隐含的角色,即region 。因此,不建议设置一个与该元素的隐含语义相匹配的角色。所以我们来设置一个可访问的名字。
一个可访问的名称只是一个用户界面元素的名称,特别是由可访问性API暴露给辅助技术。
region 角色的规范要求如此。
作者必须
给每个有区域角色的元素一个简短的标签,描述该区域内容的目的。
region 角色需要一个无障碍名称。如果没有可访问的名称,那么浏览器和辅助技术就不能将一个区域暴露给用户,因为用户将跳转到一个没有描述或上下文的区域,几乎就像发生在article 。
根据所涉及的元素,有多种方法来提供名称。然而,我们将把范围缩小到与作为region 的section 有关的内容。
第一个也是最受欢迎的命名方式是通过aria-labelledby 属性来命名你的区域。要做到这一点,你要在你的页面上引用一个可见元素,并指示辅助技术使用该可见元素的文本内容作为该区域的名称。这个可见元素最好是一个标题。
要做到这一点,给你要引用其内容的元素一个id 属性,并选择一个值。然后给你的section 元素一个aria-labelledby 属性。然后将aria-labelledby 属性的值设置为与你所引用内容的元素的id 相同的值。请看一下这个动作。
<section aria-labelledby="posts">
<!-- This area contains teasers for all blog posts on the website -->
<h2 id="posts">All blog posts</h2>
<article>
<header>
<p>Cosima Mielke wrote</p>
<h2>Expand Your Horizons (June 2022 Desktop Wallpapers Edition)</h2>
</header>
<div>
<p>What could be a better way to welcome June than with some colorful inspiration? Well, we might have something for you: wallpapers created with love by artists and designers from across the globe.</p>
<p><a>Continue reading ↬</a></p>
</div>
</article>
<!-- More blog post teasers here -->
</section>
请注意,你的aria-labelledby 并不带有# ,这与用href 链接到id 时的情况不同。它是aria-labelledby="posts" ,而不是aria-labelledby="#posts" 。还请记住,我们不会为一个section 元素设置一个role=region 。一旦你给了一个可访问的名字,它就已经被暗示了。
使用这个代码例子,屏幕阅读器会在地标导航下向他们宣布这个区域,如 "所有博客文章,区域 "或类似的东西。
给予无障碍名称的第二种方式是使用aria-label 属性,如果没有可见元素的内容可以准确地标注你的区域。在这种情况下,你给aria-label 本身的值将被读作区域的名称。
<section aria-label="all blog posts">
<!-- This area contains teasers for all blog posts on the website -->
<article>
<header>
<p>Cosima Mielke wrote</p>
<h2>Expand Your Horizons (June 2022 Desktop Wallpapers Edition)</h2>
</header>
<div>
<p>What could be a better way to welcome June than with some colorful inspiration? Well, we might have something for you: wallpapers created with love by artists and designers from across the globe.</p>
<p><a>Continue reading ↬</a></p>
</div>
</article>
<!-- More blog post teasers here -->
</section>
在这个代码例子中,没有我们可以参考的区域的标题。因此,通过直接读取我们为aria-label 属性提供的值,这个region 将被宣布为 "所有博客文章,区域"。你会注意到,可访问的名称是用小写的。这是因为读屏器可能会把写成大写的单词误认为是缩写,然后按字母顺序拼出来,而不是把它们当作一个单词来读。句子的大小写是可以的,但请避免全部大写。如果你想强调,请使用em 标签。
简而言之,aria-labelledby 是一种参考性的命名机制,之所以推荐使用,是因为用户依靠辅助技术,从页面上的现有内容中获得标签,确保他们得到的体验与其他用户得到的体验明显相同。另一方面,aria-label 是一种直接命名机制。使用它意味着依赖辅助技术的用户从作者对该元素作用的解释中获得标签。这就是为什么建议只在页面本身没有可见内容的情况下使用它。需要主动决策。
最后,不是每个section ,都必须是一个区域。严重的是,在学习这个创建region 的新权力时,很容易看着你页面上的所有元素,然后说:"你得到一个区域,你得到一个区域,每个人都得到一个区域。"请不要这样做。为什么?斯科特-奥哈拉(Scott O'Hara)解释说:"在网页上过度填充地标会降低它们帮助用户找到网页中最重要部分的能力"。记住,区域应该附在用户想要轻松到达的区域。现在让我们看看这些在现实生活中发挥作用的例子。
Smashing杂志在这篇博文的 "快速总结 "部分使用了aria-label 技术。如果你打开你的开发者工具并检查 "快速摘要",这就是标记的样子。
<section aria-label="quick summary" class="article__summary">
<span class="summary__heading">Quick summary ↬</span>
<!-- Rest of summary continues here -->
</section>
现在,屏幕阅读器用户可以使用快捷键跳转到 "快速摘要 "区域,并获得文章内容的概述,而不必首先与整篇文章互动。
让我们再看一下Twitter,这是一个使用aria-labelledby 技术的网络应用。看一下开发者工具,特别是持有你的时间线的section 。你会看到section's opening tag中的一个aria-labelledby="accessible-list-9" 属性。它指向就在它下面的h1 元素,该元素有一个id="accessible-list-9" 和文字内容,写着 "你的主页时间线"。现在屏幕阅读器的用户可以使用屏幕阅读器中的地标导航菜单,并导航到 "你的主时间线区域"。
有两个问题可能已经在你的脑海中闪过。首先,既然规范说具有无障碍名称的section ,不需要明确指定区域角色,为什么在section 元素上还有一个role="region" ?第二,如果aria-labelledby 应该引用一个可见的元素,为什么我在浏览器中看不到带有 "你的主页时间表 "的h1 元素?
对于第一个关于在section 元素上声明role="region" 的问题,规范说不建议明确地设置一个与隐含语义相同的角色。然而,他们确实认识到,可能有一些浏览器和设备确实正确地暴露了隐含语义。因此,对于像Twitter这样被数以亿计的人使用的应用程序来说,明确设置区域角色是合理的,因为他们无法预测所有使用中的不同类型的浏览器和设备。
第二个问题是为什么aria-labelledby 的引用元素不在页面上。这是一种模式/技术,人们在构建页面时不时会考虑到可访问性。这里没有违反规则。一个h1 元素是一个可见的元素。这里所做的是使用CSS来移除那些对视力正常的用户来说不需要但对非视力正常的用户来说很关键的元素的视觉渲染。对于视力正常的用户来说,没有标题的时间线是可以识别的。然而,对于屏幕阅读器用户来说,标题也是一个命名区域的参考点,所以我们的HTML中需要它。通过使用一个整洁的CSS技术,人们可以把内容从屏幕上拿下来,但让屏幕阅读器看到。
当你把你的section 变成一个region ,我注意到了另一件有趣的事情。还记得我们在开发工具中使用检查器的可访问性标签吗?嗯,section'在可访问性树上的角色在Firefox中并没有直接改变为region 。发生的情况是,一个region 分支被创建为section 的子节点。在火狐浏览器中,该树变成section →region 。
然而,在Chrome和Microsoft Edge中,section 本身变成了region 角色。
我是否应该打扰一下?
是的,你绝对应该。
事实上,即使你的设计不是为了在iWatch或其他智能设备上显示,即使你没有理由在你的页面上创建region,你仍然应该使用正确的元素。
首先,Mandy Michael的这篇文章揭示了浏览器会注意你的HTML结构来生成一个阅读模式,该模式会将页面中不必要的信息、图像和背景剥离。Safari、Chrome、Firefox、Edge和其他阅读应用程序会特别注意HTML分段内容,以优先显示为阅读。分节的内容包括article 和section 等。如果不仔细将你的内容包装成适当的元素,你就有可能在创建极简视图时被忽略。
其次,它帮助你积极思考如何呈现你的内容。内容设计是我们页面的一个关键部分,我们应该有意识地去考虑。它是我们页面的基础。我们使用的词,我们使用的标题,以及我们段落的长度都会影响我们的用户。我们如何分组我们的内容也是至关重要的。
作为设计者和开发者,我们可能觉得我们对内容进行分组的主要原因仅仅是为了使它们具有风格。但如果我们开始关心内容,我们可能会意识到有更好的方法来创建我们的页面。分组内容的作用远不止是为我们的内容准备视觉样式。如果我们注意有意识地编写我们的HTML,我们就可以在一定程度上确定,我们已经使我们的网络角落成为一个对所有人都更好的地方。
写这篇文章和思考我将如何对这个页面进行分段,有助于我为我的工作创造一个连贯的结构。它帮助我找出内容与周围环境不相称的地方。对于像这样长的文章,思考我们如何对内容进行分组变得至关重要。
即使是在内容极短的情况下,思考我们如何分组内容也有助于创造更好的内容。在最近一次关于内容设计和可访问性的知识共享网络研讨会上,Amanda Diamond分享了这张幻灯片,展示了如何将一个非常短的内容块分割开来,使其更容易被人们阅读。这两张截图包含完全相同的内容,但其中一张更容易消化。这将是一个使用section ,而不仅仅是div 。注意每个部分都有一个适当的标题来解释每个内容块。
总结
我们已经看了一个心理模型,它迫使我们与我们的内容互动,以确定如何最好地分组。我们质疑。
- 分组是否在我们的文件结构中起作用?
- 如果有,它扮演什么角色?
从我们的答案中,我们可以为我们的内容选择合适的分组元素。
我们还研究了当浏览器为我们的section 或article 元素建立可访问性树时会发生什么,以及如何将我们的section 扩展为region ,以便于导航。
最后,我认为我们与我们内容的两组消费者进行了交流--从URL上阅读我们的网页的最终用户和必须与我们的标记进行交互的其他人。在谈到HTML时,我们可能倾向于主要从最终用户的角度来考虑。不过,我相信,编写对于将在上面工作的人来说易于理解和不言自明的HTML,就足以成为使用正确语义元素的理由。