{T}

提升可访问性动画的关键技巧

Web 上的动画通常是一个有争议的话题。我认为,部分原因是糟糕的动画非常明显,而精心制作的动画则会无缝地融入背景。当处理得当时,动画确实可以提升 Web 应用或网站的水平,无论是为其增添一些个性,还是提供视觉提示和减轻认知负担。不幸的是,通常感觉有两个阵营,即可访问性和动画。

可访问性之所以重要,是因为它创造了一个更具共情力的 Web ,改善了每个人的体验。以动画、视频或 GIF 形式呈现的运动可以带来更大的背景和洞察力。然而,对许多人来说,动画可能会产生令人不适的体验,尤其是在过度使用时。对于某些其他人,包括那些患有注意力障碍的人,动画可能会带来额外的挑战,阻碍他们专注于内容。此外,对于那些患有更严重病症的人,比如一些有认知障碍的人(比如与平衡相关的病症或患有某种前庭功能障碍),任何形式的运动(动画)都可能触发身体不适,表现为恶心、头晕和头痛等症状。在更极端的情况下,患有光敏性癫痫的人可能会对某些类型的视觉刺激产生癫痫。

如何在运动敏感性和我们使用动画增强用户界面的目标之间取得平衡?通过理解不同用户群体的需求,我们只需要使用一系列关键技巧,包括使用媒体查询、优化动画参数、考虑前庭障碍等。通过遵循这些建议,Web 开发者可以确保他们的动画不仅令人印象深刻,而且对所有用户都是友好的,即可以帮助 Web 开发者在创造动画过程中平衡动画的吸引力和可访问性。

共情动画

我们先从“共情动画”聊起。要聊共情动画,就得先说“Web 共情”。

Web 共情通常指的是在 Web 设计和开发中考虑用户的感受和需求,以创造更加人性化、体贴和易用的用户体验。这包括关注用户的情感状态、心理需求和潜在的挑战,以确保 Web 应用或网站能够更好地满足用户的期望,并在使用过程中提供愉悦的体验。

对于 Web 动画而言,它仅仅是 Web 应用或网站的一部分。我们在创建 Web 动画时,同样要基于 Web 共情的原则,创造一个“共情动画”。

我们所说的“共情动画”则是指通过动画效果来增强用户体验,同时考虑到用户的感受和需求。这类动画通常旨在更加自然、流畅地响应用户的操作,提供更直观、友好的界面反馈。共情动画的目标是与用户建立情感连接,使用户感到他们与 Web 应用或网站之间存在一种互动和理解。

在实践中,共情动画可能包括一些微交互和过渡动画等,以更加细致入微的方式传达信息,帮助用户更好地理解界面发生的变化。然而,需要谨慎使用这些动画,确保它们不会引起用户的不适或干扰用户的正常使用。

正如现实生活中的万物一样,Web 动画也是一把双刃剑。要是动画处理得当,可以真正提升 Web 应用或网站的品质和用户体验,反之则降低 Web 应用或网站的质量,甚至给用户带来不适。这意味着,Web 动画给人的感觉像是两个阵营,即 Web 可访问性与 Web 动画。对于 Web 开发者而言,总是希望这两者都可兼得!

简单地说,Web 开发者在创建一个具有可访问性的 Web 动画,即共情动画。只需要在创建动画时,多问问自己:

  • 这个动画有用吗?这听起来似乎很严肃,但别担心,我们只需要知道 Web 应用或网站的目的是什么。如果你正在建立个人作品集,那尽管发挥!但是,如果有人试图提交纳税申报,古怪的加载动画可能不会受到好评。另外一方面,动画进度条可能是一个不错的选择,同时提供用户操作的视觉反馈。
  • 动画是否转移对重要信息的关注?陷入让事物飞来飞去的兴奋中太容易了,但请记住,Web 主要是一个信息系统。当用户试图阅读时,使文字动起来或在附近播放的循环动画可能会极大地分散用户的注意力,尤其是对于患有注意力缺陷障碍或多动症的人。出色的动画有助于集中注意,它不会干扰用户。
  • 我们是否允许用户选择退出?我们制作的动画对于运动敏感的人来说,安全最为重要。那些患有前庭(内耳)障碍的人可能会因 Web 动画而感到头晕、头痛,甚至恶心

这意味着,在某些情况下,给 Web 应用或网站添加动画并不是件好事。因此,在某些情况下,Web 动画,无论大小,都可能对用户体验产生不利影响。动画可能会分散用户注意力,过度刺激用户,甚至令用户感到烦感与讨厌,有时还会触发用户的疾病,比如出现晕动病或眩晕。

事实就是如此,用户对 Web 动画的反应五花八门。有积极的反应,有消极的反应,有时甚至根本没有反应。这同时使我们意识到,我们创建的一些 Web 动画可能会引起用户的烦恼或不适。如此一来,我们将面临着一个挑战:“我们应该在 Web 应用或网站上保留这些动画还是彻底删除它们?如果我们删除它们,我们将如何向用户提供反馈?而没有动画将如何影响用户对我们产品的理解?”

这也将进一步促使我们更应该创建一个具有可访问性的 Web 动画。

可访问 Web 动画的重要性

通常情况之下,说起可访问 Web ,很多同学首先会想到无障碍。也很容易将可访问性与永久性残疾联系起来,但我们经常忘记临时或情境性残疾以及它们如何影响用户体验。

正如上图所示,访问你的产品的用户可能没有前庭功能障碍,但有的用户可能会经历暂时的视力丧失或脑震荡,或者仅仅因为整天盯着屏幕而感到视觉上疲劳。

然而,Web 可访问性意味着,每个人都可以感知、理解、导航、与 Web 交互,并为 Web 做出贡献(这也是前面所说的 Web 共情)。在这方面,Web 应用或网站的可访问性包括所有影响网站访问的条件,例如视觉、听觉、物理、语言、认知和神经功能障碍。其中动画更是如此,因为它占据视觉、交互、认知等方面。

这也是为什么创建一个可访问 Web 动画重要原因。

阅读到这里,你可能想,你都说了这么多了,那到底如何制作一个可访问 Web 动画。简单地说,把控制权交给用户,通过做减法使动画能服务于所有用户。在当下,很多终端都提供了用户偏好的相关设置,假设用户开启了减少运动(Reduced Motion)偏好设置,我们就需要在我们的产品上,让这些用户看不到动画,或少看到动画。也就是说,我们的目标是将减少动画偏好无缝地整合到 Web 应用或网站中,并为所有用户的福祉做出贡献。

为什么要减少运动?

减少运动偏好(Reduced Motion Preferences)是一种用户喜好的行为,现如今的大多设备都提供了该项设置,Web 开发者即使是使用纯 CSS 也可以获得这些信息。在详细介绍这项技术之前,我们先退一步,聊一下为什么要减少运动?

