现代CSS升级,提高可访问性

553 阅读19分钟

对于在堆栈中从事任何工作的开发人员来说,可访问性是一项关键的技能。对于前端任务,现代CSS提供了我们可以利用的功能,使布局对任何设备上所有能力的用户都更具有可及性。

这篇文章将涵盖一系列的主题。

可访问性 "是什么意思?#

无障碍网站是指为不同能力的用户访问内容或执行操作而创建的没有障碍的网站。一个被称为《网络内容可访问性指南》(简称WCAG)的国际公认标准提供了成功标准,以帮助指导您创造无障碍体验。

常见的无障碍性障碍包括

  • 由于颜色对比度差,无法看到内容或区分界面元素
  • 由于没有提供替代文本,减少或取消了对非文本内容的访问,如图像或图表内的内容
  • 由于没有管理交互式元素的焦点而使键盘使用者陷入困境
  • 由于运动和闪动/闪烁的动画,对有前庭障碍的用户造成头痛或更糟。
  • 由于未能使自定义控件适应预期的模式,使屏幕阅读器等辅助技术的用户无法进行操作
  • 由于没有使用语义的HTML,包括标题层次和地标元素,限制了常见的辅助技术导航方法。

成功标准"旨在广泛适用于当前和未来的网络技术,包括动态应用、移动、数字电视等。" 我们将研究几个成功标准以及现代CSS如何帮助提供无障碍解决方案。

焦点可见性#

过去我自己做的一个很常见的违规行为是,删除链接、按钮和其他互动控件上的:focus 概述。如果不提供一个替代的:focus 样式,这就立即违反了WCAG成功标准2.4.11:焦点外观

通常情况下,这被删除的原因是觉得本地浏览器的风格不吸引人,或者不适合网站的设计选择。但是,通过现代CSS,我们有一个新的属性,可以帮助使轮廓更加吸引人。

使用outline-offset ,我们可以提供一个正值来定位轮廓远离元素的位置。对于偏移量,我们将使用em 单位,根据元素的font-size ,将轮廓相对于元素定位。

奖励:我们使用max() 函数来设置outline-width 的值,以确保它不会缩减到低于1px 的计算值,同时允许它也可以使用em 的相对大小。

选择演示按钮来显示:focus 的轮廓。

"具有正的`outline-offset'的焦点样式 "的CSS

button:focus {  outline: max(1px, 0.1em) solid currentColor;  outline-offset: 0.25em;}

.outline-offset-866 { color: purple; line-height: 1; font-size: 1.5rem; cursor: pointer; } .outline-offset-866:focus { outline: max(1px, 0.1em) solid currentColor; outline-offset: 0.25em; }

演示按钮

另外,可以使用一个负值来设置outline-offset ,以便将轮廓从元素的周边插入。

"使用负的`outline-offset'的焦点样式 "的CSS

button:focus {  outline: max(1px, 0.1em) dashed currentColor;  outline-offset: -0.25em;}

.outline-offset-127 { background-color: purple; color: white; padding:0.5em; border-radius:4px; line-height: 1; font-size: 1.5rem; cursor: pointer; } .outline-offset-127: focus { outline: max(1px, 0.1em) dashed currentColor; outline-offset: -0.25em; }

演示按钮

还有一个新的伪类,你可以考虑在某些情况下使用。:focus-visible 伪类将只在设备/浏览器(用户代理)确定它需要可见时才显示轮廓(或用户定义的样式)。通常情况下,这意味着它将在tab 键交互时出现在键盘用户身上,但对于鼠标用户来说则不会。

使用这个更新,我们的按钮样式_很可能_只在你用键盘点击按钮时显示。

负的 "outline-offset "焦点样式的CSS

button:focus {  outline: none;}button:focus-visible {  outline: max(1px, 0.1em) dashed currentColor;  outline-offset: -0.25em;}

.outline-offset-837 { background-color: blue; color: white; padding:0.5em; border-radius:4px; line-height: 1; font-size: 1.5rem; cursor: pointer; } .outline-offset-837:focus { outline: none; } .outline-offset-837: focus-visible { outline: max(1px, 0.1em) dashed currentColor; outline-offset: -0.25em; }

演示按钮

