重新思考网页上的文本缩放

原文信息: 查看原文查看原文

Rethinking Text Resizing on Web

- Steven Bassett

两只狗从一辆停着的车的后窗向外看,背景是绿色的树叶。

Airbnb在改善需要更大字体大小的房东和客人的网络可访问性方面取得了显著进步。

本文深入探讨了:

  1. 仅依赖浏览器缩放时在移动网页上遇到的问题。
  2. 引入可能影响所有前端工程师工作流程的变更的挑战。
  3. 自推出这些可访问性改进以来所看到的好处。

作者:Steven Bassett

提高网络可访问性是Airbnb的一个关键优先事项,我们使用网络内容可访问性指南(WCAG)来帮助指导我们的合规工作。一个经常导致可访问性问题的领域是WCAG 1.4.4 调整文本大小(AA级)。我们将把这个指南称为调整文本大小,这对于视力低下的人来说尤其有益,无论是可以矫正的还是不可矫正的(例如,使用眼镜或处方隐形眼镜)。该标准规定,当文本放大到原始大小的200%(2倍)时,网页内容和功能必须保持不变。确保我们的网站满足这一指南是我们持续工作以增强所有用户可访问性的重要组成部分。

在这篇博客文章中,我们将探讨我们对这一指南重要性的调查,我们如何分析我们的网站问题,使用rem单位的技术优势,我们如何决定一种方法,我们遇到的跨浏览器支持问题,以及我们在减少调整文本大小报告问题数量方面看到的好处。

满足视力困难用户的需求

“超过4000万40岁以上的美国人有视力和眼睛问题。这超过五分之三。”

《展望未来:改善我们对未来的视力》CDC

为了说明,考虑Airbnb首页可能对视力严重下降的人看起来如何。如下所示,文本变得极其难以舒适地阅读。

Airbnb首页模拟模糊视力的效果

浏览器缩放

为了更好地理解可访问性挑战,让我们探索浏览器缩放功能的工作原理。您可能已经熟悉这个功能,使用键盘快捷键如Command / Ctrl +或Command / Ctrl —来缩放窗口内的所有内容。当您将缩放级别增加到100%以上时,视口的高度和宽度成比例减小,而内容则放大以适应更大的窗口。

作为我们可访问性测试策略的一部分,我们使用浏览器缩放来测试我们的页面在桌面和移动尺寸上的可用性。桌面测试显示,我们的页面在200%缩放级别上相对表现良好,我们的响应式网页方法贯穿整个网站。与移动网页相比,我们看到了较少的整体用户体验问题。

这在桌面上运作良好,我们提供较小的断点(例如,从宽到紧凑),视口相对宽敞。然而,浏览器缩放的限制在移动网页上变得更加明显,视口更小。如果我们要在移动视口中缩放内容,它必须适应宽度和高度都是原始视口一半的视口。这可能导致重大的可访问性问题,因为文本和UI元素变得极其难以阅读和交互。正如右侧的图片所示,甚至在不滚动的情况下查看屏幕上单个列表的能力都是不可能的,导致令人沮丧的体验。

一个较大的手机显示Airbnb首页在100%和缩放版本的首页,大小是原始大小的一半。200%缩放是视口大小的一半。

Airbnb首页在浏览器缩放100%时显示在左侧,相同的屏幕在200%显示,搜索和类别被完全切断,甚至无法看到第一个列表

字体缩放

我们将使用“字体缩放”这个术语来描述独立于整体页面缩放调整文本大小的能力。与按比例缩放所有内容的浏览器缩放不同,字体缩放仅适用于页面上的文本元素。这允许用户将字体大小自定义为他们喜欢的阅读大小,而不影响其余内容的布局或响应性。

字体缩放,也是我们将用于根据用户的首选大小缩放字体的术语。与缩放不同,此设置将应用于所有网站。下面是一个示例,演示字体缩放如何仅适用于屏幕上的文本,显示只有文本的缩放增加,而不是所有内容。