自 2013 年 iOS7 发布引发了数字界面的一场认识,即屏幕上的一些动效,即使是界面的一部分,对于对动效敏感的人可能会有身体上的影响。这些动效敏感的根本原因在个体之间可能存在很大的差异。对于一些人来说,它源于平衡障碍,而对于其他人来说,它可能源于偏头痛或其他因素。引发的原因也因人而异,对于一些人来说,甚至可能每天都不同。个体由于引发动效而经历的身体症状可以从轻微的头晕或头痛到恶心或更严重的情况不等。

我们在工作中围绕动画做出的设计选择直接影响着我们的工作如何影响对动效敏感的人。了解哪些动效可能引发问题,以及我们如何通过设计选择来减轻这些问题,有助于我们设计对我们的受众安全且不会造成意外伤害的体验。动画绝对仍然可以对我们的 UX 工作产生积极的影响,但我们必须确保负责任地使用它,就像我们努力负责任地使用其他设计工具一样。

这样做是很重要的,也是值得的。Web 应用或网站用户可能因为多种原因而更喜欢减少运动。但最常见的原因是:

  • 注意力:许多用户在面对 Web 动画时难以保持注意力。这可能是由于注意力缺陷障碍,或者简单地更喜欢设计不与内容竞争的界面
  • 前庭障碍: 前庭障碍是一种内耳疾病,可能在对动画内容产生反应时引发恶心、头痛和眩晕等症状

无论原因是什么,尊重用户的运动偏好至关重要。有些用户可能只是被高度动画的网站所困扰或感到烦恼。但有些用户可能必须完全停止使用,以防止不良的身体反应。

减少运动设计的提示

更有意思的是,我们所说的动画和运动有一个重要的区别:动画并不等同于运动(Animation ≠ Motion )。虽然所有移动的元素都是动画,但并非每个动画元素都涉及位置的改变。

庆幸的是,WCAG 提供了界面中的运动相关的三个标准:

  • 暂停、停止和隐藏:我们应该允许用户暂停、停止或隐藏任何移动、闪烁或滚动的内容,以及那些自动启动或更新的内容,或者持续时间超出五秒并与其他内容同时呈现。
  • 移动或闪烁的元素:WCAG 标准包括避免癫痫和负面身体反应的准则,以避免间歇性动画,其闪烁频率超过每秒三次,因为这可能引发癫痫发作。
  • 通过交互产生的动画:WCAG 标准规定用户应能够与 UI 进行交互,而不仅仅依赖于动画。换句话说,用户应该能够停止任何类型的运动,除非动画对功能或传达信息至关重要。

这些基本原则可以用来帮助我们决定在工作是否使用动画以及如何使用动画。既然这三个标准如此重要,我们稍微花点时间来了解一下它们。

暂停、停止和隐藏

WCAG 对于动画的第一条建议就是“暂停、停止和隐藏”。对于这一点,它是这么规定的:

对于任何开始自动播放、持续时间超过五秒,并与其他内容并列呈现的移动、闪烁和滚动信息,用户都应该有一种机制可以暂停、停止或隐藏它,除非该移动、闪烁或滚动是必不可少的一部分。

这条建议非常适用于自动启动而无需用户交互的动作,起初可能听起来与 Web 动画无关。另外,在介绍动画持续时间时,多次强调,动画的持续时间不宜过长,否则会给动画带来不好的效果。

也就是说,就 Web 动画来说,我们可能使用的大多数持续时间都会远远低于五秒。但 Web 上有一些常见的模式适用于此建议。例如,自动播放的轮播或幻灯片、动画背景或动画插图。尽管这些模式中的每个单独动画可能仍然非常短暂,但通常创建的整体运动往往持续时间会超过五秒。尤其是动画被设置为无限循环播放时,它肯定会超过五秒。

如果你的应用或网站有一些较长的动画,那么就需要在应用或网站添加暂停、停止和隐藏机制,以允许用户关闭可能存在问题的运动动画(Motion Animation)。例如,你给自动播放的轮播或幻灯片组件添加暂停和播放等控件。注意,WCAG 规范并未规定这些控件的外观,因此,你可以完全控制其设计,即减少运动设计的提示。具体技术实施和代码暂且不表,稍后再介绍。

移动或闪烁的元素

在制作动画时,应该考虑动画元素的移动是否过度。例如,屏幕颜色具有类似霓虹灯的闪烁效果或有元素在屏幕上快速来回移动,它们都可能导致光敏性癫痫患者惊厥。据估计,3% 的癫痫患者遭受了光敏反应,这种症状在女性和年轻人中更常见。

WCAG 规范对于移动或闪烁的元素提出两条建议:

这个建议背后的主要原因是屏幕上的明显闪烁往往会导致用户无法使用 Web ,最严重的还会导致疾病。简而言之,Web 上不包含在任何一秒内闪烁超过三次的内容,或者闪烁在一般闪烁和红色闪烁的阈值以下

WCAG 提供了屏幕闪烁可以被认为是安全的尺寸、比例和观看角度的详细信息。但对于大多数人来说,最容易的方法是避免任何在一秒钟内闪烁超过三次的内容。另外,很少有 Web 设计师会刻意让屏幕过度闪烁,但这种情况确实发生。例如,一个追求视频游戏感觉或具有故障感的设计可能涉及一些比一稍钟多次的屏幕闪烁。

另外,对于任何极端运动,请务必使用光敏性癫痫分析工具 (PEAT) 进行测试。

Tools: https://trace.umd.edu/peat/

注意,PEAT 是一款免费工具,用于确定屏幕内容、视频或动画是否可能会导致惊厥。并非所有内容都需要通过 PEAT 评估,但出于安全考虑,包含浅色和深色背景之间闪烁或快速过渡的内容也应进行评估。

关于动画和动画的另一个问题是,元素的移动对于理解屏幕上的内容或操作是否至关重要。如果这并非必要,请考虑去除你正在构建或设计的元素中的所有移动,甚至是微移动。

假设你认为该元素的移动不是必需的,但可以增强用户的整体体验,或者由于其他原因无法移除该移动。在这种情况下,你应该遵循 WCAG 的运动准则。该准则规定,你必须构建一个选项,让用户能够针对以下元素暂停、停止或隐藏:自动启动、持续超过五秒且属于其他页面元素的非必需的移动、闪烁或滚动元素。

通过交互产生的动画

通过交互产生的动画涵盖了与前两者(“暂停、停止和隐藏”和“移动或闪烁的元素”)不同类型的动画。“暂停、停止和隐藏”与“移动或闪烁的元素”两准则通常适用于由 Web 应用或网页本身启动的动画,而这个准则更适用于由用户交互启动的动画。更具体地说:

可以禁用由交互触发的运动动画(Motion Animation),除非动画对功能或传达的信息至关重要