请注意,:focus-visible 支持仍在向所有的浏览器推出,特别是在Safari中缺少。如果你想尝试使用它,这里有一个将它作为渐进式增强的例子。

我们正在利用这样一个事实,即不理解:focus-visible 的浏览器会丢弃删除:focus 的轮廓的规则。意味着,button:focus 的第一条规则将适用于不支持:focus-visible 的浏览器,而后两条规则将在支持:focus-visible 时适用。有趣的是,:focus:not(:focus-visible) 给人一种错误的印象,即:focus-visible 在Safari_甚至_Internet Explorer 11中是有效的。

button:focus {  outline: max(1px, 0.1em) dashed currentColor;  outline-offset: -0.25em;}button:focus:not(:focus-visible) {  outline: none;}button:focus-visible {  outline: max(1px, 0.1em) dashed currentColor;  outline-offset: -0.25em;}

_嗨,你们好!_注册参加我7月份在Smashing Conference举办的CSS研讨会。用现代CSS提高水平

焦点与来源顺序#

另一个与焦点有关的标准是成功标准2.4.3。焦点顺序。对于视觉用户和非视觉用户来说,焦点顺序--通常是由键盘上的标签启动的--应该有逻辑地进行。特别是对于视觉用户来说,焦点顺序应该遵循预期的路径,这_通常_意味着遵循源的顺序。

从前面链接的标准文件中可以看出。

"例如,读屏器用户与程序确定的阅读顺序进行交互,而视力良好的键盘用户则与网页的视觉呈现进行交互。应该注意使焦点顺序对这两组用户都有意义,而不至于在他们看来是随机跳动的。"

现代CSS在技术上提供了布局属性,将视觉顺序重新排列成与源顺序不同的东西。这样做的影响是,_如果_有可关注的元素被重新排列成一个令人惊讶的顺序,则可能无法通过关注顺序的成功标准。

如果你可以的话,用你的Tab键浏览一下下面的演示,注意一下你_期望_发生的和_实际_发生的情况。当你完成后,或者如果标签键目前对你来说不是一个可用的输入,请勾选方框以显示标签顺序。

