网站可访问性一直都很重要,但如今,随着大多数国家/地区的政府都制定了明确的标准和法规,支持这些标准并使我们的项目尽可能地易于访问变得更加至关重要。
W3C 建议提供了 3 个级别的符合性:A
、AA
和 AAA
。为了达到 AA
级,除了其他要求之外,我们还必须提供一种方法来增加网站的字体大小。
1.4.4 调整文本大小:除了 字幕 和 文本图像 外,文本 可以使用 辅助技术 调整大小至 200%,而不会丢失内容或功能。(AA 级)
让我们看看针对此问题的解决方案,并尝试找到最佳方案。
更新 (2017 年 9 月 25 日):事实证明,WCAG 并不需要除了用户代理提供的功能之外的文本调整大小自定义解决方案。我们只需要确保网站在调整大小后看起来正常即可。但是,如果我们仍然出于任何原因想要缩放元素,以下是对执行此操作的不同方法的全面分析。
zoom
不完整的解决方案:CSS 当我们谈论尺寸更改时,第一个想到的词就是缩放。CSS 具有 zoom
属性,它可以准确地执行我们想要的操作——增加尺寸。
让我们看一下一个常见的界面设计模式(我们将在本文的其余部分使用它):一个水平导航栏,在某个断点处会转换为菜单图标。

下面的 GIF 显示了将 zoom
方法应用于菜单元素后得到的结果。我创建了一个切换器,允许选择不同的尺寸并应用相应的缩放级别。

菜单超出了可见区域,因为我们无法使用缩放以编程方式增加视口宽度,也无法因为要求而换行菜单。菜单图标也不会出现,因为屏幕尺寸实际上没有改变,与我们单击切换器之前相同。
所有这些问题,加上 zoom
本身根本不受 Firefox 支持。
错误的解决方案:缩放变换
我们可以使用 transform: scale
获得与 zoom
非常相似的效果。除了 transform
得到更广泛的 浏览器支持。但是,我们遇到了与 zoom
完全相同的问题:菜单不适合可见区域,更糟糕的是,它也超出了垂直可见区域,因为页面布局是根据初始 1 倍缩放计算的。
查看 Mikhail Romanov (@romanovma) 在 CodePen 上的示例代码 Font-switcher–wrong-scale。
rem
和 html
font-size
另一个不完整的解决方案:与其缩放或变换,我们可以使用 rem
作为页面上所有元素的尺寸单位。然后,我们可以通过更改 html
元素的 font-size
属性来更改其大小,因为根据定义,1rem
等于 html
的 font-size
值。
这是一个相当不错的解决方案,但并不完美。正如您在以下演示中看到的,它与前面的示例存在相同的问题:在某个点上,它无法水平适配,因为所需的空间增加了,但视口宽度保持不变。
查看 Mikhail Romanov (@romanovma) 在 CodePen 上的示例代码 Font-switcher–wrong-rem。
问题在于,媒体查询不会根据尺寸变化进行调整。当我们放大尺寸时,媒体查询应该相应地调整,以便在相同位置的效果在尺寸变化之前发生,相对于内容而言。
mixin
模拟浏览器缩放
有效的解决方案:使用 Sass 为了寻找灵感,让我们看看原生浏览器缩放功能是如何处理这个问题的。