首次接触到“运动动画”术语时,会感到困惑。因为,我通常将“运动”(Motion)和“动画”(Animaiton)两个术语互换。一开始给我感觉,“运动动画”太过于具体,但在这种情况下,这样描述是有意义的。WCAG 将“运动动画”定义为用于“营造移动幻觉”的动画,并明确指出“运动动画不包括颜色、模糊或不透明度的变化”。

实质上,“运动动画”(Motion Animation)指的是通过图形、图像或元素的动态变化,营造出一种物体移动或产生变化的视觉效果。这种动画通过逐帧变化元素的位置、形状、大小或其他属性,使用户感受到这些元素在屏幕上实际上在运动或发生变化。

通俗来说,运动动画就是通过改变图形或元素的外观,让它们看起来好像在屏幕上移动或变形的效果。这可以是简单的元素平移,也可以是更复杂的形状变化或旋转。这些动画通常用于增强用户界面的交互性,使用户更容易理解应用程序中发生的事情。

简单地说,运动动画指的是某些类型的动画是否营造出了移动的感觉,而其他类型的动画则没有。这个准则关注的是那些营造出移动感觉的动画。在讨论动画和可访问性时,在心中保持这种区别是很重要的,允确保你高效地集中精力。

前面提到过,自 2013 年 iOS7 发布之后,屏幕上的一些动效,即屏幕上的某些类型的运动,即使作为界面的一部分,对于对动效敏感的人可能会有身体上的影响。因此,这就是为什么我们可能要考虑在我们的工作中创建减少运动模式的原因。

WCAG 绘出的建议是:

  • 避免不必要的动画:考虑适用于你的 Web 应用或网站的上下文和期望,以及你在设计中使用动画量是否符合该上下文。例如,在视频或游戏网站上可能适合用一些令人惊叹的动画效果,但这些令人惊叹的动画效果用到政府网站上可能就会让用户感到不必要或不合适。
  • 为用户提供关闭任何非必要运动的控件:如果你的 Web 应用或网站上有一些运动可能会对运动敏感人士带来不适,那么你就有必要提供关闭这些运动的控件,比如一个按钮。这样对于运动敏感人士来说是一种负责任的做法。并且根据 WCAG 的定义,任何可能被视为运动动画的效果都应该包含一个减少版本(减少运动)。就拿典型的视差动画效果为例,视差效果对于运动敏感的人普遍存在问题,但它仍然是一种非常流行的技术。虽然要求完全终止所有视差效果并不太现实,但提供一些控件,使用户在一定程度上来控制(比如关闭或减少动画),这是有意义,更是一种负责的做法。
  • 利用减少运动的功能:很多操作系统长期以来都有无障碍设置,用于指定减少运动的偏好。它会导致操作系统不使用应用启动动画等装饰效果。应用本身也可以且应该遵循此设置,并移除所有不必要的动画。我们可以在 CSS 或 JavaScript 中访问它,并使用返回的值为那些希望使用减少运动体验的人提供减少运动体验。

从上述这三条 WCAG 定义的可访问 Web 动画的标准来看,我们在设计减少运动提示时,应该考虑两种类型的运动或动画:

  • 自动启动的运动或动画:指的是自动发生的移动、闪烁、滚动或自动更新动画,也就是前面所说的“暂停、停止和隐藏”与“移动或闪烁的元素”。这类运动或动画包括自动播放的视频、无限循环播放的 GIF 图和自动播放的轮播或幻灯片,它们都是自动发生的,无需用户交互。这类动画在 Web 上很常见
  • 由用户交互引起的运动或动画:指的是由用户交互所产生的运动或动画,比如视差滚动效果

针对不同类型的运动或动画,我们就可以为用户提供不同的方法来选择减少或退出运动以及暂停、关闭动画等。常见的一些方法有:

设计备用内容:可访问的开发始于可访问的设计,因此在设计阶段考虑减少运动的体验至关重要。例如,你正在为客户的网站设计一个视差滚动的效果。你不应该在事后再来思考该效果的可访问性的相关事项,而应该在设计的阶段就解决可访问性的问题:

  • 提供相应的标识,告诉患有前庭障碍的用户,这个效果可能会引起不适,甚至是不舒服
  • 探索减少运动的替代方向。例如采用淡入淡出的效果来替代视差滚动效果,既可以让效果看起来一样的精致,又可以避免让用户感到不适

赋予用户控制全局站点动作设置的权力:使用媒体查询来切换 Web 应用或网站运动是提应用或网站可访问性的好方法。但需要注意的是,一些用户可能不知道如何更新其系统设置。或者,他们可能希望立即选择加入或退出。为了让用户对运动有更多的控制权,一种方法是添加一个全局切换按钮,用于打开或关闭动画。例如,《动物之森》网站。页面的头部包含一个切换按钮,用于启用或禁用动画。当启用动画时,背景通过旋转动画进行更改,前景中的角色会跳入画面。当切换被禁用时,背景会进行更改,但没有旋转效果,角色会淡入。

动物之森:https://animalcrossing.nintendo.com/

如何减少运动?

前面大部分篇幅都在聊可访问 Web 动画的重要性,以及如何通过减少运动来使 Web 动画更具可访问性。主要是因为,我们在处理 Web 动画时,需要考虑到并不是每个人都以相同的方式体验动画。对于一些人来说,某些动画可能感觉流畅而炫酷,但对于其他人来说可能会感到讨厌或分散注意,甚至更糟糕的是可能导致恶心感,甚至引起癫痫发作。拥有大量动画的 Web 应用或网站是很丰富,但动画也可能会消耗设备数据和电池。

其次,作为一个专业的 Web 开发者,在满足需求的同时,也要提高自己的意识,以一种负责任的方式给 Web 添加动画。这样才能避免自己在无意之下伤害了别人!与此同时,Web 开发者也需要掌握更多的技术来创建一个更符合更多用户需求的 Web 动画。

接下来,我们就来讨论这方面的技术。

大家是否发现,本系列很多案例中会有下面这么一段代码:

CSS
@media (prefers-reduced-motion: reduce) {
    *,
    ::before,
    ::after {
        animation-delay: -1ms !important;
        animation-duration: 1ms !important;
        animation-iteration-count: 1 !important;
        background-attachment: initial !important;
        scroll-behavior: auto !important;
        transition-duration: 0s !important;
        transition-delay: 0s !important;
    }
 }

你可能一定会感到好奇,这一段代码有什么作用呢?在解释这段代码之前,我先给大家讲一个我亲身经历的事情。我个人比较喜欢在 Codepen 上写一些案例,有时候案例也会被推荐到首页。有一次我在写一个关于 CSS 混合模式的案例,添加了闪烁和抖动的动画效果

Demo 地址:https://codepen.io/airen/details/ExGwooV

结果有一位网友给我留言:

Please, don't make such a terrible animation. It makes me feel sick. Thank you!