视频描述:Airbnb文本通过在arc浏览器上设置字体大小进行缩放,显示从16px缩放到32xp的缩放。

这种独立的字体缩放概念类似于我们在博客文章“在Airbnb支持动态类型”中讨论的iOS上的动态类型功能。动态类型允许用户设置首选的系统范围文本大小,然后自动调整所有兼容应用程序的字体大小。

考虑到我们在iOS上的现有可访问性策略,将字体缩放(与缩放缩放相对)纳入我们的网络可访问性方法是自然而然的下一步,以帮助在各个平台上增加方法的一致性。

理解px、em与rem

现在我们了解了为什么字体缩放对移动网页如此强大,我们应该关注为什么我们可能为支持字体缩放选择一个CSS长度单位而不是另一个。在这篇博客文章中,我们只关注px、em和rem,但也还有其他单位。CSS长度单位与字体缩放有关,因为它们决定了网页上文本和其他元素的大小。一些长度单位是固定的,意味着它们不基于用户的字体大小设置而改变,而其他一些是相对的,意味着它们与字体大小成比例缩放。

让我们深入研究3个CSS长度单位以及它们与字体缩放的关系:

  • px单位是网络上最常用的,理论上它们应该代表屏幕上的一个像素。它们是固定单位,意味着渲染值不会改变。
  • em单位是一种相对单位,基于父元素的字体大小。名称‘em’来自给定字体中大写字母‘M’的宽度,传统上用作字体大小的参考点。1个em单位等于当前字体大小的高度,大约是默认值的16px。em单位按比例缩放,因此它们可能受到其父元素的字体大小的影响
  • rem单位,全称为“root em”,与em单位类似,它们与字体大小成比例,但它们只使用根元素(html元素)来计算它们的字体大小。这意味着rem单位提供字体缩放,但不受其父元素的字体大小的影响。

在em和rem单位之间的选择通常取决于字体缩放所需的控制和可预测性水平。虽然可以使用em单位,但它们可能导致级联的字体大小更改,这可能很难管理,特别是在复杂的布局中。相比之下,rem单位提供了一种更一致和可预测的字体缩放方法,因为它们总是相对于根元素的字体大小。

这在CodePen示例中得到了说明,其中展示了px、em和rem单位的不同字体缩放行为。在字体缩放是关键要求的情况下,例如提到的Airbnb示例,使用rem单位可能是一个更可靠的选择,以确保一致且可维护的字体缩放解决方案。

像rem这样的相对单位可以用于任何可以使用像px这样的固定单位的地方。然而,不加选择地在所有属性中使用rem单位可能导致不需要的缩放行为和增加的复杂性。

在Airbnb的情况下,团队决定特别优先使用rem单位用于字体缩放,而不是按比例缩放所有元素。这种有针对性的方法提供了一致文本缩放的关键好处,而没有按比例缩放布局的每个方面可能带来的缺点。

这个决定背后的理由有两个:

  1. 使用rem单位缩放一切将类似于浏览器缩放,并可能引入意想不到的布局问题,
  2. 主要关注点是提供移动友好的字体缩放解决方案。通过使用rem单位针对字体大小,团队可以确保最重要的内容——文本——适当缩放。

为设计师和开发人员实现无缝过渡

从基于像素的值转换为作为CSS实践的全公司变更的rem单位可能是一个重大挑战,特别是当跨多个团队工作时。教育设计师和前端开发人员采用新方法,并将他们现有的基于像素的值转换为rem单位所需的时间和精力可能是采用的一个重大障碍。为了解决这个问题,Airbnb团队决定尽可能自动化单位转换过程,实现向新的基于rem的系统的更无缝过渡。

减少设计迭代中的摩擦

而不是要求设计师考虑新的单位或为网络仅引入一些转换,我们决定继续以px单位编写我们的CSS。这减少了团队开始使用rem单位所需的培训量。

我们确实关注设计团队的一个领域是开始使用字体缩放测试他们的设计,利用Text Resizer — Accessibility Checker 来帮助模拟设计在2X字体大小时可能的外观。这个工具帮助我们在设计过程的早期发现问题。

