Topics

clamp() 的间距设置中容易被忽视的无障碍问题与解决方案

  • column

使用 clamp() 来调整间距,通过最小值~最大值进行灵活设置的实现方式,最近经常被使用。

作为响应式设计方案,这非常便利。不过,考虑到无障碍放大显示(缩放),其中隐藏着一些陷阱。

常见的 clamp() 指定示例

例如,使用 clamp() 调整间距时,通常会这样编写。

:root {
  --clamp-base: 16;
  --clamp-viewport-min: 375;
  --clamp-viewport-max: 1440;

  --spacing-lg-min: 24;
  --spacing-lg-max: 48;

  --spacing-lg-slope: calc(
    (var(--spacing-lg-max) - var(--spacing-lg-min)) / (var(--clamp-viewport-max) - var(--clamp-viewport-min))
  );
  --spacing-lg-intersection: calc(
    (var(--spacing-lg-max) - var(--clamp-viewport-max) * var(--spacing-lg-slope)) / var(--clamp-base)
  );
  --spacing-lg: clamp(
    calc(var(--spacing-lg-min) / var(--clamp-base) * 1rem),
    calc(var(--spacing-lg-intersection) * 1rem + 100 * var(--spacing-lg-slope) * 1vw),
    calc(var(--spacing-lg-max) / var(--clamp-base) * 1rem)
  );
}

虽然省略了详细说明,

  • 在智能手机上为 --spacing-lg-min 的尺寸
  • 在PC上为 --spacing-lg-max 的尺寸
  • 在此期间可灵活平稳地伸缩

而且这是一个非常易用的模式,对吧。

在无障碍设计中容易踩坑的地方有哪些?

问题出现在尝试满足 WCAG 2.0 成功标准 1.4.4"文本调整大小" 的时候。

这项标准最初是在智能手机普及之前制定的,目的是"即使在PC上放大到200%也能浏览",但该条件同样适用于智能手机浏览器。

实际上用智能手机放大到 200% 时,经常会出现这样的现象。

  1. 当文本放大(缩放)时,以rem为单位的外边距也会随之放大
  2. 这样会导致围绕原始内容的空白过于宽广
  3. 因此,内容显示区域变得极为狭窄,导致布局混乱和显示不清晰。

注:不过从现实情况来看,即使是海外政府网站等被要求遵守 WCAG 的地方,也似乎很少真正实施。这可能是因为成本效益不高,或者根本上智能手机需要放大到 200% 这样的需求本身就很罕见,所以在实际操作层面上可能被认为是"即使不做也不会成为大问题"。

如何解决这个问题?

重要的是使用 vw 等视口相关单位而非 rem(会受文字放大影响),确保缩放时空白不会过度增大

但是仅使用vw进行指定,就无法充分利用clamp()的"能够控制最小值和最大值"这一优势。

这时就需要用到 min() 函数了!

min()采用所传入值中"最小的值"。利用这一特性,在常规模式和放大模式下切换应用的值。

就是这样写的。

--spacing-lg: min(
  calc(var(--spacing-lg-min) / var(--clamp-viewport-min) * 100vw),
  clamp(
    calc(var(--spacing-lg-min) / var(--clamp-base) * 1rem),
    calc(var(--spacing-lg-intersection) * 1rem + 100 * var(--spacing-lg-slope) * 1vw),
    calc(var(--spacing-lg-max) / var(--clamp-base) * 1rem)
  )
);

当以 375 CSS px 显示时,min 的初始值是 --spacing-lg-min 的值 24px 转换为 vw 后的 6.4vw。

clamp()的最小值是1.5rem = 24px,但在200%放大时会变成48px,因此左侧的6.4vw会更小,所以会应用这个值。

也就是说,

  • 正常时段(显示 100%):
    • clamp()的值会小于vw基准的值。
    • 由于min()会选择较小的值,clamp()会生效,根据屏幕宽度进行响应式显示。
  • 放大时(200%显示):
    • clamp()内的rem因放大而增大,vw基准的值反而变小。
    • vw基准的值会被应用,边距相对于屏幕宽度的比率固定,可以防止过度放大。

这样就能同时实现「响应式易用性」和「无障碍设计考量」了!

* 顺便说一下,在PC显示中,包括边距在内一起放大往往能保持设计的平衡,所以--clamp-viewport-min以此为基准,仅在智能手机上应用。

实际行为对比

上面是仅使用clamp,下面是min+clamp。

在手机上放大到200%时,差异会非常明显。

* iOS Safari 可从地址栏左侧的图标放大,Android Chrome 可从右上方的图标放大。

总结

  • clamp() 在响应式边距调整中非常便捷
  • 但是如果放大显示,空白也会被放大,可能导致布局混乱
  • 与 min() 结合使用,可以实现通常情况下可变、放大时受控这样平衡的处理方式

如果要重视 WCAG 合规性,纳入这类实现方案会让人放心。"在手机上支持 200% 放大"这样的实现仍然罕见,但它既能保持日常的易读性,又能降低无障碍访问方面的风险。

另外,如果想要调整除了空白之外的细节,也可以使用指定较小断点的媒体查询方法。

@media (max-width: 239px) {
  /* 拡大時に適用したいCSS */
}

例如,当宽度为375px的屏幕放大到200%时,浏览器会将视口宽度计算为"一半的大小(约188px)"。因此,就能够匹配这种窄屏幕的条件了。

注:239px 这个数值仅为示例,建议根据实际情况调整,既要为将来屏幕尺寸的增大预留空间,又要确保不影响通常显示效果。

将「clamp() + min()」与「狭窄断点的媒体查询」结合使用,就能实现更灵活、更可靠的无障碍设计!

本文作者

从DTP跨越到Web世界,不知不觉中已掌握标签、前端开发、创意指导、无障碍设计等各项技能的"技术高手"。从Liberogic创业初期就活跃至今,如今是公司内部的"活百科"。最近沉迷于"能否在无障碍适配上更多依赖AI?"这样的思考,正在探索借助AI提示词提高效率的方法。技术实力和思维方式都还在不断进化中

Futa

IAAP 认证网络无障碍专家 (WAS) / 标记语言工程师 / 前端工程师 / 网络总监

查看本员工的文章

安心的团队体制和迅速的反应能力是我们的优势

Liberogic 拥有经验丰富的员工团队,积极推进项目,因此获得了客户的高度评价。
我们会妥善分配项目经理和总监,确保整个项目顺利进行。 通过避免不必要的全职投入导致的成本增加,并采用适当配置人力资源的方式,从把握业务内容到估价的制作和提交速度都赢得了良好的口碑。

* 本公司不积极开展SES驻场工作等业务,敬请谅解。

Slack、Teams、Redmine、Backlog、Asana、Jira、Notion、Google Workspace、Zoom、Webex 等,您可以使用几乎所有主要的项目管理工具和沟通协作工具。

您是否在网页无障碍对应方面遇到困难?

案例分析