看到这条留言的时候,我为自己的行为感到惭愧和内疚!正因为如此,我给案例以及涉及到动画相关的案例,添加了上面那么代码!用于减少运动,同时尽可能的避免因我写的动画案例给别人带来伤害!我喜欢动画,但我不想因为自己的喜欢而无意中伤害别人!

故事讲完了,我们来讲代码吧!

首先,它是一个 CSS 媒体查询 @media ,prefers-reduced-motion 媒体查询(属于媒体查询 Level 5 规范中的一部分)允许我们检测用户是否在自己系统中开启了减少动运(Reduce Motion) 的偏好设置。现在,很多操作系统都提供了“可访问性”(Accessibility)设置,允许用户在系统级别根据自己的喜好进行设置。例如,你可以在系统级别设置中设置其动画偏好:

如上图所示,当你勾选后,这些偏好设置会导致操作系统不使用应用启动动画等装饰效果。应用本身也可以且应该遵循此设置,并移除所有不必要的动画。

需要注意的是,不同的设备启动减少运动的方式可能会略有差异,下图向大家展示了 iPhone 设备的启动链路:

prefers-reduced-motion 有两个选项 reduceno-preference

  • no-preference:用户未修改系统动画相关特性
  • reduce:这个值意味着用户修改了系统设置,将动画效果最小化,最好所有的不必要的移动都能被移除

如果 prefers-reduced-motion 设置为 reduce ,那么媒体查询就会去查询用户在系统级别的偏好设置,检测是否开启了减少运动设置:

只要启用了该设置并且浏览器支持它,我们就可以使用 prefers-reduced-motion 来配置动画,以符合用户的偏好。例如:

CSS
@media (prefers-reduced-motion: reduce) {
    .result {
        animation-delay: -1ms !important;
        animation-duration: 1ms !important;
        animation-iteration-count: 1 !important;
    }
}

我们来验证一下,假设用勾选了减少运动选项,你将在页面上看不到动画效果:

Demo 地址:https://codepen.io/airen/full/ExGwooV

不过,我们需要知道的是,减少运动并不等于没有运动。有些情况下,删除动画会阻止用户理解其支持的内容。在这些情况下,减缓事物而不是完全删除它们可能更有效。例如,如果通过完全删除组件的动画会减弱其含义,我们可以减缓和简化组件的动画,以至于概念可以在不潜在地触发可访问性问题的情况下进行传达。

我们可以借助 CSS 自定义属性,以一种高效的方式来实现这一点。在以下代码中,我们为动画和过渡动画的持续时间定义了默认属性,然后根据声明它们的上下文进行修改:

CSS
/* 设置默认持续时间 */
:root {
    --animation-duration: 250ms; 
    --transition-duration: 250ms;
}

/* 在特定情境下缩短持续时间 */
@media screen and (prefers-reduced-motion: reduce), (update: slow) {
    :root {
        --animation-duration: 0.001ms !important; 
        --transition-duration: 0.001ms !important;
    }
}

@media screen and (prefers-reduced-motion: reduce), (update: slow) {
    /* 在用户请求减少动画体验时,为所有未知动画移除持续时间 */
    *, *::before, *::after{
        animation-duration: var(--animation-duration);
        animation-iteration-count: 1 !important;
        transition-duration: var(--animation-duration);
    }
}

/* 当动画对理解至关重要且设备支持时,更新持续时间 */
@media screen and (prefers-reduced-motion: reduce), (update: fast) {
    .c-educational-concept {
        /* 设置一个新的针对该组件的动画持续时间 */
        --animation-duration: 6000ms !important;
        animation-name: educational-concept;
        /* 使用局部动画持续时间 */
        animation-duration: var(--animation-duration);
    }
}

正如你所看到的,这是一个非常酷的功能,为我们的用户体验进一步提供了可访问的定制选项。

注意,上面代码示例中还使用了 update 媒体查询,它可以用于检测输出设备在呈现内容后修改外观的频率(如果有的话)。

上面示例只是 prefers-reduced-motion 最通常的用法,其实它除用于关键帧动画或过渡动画之外还有许多应用。比如:

CSS
@media (prefers-reduced-motion: reduce) {
    *,
    ::before,
    ::after {
        scroll-behavior: auto !important;
    }
 }

在此重置了 scroll-behavior 属性的值为 auto 。以此为例,向大家阐述一下 prefers-reduced-motion 应用于非关键帧动画和过渡动画的场景。

通常情况下,我会在 html 元素或滚动容器上显式设置 scroll-behavior 属性的值为 smooth ,这样做的主要目的是为用户提供一个更平滑的滚动体验,例如,当用户点击页面内的锚链接时,页面将平滑滚动到页面上的适当位置:

CSS
:root {
    --scroll-behavior: auto;
}
.item__wrapper {
    height: 100vh;
    scroll-snap-type: y mandatory;
    overflow-y: scroll;
    scroll-behavior: var(--scroll-behavior);
}

Demo 地址:https://codepen.io/airen/full/wvOaWNy

正如你所看到的,当你将 scroll-behaviorauto 切换到 smooth ,并且点击底部缩略图时(这是页面内的锚链接),页面将平滑滚动到页面上的适当位置。你可能还发现了,如果你点击列表中最后一个缩略图,页面滚动得非常快,当然也很丝滑。这样的效果对于正常用户来说,体验肯定是很愉悦的,但对于运动敏感的用户来说,如此丝滑般的滚动反而是一种不愉悦的体验。

当然,原本你的出发点是通过 scroll-behavior 来优化滚动体验,但请不要忽略其他用户的感受。不幸运的是,在 CSS 中目前还没有相关的属性可以对这种行为进行控制。但庆幸的是,我们同样可以通过 prefers-reduced-motion 来控制,可以防止在用户有减少运动偏好的情况下应用该行为:

CSS
:root {
    --scroll-behavior: auto;
}

.item__wrapper {
    height: 100vh;
    scroll-snap-type: y mandatory;
    overflow-y: scroll;
    scroll-behavior: var(--scroll-behavior);
}

@media (prefers-reduced-motion: reduce) {
    :root {
        --scroll-behavior: auto !important;
    }
}

如此一来,即使 scroll-behavior 设置为 smooth ,用户在点击页面内的锚链接时,页面不再会快速滚动:

Demo 地址:https://codepen.io/airen/full/poYJEJY

注意,上面示例我们先将 scroll-behavior 设置为 auto ,当用户点击页面顶部切换按钮之后,才会将 scroll-behavior 属性的值从 auto 切换到 smooth 。不过,如果用户在系统级别设置了减少运动,那么 scroll-behavior 属性的值会再次重置为 auto 。看上去有点绕,对吧!其实这是给了用户更多的控制权,稍后我们还会有相似的案例!

如果页面没有提供其他的控制按钮,那么可以反过来做,先将 scroll-behavior 设置为 auto ,这样一来,用户有没有在系统级别设置减少运动,页面都不会快速滚动。然后再像下面这样重置 scroll-behavior 的值为 smooth