[class*="source-order"] { color:#222; } .source-order-36 { display: grid; grid-template-columns: repeat(3, 1fr); grid-gap: 1rem; list-style: none; } .source-order-36 li { padding:1rem; text-align: center; } .source-order-36 li a { display: grid; place-content: center; color: inherit; } .source-order__label-36 { font-weight: bold; } .source-order__label-36, .source-order__checkbox-36 { display: inline-block; margin-top: 0.5rem; margin-left: 0.5rem; margin-bottom:1.5rem; } .source-order__checkbox-36:checked ~ ol { list-style: decimal; list-style-position: inside; } .source-order-36 li:nth-child(2) { grid-column:3; grid-row: 2; } .source-order-36 li:nth-child(5) { grid-column:2; grid-row: 1; } .source-order-36 li:nth-child(7) { grid-column:1; grid-row: 1; } .source-order-36 li:nth-child(3) { grid-column:1; grid-row: 3; }

揭示秩序

  1. 链接
  2. 链接
  3. 链接
  4. 链接
  5. 链接
  6. 链接
  7. 链接

本节的目的更多的是为了在你考虑如何解决布局难题时提供对这一标准的认识。即将到来的CSS网格是一个原生的 "砖石结构 "解决方案。不幸的是,它可能对预期的焦点顺序产生负面影响。在分配不符合源顺序的特定网格区域时,以及使用order 属性在flexbox中定制项目顺序时,也会产生类似的问题。

我最近面临的一个挑战是,一个导航链接的列表被要求分成几列。在这种情况下,逻辑上的标签顺序应该是在进入下一列之前先向下移动一列。问题是,这是一个单一主题的项目列表,所以从语义上来说,把它分成每一列的列表并不理想。对于使用屏幕阅读器等辅助技术的用户来说,分成多个列表也会错误地显示单个主题的项目数量,因为屏幕阅读器会公布列表中的项目数量。

使用下面这组CSS网格属性,我能够得到一个不破坏列表的解决方案。

"使用CSS网格的列表焦点顺序解决方案 "的CSS

ul {  display: grid;  grid-column-gap: 2rem;  grid-row-gap: 1rem;  /* Causes items to be ordered into columns */  grid-auto-flow: column;  /* # required to prevent a column per link */  grid-template-rows: repeat(3, 1fr);  /* Size the columns */  grid-auto-columns: minmax(0, 1fr);}

.grid-list-focus-order-943 { list-style: none; padding:2rem; display: grid; grid-column-gap: 2rem; grid-row-gap: 1rem; grid-auto-flow: column; grid-template-rows: repeat(3, 1fr); grid-auto-columns: minmax(0, 33%); } . Grid-list-focus-order-943 a { color: blue; }

这里需要注意的是,要注意容纳内容所需的空间。在导航场景中,内容通常是被严格控制的,所以这可能是一个合理的解决方案。

Manuel Matuzovic对CSS网格布局和改变源顺序的考虑有一个很好的、更彻底的指南

桌面缩放和回流#

你已经使用浏览器开发工具以及真实的移动设备对不同的视口尺寸进行了测试,而且你对你的网站的响应行为感到满意。但你可能缺少一个测试点:桌面缩放。

之前的教程中,我们开始研究WCAG成功标准1.4.10--回流

Reflow是支持桌面缩放的术语,最高可达400%。在400%的1280px宽的分辨率上,视口内容相当于320个CSS像素宽。用户使用这一设置的意图是触发内容_回流_到单栏,以方便阅读。

前面的教程中也提到,通常缩放开始触发你可能用媒体查询设置的响应行为。但目前还没有缩放媒体查询。因此,桌面上放大到400%的长宽比会导致你的内容出现_回流_问题。

一些可能出现问题的例子。

  • 覆盖一半_或更多视口_的粘性导航
  • 假设手机纵向长宽比,所包含的滚动区域变得无法滚动/被切断
  • 在使用流体排版技术时出现不想要的结果
  • 溢出或重叠的问题,切断了内容
  • 相对于内容的大小,边距和填充间距显得过大

如果没有缩放媒体查询,可能很难设计出独立于设备尺寸假设的缩放解决方案。

然而,有了现代的CSS功能,如min()max() ,我们就有了解决一些缩放情况的工具,而不会影响到我们假设的移动设计的原意。

**你希望在你的收件箱中收到CSS技巧吗?**请加入我的新闻通讯,以获得文章更新、CSS技巧和前端资源。

我们之前研究过使用min 来调整一个包含头像的网格列,其方式适用于小的、大的和放大的视口。

让我们来看看解决垂直间距的问题。一个常见的做法是,设计师为间距创建一个像素斜坡,也许是基于一个8px的单位。因此,你也许会创建间距工具,看起来像。

.margin-top-xs {  margin-top: 8px;}.margin-top-sm {  margin-top: 16px;}.margin-top-md {  margin-top: 32px;}.margin-top-lg {  margin-top: 64px;}.margin-top-xl {  margin-top: 128px;}

以此类推,以适应你的斜面的全部范围。这在标准的设备范围内通常是好的。xl 但是考虑到128px ,在桌面上放大到400%的值就变成了_视口高度的一半_。

相反,我们可以更新范围的上端,加入min() ,选择_最低的计算值_。这意味着,对于非缩放的视口,将使用128px 。而对于400%缩放的视口,可以使用另一个视口单位值。

如果你使用的是台式机,可以尝试一下缩放,看看对演示元素之间的空间有什么影响。

"解决缩放的边距问题 "的CSS

section + section {  margin-top: min(128px, 15vh);}

.zoom-margin-spacing-668 { min-height: 150px; padding:1rem; margin: 0 1rem; outline: 1px solid purple; outline-offset: -.5rem; color:#222; } .zoom-margin-spacing-668 + .zoom-margin-spacing-668 { margin-top: min(128px, 25vh); }

第1节

第2节

第三节

如果你遇到绝对定位元素的重叠,也有可能使用这种技术。

关于缩放如何影响布局和一些现代CSS解决方案的更多例子,请查看CSS Cafe聚会的录音:"现代CSS对(以前)复杂问题的解决方案"

在下一节中,我们将看到如何为触摸设备查询。使用这个方法可以成为一个很好的组合,帮助确定用户的上下文,并为粘性导航或自定义滚动区域等事项提供一个替代的布局。

确定交互式目标的大小#

我们的下一个领域是考虑正确确定交互式目标的大小,其中 "目标 "一词来自成功标准2.5.5:目标尺寸。从该标准来看。

"_这个成功标准的意图是确保目标尺寸足够大,使用户能够轻松地激活它们,即使用户是在小型手持触摸屏设备上访问内容,灵活性有限,或者由于其他原因难以激活小目标。_例如,鼠标和类似的指向性设备对这些用户来说可能很难使用,较大的目标会帮助他们激活目标。"

在WCAG 2.2中引入的是成功标准2.5.8:指针目标间距。该指南指出,一般来说,交互式控件应该是

  • 有一个最小的实际尺寸为44px;或者
  • 允许最小目标尺寸--包括控件和其他元素之间的间距--为44px。

在链接的资源中,有一些例外情况和额外的例子来帮助澄清这一要求。Adrian Roselli也提供了一个很好的概述和历史

除了这个网站之外,我还维护着SmolCSS.dev,它探索了用于创建布局和组件的最小的现代CSS解决方案。下面是其中一个演示的节选--"Smol头像列表组件"。

它使用CSS函数max() ,以确保头像链接列的默认显示_至少_是44px ,而不考虑可能在--avatar-size 值内传递的值。

.smol-avatar-list {  --avatar-size: 3rem;  --avatar-count: 3;  display: grid;  /* Default to displaying most of the avatar to  enable easier access on touch devices  `max` ensures the WCAG touch target size is   met or exceeded */  grid-template-columns: repeat(    var(--avatar-count),    max(44px, calc(var(--avatar-size) / 1.15))  );}

然后,当检测到一个具有悬停功能的设备也可能采取 "精细 "输入,如鼠标或手写笔时,该解决方案允许头像重叠。这种允许是由于在:hover:focus --这两种交互方式对纯触摸设备来说是不可用的--上的动画,在这些状态下完全显示出头像并满足目标尺寸。

这个片段显示了允许该检测的媒体查询。

@media (any-hover: hover) and (any-pointer: fine) {  /* Allow avatars to overlap by shrinking  grid cell width */}

使用设备能力检测,我们可以提供允许满足这一标准的体验,同时也允许设计的灵活性。

始终使用基于真实用户数据的真实设备来测试解决方案

减少运动#

你的一些用户可能有前庭障碍,有可能因为运动和闪烁/眨眼的动画而导致头痛甚至癫痫发作。

有三个主要标准。

关于更全面的信息,Val Head是一位领先的专家,他对这个标准有广泛的论述,包括这篇CSS-Tricks的文章,涵盖了与运动相关的WCAG标准

现代CSS为我们提供了一个媒体特征查询,我们可以用它来测试用户对运动的OS设定偏好。虽然你的基本动画/过渡应该符合WCAG标准中提到的与flash相关的阈值,但如果用户喜欢减少动作,你应该完全阻止它们。

这里有一个快速的规则集来全面处理这个问题,由Andy Bell的Modern CSS Reset提供。

/* Remove all animations and transitionsfor people that prefer not to see them */@media (prefers-reduced-motion: reduce) {  *,  *::before,  *::after {    animation-duration: 0.01ms !important;    animation-iteration-count: 1 !important;    transition-duration: 0.01ms !important;    scroll-behavior: auto !important;  }}

动画只运行一次,任何转换都会立即发生。在某些情况下,你要为这种可能性规划动画,以确保它们 "冻结 "在理想的帧上。

这个演示包括一个轻柔的脉冲圆圈,除非用户选择减少运动。

CSS for "Demo of `prefers-reduced-motion'"

@media (prefers-reduced-motion: reduce) {  div {    animation-duration: 0.01ms !important;    animation-iteration-count: 1 !important;  }}

@keyframes pulse { 0% { transform: scale(0.85); } 100% { transform: scale(1.25); } } .prefers-reduced-motion-13 { width: 3rem; height: 3rem; border-radius: 50%; border:3px solid purple; animation: pulse 2000ms infinite alternate easy-in-out; }

你可以在Chrome/Edge浏览器中测试这个媒体特征查询的结果,方法是打开开发工具,选择烤肉串菜单(3个垂直点),然后是 "更多工具 "和 "渲染"。然后你可以切换 "模拟CSS媒体特征偏好--减少运动 "部分的设置。

preview of the dev tools panel for this setting as described in the previous text

尊重颜色和对比度的设置#

黑暗模式似乎是一种时尚,但对于一些用户来说,它是确保他们能够阅读你的内容的关键。虽然目前没有指导原则规定内容的深色和浅色模式都是必须的,但你可以通过考虑提供这两种模式来开始对未来友好。

_一个_要求是,如果你提供深色模式,至少要继续通过成功标准1.4.3中提供的标准色彩对比准则对比度(最低)

需要满足的最低对比度至少是。

  • 正常文本为4.5:1
  • 3:1用于大型文本 - 定义为18.66px粗体或更大,或24px和更大
  • 3:1用于图形和用户界面组件(如表格输入边框)。

提醒一下。WCAG 3正在考虑一个新的色彩对比模型,但要成为标准还需要几年时间。你可以在WCAG 3指南草案中了解更多关于拟议的高级感知对比算法(APCA)的信息(这些可能会随着时间的推移而改变,直到它成为标准)。

无论你是否提供黑暗和光明模式,Windows 10设备的用户可以选择系统设置来启用高对比度模式

在大多数情况下,你应该允许用户在这个模式下的设置被应用。偶尔,高对比度设置的应用意味着对理解你的界面很重要的颜色会被移除。

在Windows高对比度模式下,有三个通常很关键的属性将被删除。

  • box-shadow
  • background-color
  • background-image ,除非它包含一个url()

还有两个关键的属性,它们的颜色将被换成 "系统颜色 "的等值。

  • color
  • border-color

你可以查看受这种 "强制颜色 "模式影响的属性的完整列表

有时这些属性可以通过使用透明的替代物来补偿。例如,如果你使用box-shadow 作为outline 的替代物,以便在:focus 上匹配border-radius ,你仍然应该包括一个颜色值设置为transparentoutline 作为补充,以保留强制颜色模式的:focus 样式。这个例子包含在我的CSS按钮样式指南中。以类似的方式,如果阴影是为了传达一个重要的边界,你可以包含一个透明的边框来代替box-shadow

如果你使用SVG图标,将currentColor 作为fillstroke 的值传递,将有助于确保它们响应强制颜色的设置。

或者,你可以使用一个特殊的媒体功能查询,从系统调色板中分配颜色。这些都是尊重用户设置,同时允许你确保你的关键界面元素保留颜色。

下面是一个使用简单的CSS形状和梯度作为图标的例子,并确保它们在强制颜色模式下保留颜色。在forced-colors 功能查询中,我们只需要设置color 属性,因为我们已经将图标设置为使用currentColor 值。

"强制颜色的演示 "的CSS

.icon {  width: 1.5rem;  height: 1.5rem;  display: inline-block;  color: blue;}.filled {  background-color: currentColor;  border-radius: 50%;}.gradient {  background-image: repeating-linear-gradient(    45deg,    currentColor,    currentColor 2px,    rgba(255, 255, 255, 0) 2px,    rgba(255, 255, 255, 0) 6px  );  border: 1px solid;}@media screen and (forced-colors: active) {  .icon {    // Required to enable colors    forced-color-adjust: none;    // User-preferred "text" color    color: CanvasText;  }}

.icon-221 { width: 1.5rem; height: 1.5rem; display: inline-block; color: blue; } .fill-221 { background-color: currentColor; border-radius: 50%; } .gradient-221 { background-image: repeating-linear-gradient( 45deg, currentColor, currentColor 2px, rgba(255, 255, 255, 0) 2px, rgba(255, 255, 0) 6px ) ; border:1px solid; } @media screen and (forced-colors: active) { .icon-221 { // Required to enable colors forced-color-adjust: none; // User-preferred "text" color color: CanvasText; } }

使用Windows高对比度模式,基于默认值的可能结果是,由于CanvasText 颜色关键字,蓝色变成白色,而页面背景变成黑色。

通过微软Edge博客上的一个更广泛的例子,回顾更多关于该模式如何工作的信息

可及性学习资源#

虽然我们在整个例子中链接了成功标准和其他资源,但还有很多东西需要学习

这里有一些额外的资源,可以了解更多。

我也创建了各种资源。

我喜欢谈论可及性,并尽力设计可及性教程,并指出任何可及性的细节。如果你发现了一个错误或想提出一个改进建议,请在Twitter上给我留言