解决两个CSS-in-JS系统的复杂性

Airbnb正在从React-with-Styles过渡到使用Linaria的更新方法。虽然Linaria的采用进展迅速,但我们认识到需要支持两种风格系统以获得一致的体验。管理这两种不同的CSS-in-JS系统之间的转换带来了额外的挑战。

Linaria

通过利用Linaria对CSS自定义属性的支持,团队能够创建新的排版主题值,这些值自动将现有的基于像素的值转换为它们的rem等效项。这种方法允许团队以集中的方式引入新的基于rem的主题值,使它们可供子元素使用。这给了团队在过渡过程中按页面覆盖rem值的必要灵活性。

import { typography } from './site-theme';  

// 循环遍历我们用于排版的CSS变量,并从px转换为rem单位。  
const theme: css\` ${getCssVariables({ typography: replacePxWithREMs(typography) })} // 从:  
 // - body-font-size: 16px;  
 // 改变为  
// - body-font-size: 1rem;   
\`;  
// 使用Linaria生成的类名来覆盖此组件的子元素的主题变量。  
const RemThemeLocalProvider: React.FC = ({ children }) => {  
 const cx = useCx();  
 return <div className={linariaClassNames.theme)}>{children}</div>;  
};

尽管这种方法帮助我们转换了大部分字体缩放属性,但我们的代码中有许多地方我们在主题之外使用了基于px的值。Linaria对post-CSS插件的支持使解决这些领域相对容易。我们利用postcss-pxtorem 更容易地针对这些值。我们首先使用允许列表,这样我们就可以谨慎地将此更改应用于较小的早期采用页面集。

当前端工程师需要使用px单位时,提供紧急出口非常重要。幸运的是,我们能够通过使用不同的大写形式来提供这一点,如下所示。

/* `px` 被转换为 `rem` */  
.convert {  
  font-size: 16px; /* 转换为 1rem */  
}  
/* `Px` 或 `PX` 被 `postcss-pxtorem` 忽略  
  但仍然被浏览器接受 */  
.ignore {  
  font-size: 200Px;  
  font-size: clamp(16Px, 2rem, 32Px);  
}

React with Styles

我们的前端代码中还有相当一部分使用react-with-styles,所以我们不得不找到另一种方式来支持这些情况,并轻松转换。通过这个,我们创建了一个简单的高阶组件,使得转换变得相当直接。首先,我们为withStyles函数创建了一个包装器,如下所示,并提供了避免转换的能力。

export const withRemStyles = (  styleFn?: Nullable<(theme: Theme) => Styles>,  
  options?: WithStylesOptions & { disableConvertToRemUnits?: boolean },) => {  
  const disableConvertToRemUnits = getDisableConvertToRemUnits(options);  
   // 如果转换被禁用,只返回原始的withStyles函数  
   if (disableConvertToRemUnits) {  
     return _withStyles(styleFn, options);  
    }  
   // 否则,包装原始样式函数  
   // 用一个新的函数将px转换为rem  
   return _withStyles((theme: Theme) => {  
     if (styleFn) {  
     const styles = styleFn(theme);  
     const remStyles = convertToRem(styles);  
     return remStyles;  
   }  
   return {};  
 }, options);  
};

然后convertToRem将查看键和值,并为任何字体大小属性映射转换后的值。这使我们能够以更直接的方式自动化转换过程。

改进组件测试

有了这两个挑战,我们可以开始测试我们的组件,以验证在推出之前是否需要解决任何重大问题。在我们的组件文档和工具中,我们构建了一个内部插件,允许通过直接设置html元素上的字体大小来更容易地进行测试,以进行字体缩放测试。

截图测试帮助我们的团队捕获视觉回归。添加支持以允许在不同的根字体大小时设置额外的截图,帮助我们的产品团队审查组件在不同的字体缩放下的外观。为此,我们允许在捕获截图时设置额外的字体大小,以便您不必仅为了字体缩放而创建新的组件变体。

移动Safari上的字体缩放

支持移动Safari的字体缩放更加困难。与其他浏览器不同,移动Safari中没有可用的字体大小偏好。然而,他们已经发布了对他们自己的字体:-apple-system-body的支持,但有一些重要的考虑因素。

由于macOS High Sierra(10.13)以来,桌面Safari也支持字体偏好,但在MacOS中没有简单的“字体大小”配置可用。由于桌面Safari上可能有意外的行为,所以我们使用@supports语句来防止这种情况。下面的代码将仅针对移动Safari。

// Apple的动态类型需要使用这个字体系列  
// 仅针对iOS/iPadOS  
@supports (font: -apple-system-body) and (\-webkit-touch-callout: default) {  
  :root {  
    font: -apple-system-body;  
  }  
}

另一个考虑因素是,“100%”默认字体大小选择不等于标准字体大小16px,而是17px。这是一个非常微妙的差异,但对于我们在Airbnb追求的设计质量标准至关重要。因此,为了解决这个问题,我们最终使用了一个内联头部脚本来规范化值,通过将其早期放入页面执行中,我们避免了看到字体大小的变化。

(() => {  
  // 如果浏览器不匹配支持语句,不要做任何事情  
  if (!CSS.supports('(font: -apple-system-body) and (-webkit-touch-callout: default)')) return;  
  // 必须创建一个元素,因为根元素的样式尚未解析。  
  const div = document.createElement('div');  
  div.setAttribute('style', 'font: -apple-system-body');  
  // Body尚未可用,所以这必须添加到根元素  
  documentElement.appendChild(div);  
  const style = getComputedStyle(div);  
  if (style.fontSize === '17px') {  
    documentElement.style.setProperty('font-size', '16px');  
  }  
  documentElement.removeChild(div);  
})();

然后,当页面加载时,我们使用resize observer来检测值是否再次更改为取消设置或设置html元素上的字体大小属性。这有助于我们仍然支持可缩放的字体,但不会对默认字体大小(100%)产生重大影响。

影响

支持可缩放的字体是一项投资,应该为我们的房东和视力低下的客人以及任何从更大的字体大小和对浏览体验的控制中受益的人带来戏剧性的变化。以下是两个示例,展示了首页在默认字体大小(16px)对于视力模糊的人看起来如何,以及将字体大小加倍(32px)时的外观。第二张图片更易读和可用。

两个移动屏幕显示带有模糊视力的Airbnb列表:左侧屏幕字体大小为16px更难阅读,右侧屏幕字体大小为32px更易读。

对于带有模糊视力的Airbnb列表的字体大小比较,以提高可读性:16px与32px。

选择字体缩放作为产品可访问性策略带来了一系列显著的好处,显著增强了我们平台的整体用户体验。使用自动化将转换为rem单位使这个过渡更容易。在这些更改在全站范围内实施后,我们现有的80%以上的调整文本问题都得到了解决。此外,从那时起,我们看到的新问题更少。

总之,我们在增强网页上的调整文本方面的旅程充满了有价值的实践经验。从我们如何战略性地应用rem单位,到工具和自动化的作用,每个经验都是提升Airbnb用户体验的重要一步。我们希望通过分享我们的旅程,可以帮助其他人更无缝地进行这个过渡。我们的工作正在进行中,我们致力于不断推进Airbnb的可访问性。如果您对此类挑战充满热情,我们邀请您探索Airbnb的职业机会

感谢:

  • Alan Pinto Souza、Dennis Wilkins、Jimmy Guo和Andrew Scheuermann的建议和技术审查。
  • Sterling DeMille、Riley Glusker和Ryan Booth作为早期产品合作伙伴。
  • Jordanna Kwok、Sarah Alley和JN Vollmer支持这种方法。
  • Veronica Reyes和Jamie Cristal提供设计支持。

所有产品名称、标志和品牌均为各自所有者所有。本网站上使用的所有公司、产品和服务名称仅用于识别目的。使用这些名称、标志和品牌并不意味着认可。

分享于 2024-05-23

访问量 46

预览图片