CSS
:root {
    --scroll-behavior: auto;
}

.item__wrapper {
    height: 100vh;
    scroll-snap-type: y mandatory;
    overflow-y: scroll;
    scroll-behavior: var(--scroll-behavior);
}

@media (prefers-reduced-motion: no-preference) {
    :root {
        --scroll-behavior: smooth;
    }
}

你可能已经猜到了,如果用户在系统级别设置了减少运动,上面代码同样不会使页面快速滚动,也是符合你预期的效果!

CSS 媒体查询 prefers-reduced-motion 对于 CSS 的 animationtransition 制作的动效有很好的控制,只要用户在设置中将减少动画选项选中,那么动效就会停止。但 Web 上还有很多动画效果,比如 JavaScript 制作的动画,Canvas,SVG 中的动画,视频和 GIF 图等,那么 prefers-reduced-motion 就不太好控制了。不过我们可以使用媒体查询的 JavaScript API,即 window.matchMedia 在 JavaScript 中对媒体查询进行操作。

JavaScript
function getPrefersReducedMotion() { 
    const QUERY = '(prefers-reduced-motion: no-preference)'; 
    const mediaQueryList = window.matchMedia(QUERY); 
    const prefersReducedMotion = !mediaQueryList.matches; 
    
    return prefersReducedMotion; 
}

正如上图所示,如果用户在设置中没有勾选“减少动态效果”复选框,那么 mediaQueryList.matches 返回 true。记住,我们在代码中检测的是 prefers-reduced-motionno-preference。如果用户勾选“减少动态效果”复选框,那么 no-preference 将为 false。因此,为了确定用户是否勾选“减少动态效果”复选框,我们使用 !mediaQueryList.matches 来反转这个布尔值。

另外,也可以使用事件监听来处理:

JavaScript
const QUERY = '(prefers-reduced-motion: no-preference)'; 
const mediaQueryList = window.matchMedia(QUERY); 
const listener = event => { 
    const getPrefersReducedMotion = getPrefersReducedMotion(); 
}; 

mediaQueryList.addListener(listener); 
mediaQueryList.removeListener(listener); 

当用户在操作系统中切换“减少动态效果”复选框时,该侦听器将触发。我们想要监听这个事件,因为我们想要在用户勾选“减少动态效果”复选框时立即终止动画,即使页面已经加载或动画正在进行中。 如果你希望在 React 中使用的话,可以自定义一个“减少动态效果”相关的钩子函数:

JavaScript
const QUERY = '(prefers-reduced-motion: no-preference)'; 
const getInitialState = () => ( !window.matchMedia(QUERY).matches ); 

function usePrefersReducedMotion() { 
    const [ prefersReducedMotion, setPrefersReducedMotion ] = React.useState(getInitialState); 
    
    React.useEffect(() => { 
        const mediaQueryList = window.matchMedia(QUERY); 
        
        const listener = event => { 
            setPrefersReducedMotion(!event.matches); 
        }; 
        
        mediaQueryList.addListener(listener); return () => { 
            mediaQueryList.removeListener(listener); 
        }; 
    }, []); return prefersReducedMotion; 
} 

通过这种方式,我们可以更好的为用户提供组件级别控件,为用户提供更多的选择。例如,哈佛大学的这个页面以一个自动播放视频为背景,并且在视频右下角提供了一个突出的控件(视频播放按钮),允许用户暂停自动播放的视频。就这个页面上的背景视频而言,要是用户在系统级别设置了减少运动,该视频是不会自动播放,与此同时仍为用户提供了一种选择播放视频的方式(点击视频右下角播放按钮即可):

URL:https://www.harvard.edu/in-focus/the-accessible-world/

正如你所看到的,如果用户没有在系统级别设置减少运动,那么背景视频会自动播放,当用户点击页面右下角的播放按钮之后,视频才会停止播放!反过来,如果用户在系统级别设置了减少运动,那么背景视频并不会自动播放,只有用户点击播放按钮才会播放:

URL:https://www.harvard.edu/in-focus/the-accessible-world/

这样的设计旨在引起用户的注意,效果可能很炫酷,但对于用户而言,在没有经过他们同意的情况下开始播放视频或音频内容。视频及其伴随的音频可能会使用户感到困惑或分心,干扰他们对页面内容的消化,甚至视频或音频的自动播放还会给用户带来惊吓。

我们可以通过 window.matchMedia API 来获取用户在系统级别的设置,如果检测到 prefers-reduced-motionno-preference 的话,表示用户没有开启减少运动,意味着用户并不讨厌视频或音频自动播放(这仅是一种判断,没有具体数据支撑);反之,如果检测到 prefers-reduced-motionreduce 的话,表示用户在系统级别开启了减少运动,意味着该用户不太喜欢应用上有运动,视频亦是如此,在这种情况下,视频和音频不能设置为默认播放。

我们来简单的还原一下哈佛大学这个页面的视频效果:

HTML
<div class="hero">
    <h1>An accessible world is a better world for everyone.</h1>
    <div class="video--wrapper">
        <video playsinline="" muted="" loop="" class="hero__bg-video" aria-label="Background Video">
            <source src="https://www.harvard.edu/wp-content/uploads/2022/01/galaxy2.mp4" type="video/mp4">
        </video>
        <button class="button--video" hidden>
            <svg t="1703755154233" class="icon icon--play" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="12545" width="200" height="200">
                <path d="M785.9 443.3C758.3 421.9 385.2 108 352.6 84.2c-23.9-17.4-119.8-51.4-157.1 46.1-6.9 18.1-4.8 355.6-4.8 355.6s-1.8 392.3 2.3 406.3c27.3 93.8 132.8 69.7 160.8 48.6C376.2 924 747.7 611.7 786 582.5c69.8-63 57-97-0.1-139.2z" fill="currentColor" p-id="12546"></path>
            </svg>
            <svg t="1703755172207" class="icon icon--paused" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="12688" width="200" height="200">
                <path d="M280.5 64c-77.1 0-139.6 62.5-139.6 139.5v616.9c0 77.1 62.5 139.6 139.6 139.6s139.6-62.4 139.6-139.6V203.5c0-77-62.5-139.5-139.6-139.5z m463 0c-77.1 0-139.6 62.5-139.6 139.5v616.9c0 77.1 62.5 139.6 139.6 139.6s139.6-62.4 139.6-139.6V203.5c0-77-62.5-139.5-139.6-139.5z" fill="currentColor" p-id="12689"></path>
            </svg>
        </button>
    </div>
</div>

我们使用 CSS Grid 相关技术,完成案例的布局,具体代码就不在这里展示了,其中关键点是 JavaScript ,具体代码如下:

JavaScript
const buttonHandler = document.querySelector(".button--video");
const video = document.querySelector(".hero__bg-video");
const player = document.querySelector(".icon--play");
const paused = document.querySelector(".icon--paused");