哇!Chrome 理解缩放实际上确实会改变视口。缩放倍数越大,视口越窄。这意味着我们的媒体查询将按我们的预期生效,并且需要它们生效。
实现此目标的一种方法(不依赖于原生缩放,因为我们无法访问 AA 所需的页面内控件的原生缩放)是以某种方式在每次切换字体大小时更新媒体查询值。
例如,假设我们在 1024px
处有一个媒体查询断点,并且我们执行 200%
缩放。我们应该将该断点更新为 2048px
以补偿新的尺寸。
这难道不应该很容易吗?我们不能只使用 rem
单位设置媒体查询,以便当我们增加 font-size
时媒体查询会自动调整吗?遗憾的是,这种方法不起作用。尝试在此 示例代码 中将媒体查询从 px
更新为 rem
,您会发现没有任何变化。在增加尺寸后,布局不会切换断点。这是因为,根据 标准,媒体查询中的 rem
和 em
单位都是基于 html
元素 font-size
的初始值计算的,该值通常为 16px
(并且可能会有所不同)。
媒体查询中的相对单位基于初始值,这意味着单位永远不会基于声明的结果。例如,在 HTML 中,
em
单位相对于“font-size
”的初始值。
但是,我们可以利用 Sass mixin
的功能来解决这个问题!以下是我们的操作方法。
- 我们将对
html
元素使用一个特殊的类来表示每个尺寸(font-size--s
、font-size--m
、font-size--l
、font-size--xl
等)。 - 我们将使用一个特殊的
mixin
,它为断点和尺寸的每种组合创建一个媒体查询规则,并同时考虑屏幕宽度和应用于html
元素的修饰符类。 - 在我们要应用媒体查询的任何地方,我们都将代码包装在此
mixin
中。
以下是此 mixin
的外观。
$desktop: 640px;
$m: 1.5;
$l: 2;
$xl: 4;
// the main trick is here. We increase the min-width if we increase the font-size
@mixin media-desktop {
html.font-size--s & {
@media (min-width: $desktop) {
@content;
}
}
html.font-size--m & {
@media (min-width: $desktop * $m) {
@content;
}
}
html.font-size--l & {
@media (min-width: $desktop * $l) {
@content;
}
}
html.font-size--xl & {
@media (min-width: $desktop * $xl) {
@content;
}
}
}
.menu {
@include media-desktop {
&__mobile {
display: none;
}
}
}
以及它生成的 CSS 示例。
@media (min-width: 640px) {
html.font-size--s .menu__mobile {
display: none;
}
}
@media (min-width: 960px) {
html.font-size--m .menu__mobile {
display: none;
}
}
@media (min-width: 1280px) {
html.font-size--l .menu__mobile {
display: none;
}
}
@media (min-width: 2560px) {
html.font-size--xl .menu__mobile {
display: none;
}
}
因此,如果我们有 n 个断点和 m 个尺寸,我们将生成 n 乘以 m 个媒体查询规则,这将涵盖所有可能的情况,并使我们能够在字体大小增加时使用增强的媒体查询。
查看下面的示例代码以了解其工作原理。
查看 Mikhail Romanov (@romanovma) 在 CodePen 上的示例代码 Font-switcher–right。
缺点
但也有一些缺点。让我们看看如何处理它们。
媒体查询选择器上的特异性增加。
媒体查询内的所有代码都获得了额外的特异性级别,因为它位于 html.font-size — x
选择器内部。因此,如果我们采用移动优先方法并例如在元素上使用 .no-margin
修饰符,则桌面正常样式可能会胜过修饰符,并且会应用桌面边距。
为了避免这种情况,我们可以为移动端创建相同的 mixin
,并使用我们的 mixin
不仅包装桌面 CSS 代码,还包装移动端 CSS 代码。这将平衡特异性。
其他方法是通过人为地提高特异性或创建具有所需功能(在我们的示例中为无边距)的 mixin
并将其不仅用于移动端,还用于每个断点代码来处理每个特殊情况。
生成的 CSS 代码量增加。
生成的 CSS 代码量会更高,因为我们为每个尺寸都生成了相同的 CSS 代码。
如果文件使用 gzip 压缩(通常情况下是这样),这应该不是问题,因为它可以很好地处理重复的代码。
一些前端框架(如 Zurb Foundation)在 JavaScript 工具和 CSS 媒体查询中使用内置断点。
这有点棘手。就我个人而言,我会尽量避免依赖屏幕宽度的框架功能。其中一个经常被忽略的功能是网格系统,但随着 flexbox 和 grid 的兴起,我认为这已经不再是问题了。查看这篇文章,了解有关如何构建自己的网格系统的更多详细信息。
但是,如果项目依赖于这样的框架,或者我们不想解决特异性问题但仍然想使用 AA,那么我会考虑去除固定高度元素,并结合使用 rems
和修改 html
元素的 font-size
来相应地更新布局和文本尺寸。
感谢您的阅读!如果您觉得这有帮助,或者在符合 1.4.4 调整文本大小 W3C 无障碍要求方面遇到其他问题,请告诉我。
我最近做了很多工作,试图以编程方式检测用户是否使用浏览器控件(键盘命令或菜单)进行了缩放。这会影响所见即所得应用程序渲染文本的方式。不幸的是,由于视网膜屏幕和其他移动设备,目前无法确定浏览器是否已缩放。大多数答案会引用
window.devicePixelRatio
,但根据设备和缩放级别,此方法会失败。看起来这个比率是由设备制造商任意设置的,以便将更多像素塞进设备中。在实现页面内文本调整大小窗口小部件后,我会非常谨慎地建议使用它,因为使布局随文本正确缩放会带来很大的复杂性。
根据 WCAG 指南,自定义文本调整大小窗口小部件也不需要满足此标准(除非支持旧版浏览器)。
(https://www.w3.org/TR/UNDERSTANDING-WCAG20/visual-audio-contrast-scale.html
因此,考虑到这一点,我会专注于正确使用 ems/rems,并构建一个良好的响应式网站,以便浏览器本机缩放能够获得最佳效果。
嗯……我认为 WCAG 并没有建议每个网站都实现自己的自定义缩放控件——他们只是意味着您应该在各种浏览器缩放级别下测试您的网站。
引用规范时,请提供链接。
https://www.w3.org/TR/WCAG20/#visual-audio-contrast-scale
已完成,感谢您指出。
您真的应该尝试在最小宽度为 50em 的媒体查询中将字体大小设置为类似“1.13vw”的值。
嗨,Eric。不幸的是,我不明白你的意思。你能否提供更多详细信息,例如我应该在哪里执行此操作以及预期结果是什么?
顺便说一句,根据规范的示例(https://www.w3.org/TR/UNDERSTANDING-WCAG20/visual-audio-contrast-scale.html),此功能仅在必须在不支持用户代理缩放的浏览器(例如 IE6,但不包括 IE7 及更高版本)上支持时才需要。
但是,这确实是解决该问题的非常酷的方案。
哇,发现得不错!看起来根据规范,我们实际上可以依赖浏览器本机缩放。
但是,除了 IE6 之外,我们至少还有
– iOS Safari(我看不到在不使用“阅读器视图”(它会切断嵌入的 Pen 示例)的情况下缩放其内容的方法),
– 以及不同的 Web 视图(例如从 Facebook 或 Inbox 应用程序浏览网页),它们也不提供缩放支持。
需要注意的是,WCAG 2.0 并没有要求开发人员添加任何类型的文本调整大小窗口小部件。
它对开发人员更改事物大小的不同方法进行了有趣的分析,但说任何人都应该将它们用于无障碍和/或 WCAG 符合性目的,这非常具有误导性。
是否可以在顶部(就在 1.4.4 引用下方)添加一个注释,内容类似于
“我最初在编写这篇文章时认为这是 WCAG 要求的,但后来发现该要求是用户能够更改其设置(缩放或文本大小),并且网站仍然可以正常工作。但是,它仍然是对缩放元素的不同方法的有趣分析”(或者其他类似的内容,您理解我的意思)
您可能感兴趣的是,下一版 WCAG(2.1,将于明年发布)可能会更新此要求,明确要求浏览器缩放可以工作到宽度相当于 320px 的程度。(可供评论的草案。)
是的,我肯定会根据所有评论进行操作。
我给 W3C 发了一封电子邮件寻求澄清,但到目前为止还没有收到回复。
感谢您的反馈。
您将邮件发送到哪里?我参加了 WCAG 工作组,我没有看到它,但这些邮件可能发送到很多地方!我认为合适的地方应该是 public-agwg-comments(@w3.org),但我们目前正在处理 wcag 2.1,因此它可能会被搁置。
最好查看我上面链接的更新指南,该指南无论如何都会更改要求……
我发送到 [email protected],但没关系,因为您在这里。
因此,使用浏览器本机缩放功能符合 AA。这是个好消息。
您能否澄清一下 iOS Safari 和 Facebook 或 Google Inbox iOS 应用程序等 Web 视图(我们可以在其中查看网站内容)的情况。我找不到在那里缩放内容的方法,
而无需在多个轴上滚动
,如您提供的指南更新中所述。(好吧,我们有时可以在 Safari 中访问阅读器视图,但它会删除某些内容——例如嵌入的 Pen。)
这就是为什么它被表述为缩放至 320px 宽,这是“内容要求”,即作者/开发人员可以控制的内容。
iOS/Android 目前不支持带回流的缩放(除了允许一些回流的 Android 版 Opera),但在没有更好的支持的情况下,我们无法要求开发人员解决用户代理中的问题。
还有一个实际问题,即它本来就是一个小型界面,那么东西该放在哪里呢?用户也需要负起一些责任,拥有满足其需求的设备,对于视力低下的人来说,这意味着更大的屏幕。这里可能需要做一些改进,但这将留待下一版本进行。
解决方案是否仅仅是不使用像素作为单位?
在媒体查询中使用 ems,在元素中使用 rems。