const noMotionPreference = window.matchMedia(
    "(prefers-reduced-motion: no-preference)" // 注意,这里需要带括号,这个很关键
);

const initVideo = () => {
    // 删除默认控件,以便我们可以添加自定义控件
    video.removeAttribute("controls");

    // 显示自定义按钮
    buttonHandler.hidden = false;

    // 设置为自动播放,只有当用户没在系统上设置减少运动
    if (noMotionPreference.matches) {
        video.setAttribute("autoplay", true);
        player.classList.remove("active");
        paused.classList.add("active");
    } else {
        player.classList.add("active");
        paused.classList.remove("active");
    }
};

buttonHandler.addEventListener("click", () => {
    // 切换视频播放
    if (video.paused) {
        video.play();
        player.classList.remove("active");
        paused.classList.add("active");
    } else {
        video.pause();
        player.classList.add("active");
        paused.classList.remove("active");
    }
});

initVideo();

Demo 地址:https://codepen.io/airen/full/bGZdBpb

该建议同样也适用于 AVIF、WebP 或 GIF 等格式的图片内容。有趣的是,使用 <picture> 元素,依赖媒体查询 media 属性,也可以根据用户偏好来加载不同的媒体(图片或视频)来源。如果 (prefers-reduced-motion: no-preference) 的值结果为 true,则可以放心地显示动画版本,否则显示静态版本:

HTML
<picture>
    <!-- 动画版本 -->
    <source srcset="nyancat.avifs" type="image/avif" media="(prefers-reduced-motion: no-preference)" />
    <source srcset="nyancat.gif" type="image/gif" media="(prefers-reduced-motion: no-preference)" />
    <!-- 静态版本 -->
    <img src="nyancat.png" alt="Nyan cat" width="250" height="250" />
</picture>

Demo 地址:https://codepen.io/airen/full/abMOJZd

这很酷,因为这意味着对于喜欢减少运动的用户,更大的GIF文件甚至都不会被下载。不足之处在于,在个别系统中,一旦文件被下载,用户就无法切换回无动作的替代版本。你也可以使用 @KrasimirGifffer 库来管理,它将默认的 GIF 替换为静态图像和播放按钮。当然,你也可以不使用任何库,像处理视频一样,通过一些 JavaScript 脚本来实现类似 Gifffer 库相似的效果:

Demo 地址:https://codepen.io/airen/full/gOEpmLv

注意,这种方案在 Chrome 中有一个明显的缺陷,在动画和无动画选项之间切换时,似乎每次都会重新下载动画,比如上面示例中的 AVIF 图,而在其他浏览器中并非如此。

尽管 CSS 媒体查询 prefers-reduced-motion 很有用,但它有一个缺点,只服务于在系统中设置减少运动的用户。很多用户对这个设置可能不太了解,而另一些用户可能正在使用借来的计算机,无法访问系统级别的设置。还有一些用户可能对大多数 Web 应用或网站上的动画感到满意,但发现那些使用大量动画的应用或网站难以忍受。

如果仅是为了访问某一个应用或网站而不得不调整系统偏好设置,这可能会很烦人。出于这些原因,或者说为了能给用户提供更多的选择权和控制权,我们应该在自己的 Web 应用或网站上为用户提供可选择的控件。例如前面展示的《动物之森》网站,它就在页头底下为用户提供减少运动的切换控件:

动物之森:https://animalcrossing.nintendo.com/

这跟上面的视频和动画的设计思路是类似的。我们可以通过 JavaScript 来实现这一点。

CSS
@layer motion {
    @media (prefers-reduced-motion: no-preference) {
        body {
            --playState: running;
        }
    }
}

@layer animation {
    @keyframes lights {
        0%,30%,100% {
            opacity: 0;
        }
        40%,90% {
            opacity: 1;
        }
    }

    .lit {
        animation: 2s linear infinite lights var(--playState, paused);

        &.yellow {
            animation-delay: 0.5s;
        }

        &.blue {
            animation-delay: 1s;
        }

        &.red {
            animation-delay: 1.5s;
        }
    }
}
JavaScript
const toggle = document.querySelector("[data-toggle]");
const buttonText = document.querySelector("[data-btn-text]");
const prefersReducedMotion = window.matchMedia("(prefers-reduced-motion: reduce)");
const bodyEle = document.body;

const setReducedMotionStyles = () => {
    buttonText.textContent = ": Off";
    toggle.setAttribute("aria-checked", "false");
    bodyEle.classList.remove("allow-motion");
    bodyEle.style.setProperty("--playState", "paused");
};

const setMotionStyles = () => {
    buttonText.textContent = ": On";
    toggle.setAttribute("aria-checked", "true");
    bodyEle.classList.add("allow-motion");
    bodyEle.style.setProperty("--playState", "running");
};

const getMotionPreference = () => {
    const localStoragePreference = localStorage.getItem("prefersReducedMotion");

    if (localStoragePreference) {
        return localStoragePreference;
    } else {
        return prefersReducedMotion.matches ? "reduce" : "no-preference";
    }
};

const setInitialStyles = () => {
    if (getMotionPreference() == "reduce") {
        setReducedMotionStyles();
    } else {
        setMotionStyles();
    }

    toggle.hidden = false;
};

setInitialStyles();

toggle.addEventListener("click", () => {
    if (getMotionPreference() == "reduce") {
        localStorage.setItem("prefersReducedMotion", "no-preference");
        setMotionStyles();
    } else {
        localStorage.setItem("prefersReducedMotion", "reduce");
        setReducedMotionStyles();
    }
});

Demo 地址:https://codepen.io/airen/full/xxBGpzg

示例中彩灯在不断的闪烁。初始的动画样式是由用户的系统偏好设置(使用 prefers-reduced-motion)确定的,然而用户可以通过按钮切换动画的开关。这会向 body 添加一个 .allow-motion 类,我们可以使用该类来设置根据所选偏好设置的样式。

示例中,我们使用了CSS 自定义属性 --playState ,用户点击“动画切换”按钮时,将会切换 --playState 属性的值(pausedrunning 之间切换),我们使用它来控制彩灯动画的播放或暂停。首先,我们将播放状态设置为暂停(--playState 的值为 paused):

CSS
.lit {
    animation: 2s linear infinite lights var(--playState, paused);
}

如果用户在系统设置中设置了对减少运动的偏好,我们可以将播放状态设置为运行:

CSS
@media (prefers-reduced-motion: no-preference) {
    body {
        --playState: running;
    }
}

当用户点击切换时,自定义属性在 body 上更新。

通过前面的学习,我们可以获知:

  • 并非每台可以访问网络的设备都能渲染动画,或者平滑地渲染动画
  • 减少运动并不等于没有运动
  • 动画并不等同于运动(Animation ≠ Motion )
  • 并非所有 Web 应用或网站都会使用 prefers-reduced-motion 来减少运动,或者可能不足以满足你的需求

但作为一名出色的 Web 开发者,我们在创建动画时,需要为更多的用户考虑,创建出更具可访问的 Web 动画。或者说,要有一种意识,为 Web 应用或网站提供减少动画的机制。这也就是为什么在示例中会有下面这段代码:

CSS
@media (prefers-reduced-motion: reduce), (update: slow) {
    *,
    ::before,
    ::after {
        animation-delay: -1ms !important;
        animation-duration: 1ms !important;
        animation-iteration-count: 1 !important;
        background-attachment: initial !important;
        scroll-behavior: auto !important;
        transition-duration: 1ms !important;
        transition-delay: 1ms !important;
    }
}

其工作原理是,上述 CSS 替换了所有动画和过渡效果的时长,使其都过短,以至于它们都不再引起注意。

何时减少运动?

这里所说的“何时减少运动”并不是说什么时候在系统级别开启“减少运动”偏好设置,而是指 Web 开发者在创建动画时,需要使用 prefers-reduced-motion 媒体查询。原则上说,你创建的动画成为前庭障碍触发器,那就得考虑在 prefers-reduced-motion 媒体特性匹配时禁用或使用变体。

为了更好的帮助 Web 开发者应该在何时启用 prefers-reduced-motion 媒体查询来禁用或提供简化版本动画,接下来我会以一些实际案例来阐述。

缩放和变焦

在《CSS 变换的世界:创建流畅的 Web 动画》课程中,花了不少的篇幅向大家阐述了,缩放和变焦是制作一个流畅的 Web 动画的必要特性。但我们也需要知道,视觉缩放或变焦动画会使用户产生在物理空间中前后移动的幻觉。一些带有模糊效果的动画也会产生类似的幻觉。例如下面这示例,当用户的鼠标悬浮在视频播放按钮上时,海报(缩累略图)会有缓慢缩放的动画效果:

为了避免因缩略图的缩放动画触发前庭障碍,你可以使用 prefers-reduced-motion: reduce 禁用缩略图的缩放效果,你可以考虑使用瞬间动画效果替代:

再来看一个 3D 缩放加模糊的动画效果,该效果给用户一种物理位置和焦点在改变的感觉:

为了避免该动画效果触发触发前庭障碍,苹果团队的工程师在 prefers-reduced-motion: reduce 下将该动画效果简化为一个简单的滚动效果。

macOS 网站上多处都采用相似的方案。

你可以已经发现了,当你将 prefers-reduced-motion 的值从 no-preference 切换到 reduce 时,带有 3D 缩放的效果图片会变成一张静态图。

旋转和旋涡效应

CodePen 上有很多类似的使用螺旋或旋转的动画效果,这些动画效果配上色彩或其他图形形状,使整个动画效果更炫酷:

Demo 地址:https://codepen.io/tmrDevelops/full/RWGNrv

这些螺旋或旋转的动画效果看上去是非常炫酷,但它们对于患有前庭障碍的人士来说,是极其不友善的,因为这些动画效果可能会导致一些患有前庭障碍的人失去平衡或垂直方向的方向感。即使是没有患有前庭障碍的用户,看久了这些动画效果都会感到头晕,眼花。

我们来看一个更具体的案例。

Viljami Salminen 网站的首页使用 Canvas 技术绘制了一个旋转的视差星场效果,但为了不给有前庭障碍的用户带来不适,该团队使用 prefers-reduced-motion ,用户只要开启了减少运动偏好,将看不到旋转的视差星动效,看到的将是静止的星点:

类似这种场景在 Web 上还是很常见的,例如圣诞节主题方面的应用,为了增加节日的气氛,会在页面上增加雪花飘落的动画,甚至为了使雪花飘落的效果更逼真,还会添加一些类似旋转、漩涡等效果。如果你正在创作一个这样的动画,那请为患有前庭障碍的用户做一考虑。

多速度或多方向运动

前面多次提到过视差滚动效果容易触发前庭障碍:

除此之外,其他多速度或多方向运动的动画也可能触发前庭障碍:

以早期 iOS 10 网站为例,当初该网站以不同速度垂直移动图像为特色,我们可以与 prefers-reduced-motion 一起使用,为患有前庭障碍的用户提供极简版本,即滚动的时候没有图片偏移效果。简单地说,简化了滚动视差的效果,只有简单的滚动效果:

上面所展示的仅是一些常见的情境,只是为了帮助大家更好理解应该在何时运用prefers-reduced-motion

如何创建可访问 Web 动画

考虑到 WCAG 设定的标准和动画与运动之间的区别,我们可以将动画分为三大类型:不符合 WCAG 标准的动画、可以移除的非必要的动画可以调整的必要动画

不符合 WCAG 标准的动画

首先来看第一种类型,即不符合 WCAG 标准的动画。

在 Web 上很多动画并不属于任何类型运动,对于这些动画,我们无需进行任何调整,因为它们对具有前庭障碍或减少运动偏好的用户没有触发效应。例如:

  • 瞬间出现和消失而无需过渡的对象
  • 过渡颜色或不透明度的元素,最常见的就是对象状态变化

就拿 Web 上的按钮为例。通常情况之下,Web 设计师会为按钮不同状态提供不同的视觉效果,例如在鼠标悬浮在按钮上时改变按钮背景颜色:

只要我们在悬停效果上没有应用某种激进的改变,而且颜色具有足够对比度,使按钮易读,我们则可以认为它是安全的,不受无障碍准则的影响,即是符合 WCAG 标准的动画(如上图所示)。

反过来,如果你的按钮在悬浮效果上有一些激进的改变,例如像下图这个呼吸灯的动画效果,那你就得注意了,它会给部分有障碍的人士带来不适。该效果是不符合 WCAG 标准的,对像的运动看起来是在不断的闪烁:

对于一个不符合 WCAG 标准的动画,你就需要做一定的考量和评估,最好为有障碍的人士提供一种适合的动画效果。

可以移除的非必要动画

Web 应用或网站上还有一些运动对于界面来说并不重要,例如,与那些添加上下文或帮助用户导航的动画相比,它就显得不那么重要了。换句话说,所谓的不重要的动画是那些对理解内容或界面状态并非至关重要,而且这些动画可能会使一些人士感到不适或烦恼。

比如:

  • 占据屏幕三分之一以上或在屏幕上移动的动画对象
  • 具有自动播放或自动更新的元素
  • 视差效果、多方向运动或沿着 z 轴移动的元素,如 3D 透视
  • 具有闪烁或循环动画的内容
  • 具有漩涡、缩放、变焦或模糊效果的元素
  • 动画插图,如变形的 SVG 形状

这些是我们决定在用户开启减少运动偏好时可以完全移除的动画,因为它们不影响内容的呈现,而选择提供更具可文访问性和舒适性的体验。例如下图这个 SVG 插图动画,它就是属性非必要的动画:

我们一起来看几个更具体的案例。

Material 设计系统中,有很多类似于下图这种占据屏幕三分之一以上或在屏幕上移动对象的动画效果:

针对这类动画,我们可以为开启减少运动的用户提供一个额外的效果,比如最小化不必要的移动,使用平滑过渡替代瞬间过渡等。通过这种方式,我们可以动画既向用户传达了关键信息,而且还不会造成任何不适,同时在两种情况下,都可提供引人入胜的体验:

上图左侧呈现的是原始动画效果,右侧呈现的是减少运动的动画效果,服务于开启了减少运动偏好的用户

大家再回忆一下前面提到的《动物森林》的网站上首页的动画效果亦是如此。默认情况之下,动画占据了屏幕三分之一以上,并且在屏幕上移动对象较多,动画效果复杂且炫酷:

同样为了使动画既可以向用户传达了关键信息,又不会造成任何不适。Web 开发者为减少运动偏好的人士提供更简单的动画效果:

正如你所看到的,没有那些复杂的旋转效果,只有简单的淡入淡出效果。

除了上面所展示的两个示例之外,像自动播放、自动更新和无限循环的元素都可以被视为可移除的动画。例如,视频,自动播放的轮播图和幻灯片等。类似这些运动,我们应该给予用户绝对的控制权来决定何时发生过渡,比如在轮播图,更合适的方式不应该是自动播放,把播放权留给我们的用户。

此外,与前面示例相似,我们还可以为开启减少运动偏好的用户提供减化版的动画效果。例如,使用淡入淡出替代水平滑动动画效果,这样就不会增加额外的运动,进一步防止触发前庭障碍的可能性。

上图中轮播图效果,只有用户触发才会滚动,并且左侧滚动切换是一个平滑的动画效果,右侧是一个淡入淡出的瞬间过渡,右侧的效果主要用于开启减少运动的用户。

同样的思路下,我们可以将视差滚动和涉及缩放、变焦、模糊和漩涡效应的任何多方向运动用瞬间过渡动画来替代。如下图这个效果:

除此之外,就是插图动画。我们可以直接为开启减少运动偏好用户提供一个静态版本。这样,图像仍然提供了上下文,使用户能够理解内容,而无需额外的运动。

可以调整的必要动画

Web 应用或网站的动画内容是很有必要的,例如那些对于使用和理解用户界面的动画。这类动画要是直接移动,可能对于 Web 应用或网站的功能会起到一定的影响。这个时候就会出现我们前面所说的问题,鱼和熊掌能否兼容。

  • 对于 Web 应用或网站而言,这类动画起着重要的作用,它能更好的向用户传达相应的功能,也能帮助用户更好的理解用户界面
  • 对于部分用户而言,比如具有前庭障碍的用户,这类动画很有可能会引起他们的不适,甚至更为严重的问题,例如触发癫痫发作,这将是很恐怖的事情

因此而言,这类动画对于 Web 开发者而言是最具挑战性的,弃之可惜,食之无味。因为必须在必要的动画和保持可访问体验之间取得微妙的平衡。

这就是为什么在前面一直强调,为开启减少运动偏好的用户提供一个替代版或极简动画的原因。在许多情况下,这仅仅是调整或减少动画,以便用户始终能够理解界面的功能(理解屏幕上发生的事情),同时也不至于引起不适。

经过相当长的时间以及经验,你会发现要达到这样的预期,最简单或者说最佳的方法就是调整动画,使其更为微妙。例如,调整动画的持续时间,使其播放时间更长、更慢,是应用这一挑战的一种方式。因为以较慢的速度播放动画,对于普通人来说,它可能会是一种很好的体验,这一点我们在介绍动画持续时间和延迟时间以及动画设计原则就有阐述过,但我们必须要记得,你的用户可能有一群患有前庭障碍,对于这些人士而言,他们在一定程度上是可以接受较慢速度播放的动画,这些慢播放的动画也可能不会引起他们的不适以及触发疾病。

就此而言,作为一名专业的 Web 开发人员和设计师,我们应该始终有这样的意识和敬畏之心,为所有用户提供平等的机会和同样的用户体验。哪怕你无法做到最好,但也需要知道,不能因为自己的无意而伤害了别人。

我们以 Web 最为常见的动画案例为例,即加载指示器:

像上图中这种加载指示器动画(也就我们常说的 Loading 动画)随处可见,甚至还有比别上更为炫酷的加载指示器动画:

试问,在 Web 应用或网站上,加载指示器动画是绝对必要的吗?毫无疑问,它很有必要,尤其是在一些既定情境中,例如页面加载,文件上传等场景,加载指示器动画效果直接向用户传达了页面是否加载完,文件是否上传完。简单地说,它向用户提供了界面活动的反馈。如果它在界面未更新(例如,页面还没加载完,文件还没上传完)的情况下停止,用户可能会理解成页面加载或文件上传失败或卡住了。

与其完全删除动画,我们还不如针对自己创建的加载指示器动画做一些分析,确定动画可能引起问题的方面,主要是针对有障碍人士会引起不适的方面,例如:

我们可以根据 WCAG 对运动提供的标准来进行分析,比如上面这个加载器指示动画,我们可以尝试着问自己一些问题:

  • 动画元素旋转速度是否过快?
  • 动画元素是否不断地改变大小?
  • 动画元素是否在一个无限循环中运行,直到消失?
  • 动画元素是否在不断移动和闪烁?
  • 等等...

这样一来,我们就可以找到一些为开启减少运动偏好的用户提供另一个版本的动画,对于 Web 开发者而言,也就找到了修改动画的方案:

  • 减缓动画元素旋转速度
  • 消除动画元素的缩放效果
  • 将最大持续时间设定为五秒
  • 等等...

如下图所示,左侧是最原始的加载指示器动画效果,服务于应用的普通用户,右侧是经过调整的加载指示器动画,该动画只有用户在系统级别开启了减少运动偏好才能看到:

对于 Web 应用或网站上的重要且必要的动画,我们都可以按这种方式来制作。但唯一的缺陷是开发成本上来了,Web 开发需要具备更多的制作动画的技巧和相关理论知识,除了要知道如何创建动画之外,还需要知道什么情况之下会引起用户不适。但这一切都是值得的,因为你的努力不会再伤害到别人。

综合来说,Web 动画是能给 Web 应用带来诸多的好处,但作为一名 Web 开发者,你在创造动画时,除了满足动画的创意、功能等需求之外,也需要同时考虑到减少运动的用户偏好。

小结

前面一直以来,我们都在强调 Web 动画可以提高 Web 应用或网站的可用性和参与度,还能丰富 Web 和吸引用户等,但在这节课我们又在不断地强调 Web 动画又会给患有前庭障碍用户带来伤害。但这两者并不矛盾,因为 Web 属于用户,而不是开发者。始终调整你创建的动画以满足用户的需求。