尊重用戶的運動偏好

已發表: 2022-03-10
快速總結 ↬ 近幾年來,prefers prefers-reduced-motion媒體查詢在所有現代瀏覽器中都有出色的支持。 在本文中,Michelle Barker 解釋了為什麼現在沒有理由不使用它來使您的網站更易於訪問。

在網絡上使用動畫時,重要的是要考慮到並非每個人都以相同的方式體驗它。 對某些人來說可能感覺光滑和光滑的東西可能會令人討厭或分散其他人的注意力 - 或者更糟糕的是,會引起生病的感覺,甚至導致癲癇發作。 具有大量運動的網站也可能對移動設備的電池壽命產生更大的影響,或者導致使用更多的數據(例如,自動播放視頻將需要比靜態圖像更多的用戶數據)。 這些只是運動繁重的網站可能不適合所有人的一些原因。

大多數新操作系統允許用戶在其係統級設置中設置他們的運動偏好。 prefers-reduced-motion媒體查詢(Level 5 Media Queries 規範的一部分)允許我們檢測用戶的系統級運動偏好,並應用尊重這一點的 CSS 樣式。

prefers-reduced-motion的兩個選項是reduceno-preference 。 如果用戶明確設置了減少運動的偏好,我們可以在我們的 CSS 中以下列方式使用它來關閉元素的動畫:

 .some-element { animation: bounce 1200ms; } @media (prefers-reduced-motion: reduce) { .some-element { animation: none; } }

相反,只有當用戶沒有運動偏好時,我們才能設置動畫。 這樣做的好處是減少了我們需要編寫的代碼量,並且意味著我們不太可能忘記滿足用戶的運動偏好:

 @media (prefers-reduced-motion: no-preference) { .some-element { animation: bounce 1200ms; } }

另一個優點是不支持prefers-reduced-motion舊瀏覽器將忽略該規則,只顯示我們原始的、無運動元素。

哪個規則?

不像min-widthmax-width媒體查詢,或多或少建立的共識是移動優先(因此支持min-width ),沒有單一的“正確”方法來編寫您的縮減運動樣式。 由於上面列出的原因,我傾向於支持第二個示例(僅當prefers-reduced-motion: no-preference評估為 true 時才應用動畫)。 Tatiana Mac 撰寫了這篇出色的文章,其中涵蓋了開發人員可能會考慮採用的一些方法,以及許多其他要點,包括在 web 上進行動態設計時要問的關鍵問題。

與往常一樣,團隊溝通一致的策略是確保在 Web 可訪問性方面涵蓋所有基礎的關鍵。

跳躍後更多! 繼續往下看↓

實際使用:將prefers-reduced-motion應用於滾動行為

除了應用(或不應用)關鍵幀動畫或過渡之外, prefers-reduced-motion還有很多應用。 一個例子是平滑滾動。 如果我們在html元素上設置scroll-behaviour: smooth ,當用戶點擊頁內錨鏈接時,他們將平滑滾動到頁面上的適當位置(目前 Safari 不支持):

 html { scroll-behavior: smooth; }

不幸的是,在 CSS 中,我們現在對這種行為沒有太多控制。 如果我們的內容頁面很長,頁面滾動速度非常快,這對於具有運動敏感性的人來說可能是一種非常不愉快的體驗。 通過將其包裝在媒體查詢中,我們可以防止在用戶具有reduced-motion偏好的情況下應用該行為:

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

在 Javascript 中滿足運動偏好

有時我們需要在 JavaScript 而不是 CSS 中應用動畫。 我們可以類似地使用 JS 檢測用戶的運動偏好,使用matchMedia 。 讓我們看看如何在 JS 代碼中有條件地實現平滑滾動行為:

 /* Set the media query */ const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)') button.addEventListener('click', () => { /* If the media query matches, set scroll behavior variable to 'auto', otherwise set it to 'smooth' */ const behavior = prefersReducedMotion.matches ? 'auto' : 'smooth' /* When the button is clicked, the user will be scrolled to the top */ window.scrollTo({ x: 0, y: 0, behavior }) })

相同的原理可用於檢測是否使用 JS 庫實現運動豐富的 UI,甚至是否自己加載庫。

在以下代碼片段中,如果用戶更喜歡減少運動,則函數會提前返回,從而避免不必要地導入大型依賴項——為用戶帶來性能提升。 如果它們沒有設置運動偏好,那麼我們可以動態導入 Greensock 動畫庫並初始化我們的動畫。

 const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)') const loadGSAPAndInitAnimations = () => { /* If user prefers reduced motion, do nothing */ if (prefersReducedMotion.matches) return /* Otherwise, import the GSAP module and initialize animations */ import('gsap').then((object) => { const gsap = object.default /* Initialize animations with GSAP here */ }) } loadGSAPAndInitAnimations()

reduced-motion並不意味著沒有運動

在為減少運動偏好設置樣式時,重要的是我們仍然為用戶提供有意義且可訪問的指示何時發生動作。 例如,當為喜歡減少運動的用戶關閉分散注意力或運動密集的懸停狀態時,我們必須注意為用戶懸停在元素上時提供清晰的替代樣式。

以下演示顯示了當用戶懸停或專注於畫廊項目(如果他們沒有設置運動首選項)時的精細轉換。 如果他們更喜歡減少運動,則過渡會更加微妙,但仍能清楚地指示懸停狀態:

請參閱 Michelle Barker 的鋼筆 [Pears-reduced-motion 畫廊](https://codepen.io/smashingmag/pen/KKvMqaL)。

請參閱 Michelle Barker 的 pen Gallery with prefers-reduced-motion。

減少運動也不一定意味著從我們的網頁中刪除所有變換。 例如,一個帶有小箭頭圖標的按鈕在懸停時會移動幾個像素,對於喜歡減少運動體驗的人來說不太可能導致問題,並且提供比單獨顏色更有用的狀態變化指示。

我有時會看到開發人員通過以下方式應用縮減運動樣式,這消除了所有元素上的所有過渡和動畫:

 @media screen and (prefers-reduced-motion: reduce) { * { animation: none !important; transition: none !important; scroll-behavior: auto !important; } }

這可以說比忽略用戶的運動偏好更好,但不允許我們輕鬆地定制元素以在必要時提供更微妙的過渡。

在下面的代碼片段中,我們有一個在懸停時按比例增長的按鈕。 我們正在轉換顏色和比例,但喜歡減少運動的用戶根本不會得到任何轉換:

 button { background-color: hotpink; transition: color 300ms, background-color 300ms, transform 500ms cubic-bezier(.44, .23, .47, 1.27); } button:hover, button:focus { background-color: darkviolet; color: white; transform: scale(1.2); } @media screen and (prefers-reduced-motion: reduce) { * { animation: none !important; transition: none !important; scroll-behavior: auto !important; } button { /* Even though we would still like to transition the colors of our button, the following rule will have no effect */ transition: color 200ms, background-color 200ms; } button:hover, button:focus { /* Preventing the button scaling on hover */ transform: scale(1); } }

查看此演示以查看效果。 這可能並不理想,因為沒有過渡的突然顏色切換可能比幾百毫秒的過渡更令人不安。 這就是為什麼總的來說,我通常更喜歡根據具體情況設計減少運動的樣式

如果您有興趣,這與重構的演示相同,以允許在必要時自定義轉換。 它為過渡持續時間使用自定義屬性,這使我們可以打開和關閉縮放過渡,而無需重寫整個聲明。

何時刪除動畫更好

Eric Bailey 在他的文章“Revisiting prefers-reduced-motion,減少運動的媒體查詢”中提出了“並非每個可以訪問網絡的設備都可以渲染動畫,或者流暢地渲染動畫”的觀點。 對於刷新率低的設備,可能會導致動畫卡頓,實際上最好刪除動畫update媒體功能可用於確定:

 @media screen and (prefers-reduced-motion: reduce), (update: slow) { * { animation-duration: 0.001ms !important; animation-iteration-count: 1 !important; transition-duration: 0.001ms !important; } }

請務必閱讀 Eric 建議的完整文章,因為他是可訪問性領域的一流人物。

所有部分的總和

當如此緊密地關注組件級 CSS 時,牢記整體頁面設計非常重要。 在組件級別看似無害的動畫在整個頁面中重複時可能會產生更大的影響,並且是許多移動部分之一。

在 Tatiana 的文章中,她建議在單個 CSS 文件中組織動畫(使用prefers-reduced-motion ),只有在(prefers-reduced-motion: no-preference)評估為 true 時才能加載該文件。 查看我們所有動畫的總和可以幫助我們將訪問整個站點的體驗可視化,並相應地調整我們的減動畫樣式。

顯式運動切換

雖然prefers-reduced-motion很有用,但它確實有一個缺點,即只迎合那些在其係統設置中了解該功能的用戶。 許多用戶不了解此設置,而其他用戶可能正在使用借來的計算機,而無法訪問系統級設置。 儘管如此,其他人可能對絕大多數網站的運動感到滿意,但發現大量使用運動的網站難以忍受。

僅僅為了訪問一個站點就必須調整系統偏好可能很煩人。 由於這些原因,在某些情況下,最好在站點本身上提供一個顯式控件來切換運動 on 和 off 。 我們可以用 JS 來實現。

下面的演示有幾個圓圈在背景中漂移。 初始動畫樣式由用戶的系統偏好決定(使用prefers-reduced-motion ),但是,用戶可以通過按鈕打開或關閉運動。 這為body添加了一個類,我們可以使用它來根據所選偏好設置樣式。 作為獎勵,動作偏好的選擇也保存在本地存儲中——所以當用戶下次訪問時它會被“記住”。

請參閱 Michelle Barker 的 Pen [Reduced-motion toggle](https://codepen.io/smashingmag/pen/porEQLB)。

請參閱 Michelle Barker 的 Pen Reduced-motion 切換。

自定義屬性

演示中的一個功能是切換設置了一個自定義屬性--playState ,我們可以使用它來播放或暫停動畫。 如果您需要一次暫停或播放多個動畫,這可能特別方便。 首先,我們將播放狀態設置為paused

 .circle { animation-play-state: var(--playState, paused); }

如果用戶在他們的系統設置中設置了減少運動的偏好,我們可以將播放狀態設置為running

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

注意:body上設置這個,而不是在單個元素上,意味著可以繼承自定義屬性。

當用戶單擊切換時,自定義屬性會在body上更新,這將切換使用它的任何實例:

 // This will pause all animations that use the `--playState` custom property document.body.style.setProperty('--playState', 'paused')

在所有情況下,這可能不是理想的解決方案,但一個優點是當用戶單擊切換時動畫只是暫停,而不是跳回其初始狀態,這可能會很刺耳。

特別感謝 Scott O'Hara 就改進切換的可訪問性提出的建議。 他讓我知道,一些屏幕閱讀器不會宣布更新的按鈕文本,當用戶單擊按鈕時會更改,而是建議在按鈕上使用role="switch" ,並在單擊時將aria-checked切換為onoff

視頻分量

在某些情況下,在組件級別切換運動可能是更好的選擇。 獲取具有自動播放視頻背景的網頁。 我們應該確保視頻不會為喜歡減少運動的用戶自動播放,但我們仍然應該為他們提供一種他們選擇時播放視頻的方式。 (有些人可能會爭辯說我們應該避免完全停止自動播放視頻,但我們並不總能贏得這場戰鬥!)同樣,如果視頻被設置為為沒有明確偏好的用戶自動播放,我們還應該為他們提供一種方法暫停視頻。

這個演示展示了我們如何在用戶沒有明確的運動偏好時設置自動播放屬性,實現自定義播放/暫停按鈕以允許他們也切換播放,無論偏好如何:

請參閱 Michelle Barker 的 Pen [帶有運動偏好的視頻](https://codepen.io/smashingmag/pen/qBXNjqR)。

請參閱 Michelle Barker 的具有運動偏好的 Pen Video。

(我隨後看到了 Scott O'Hara 的這篇文章,詳細介紹了這個確切的用例。)

使用<picture>元素

Chris Coyier 寫了一篇有趣的文章,結合了幾種技術來根據用戶的運動偏好加載不同的媒體源。 這很酷,因為這意味著對於喜歡減少運動的用戶來說,甚至不會下載更大的 GIF 文件。 據我所知,不利的一面是,一旦下載了文件,用戶就無法切換回無運動替代方案。

我創建了添加此選項的演示的修改版本。 (在您的系統偏好設置中打開reduced-motion以查看它的實際效果。)不幸的是,在 Chrome 中的動畫和無運動選項之間切換時,似乎每次都重新下載 GIF 文件,而在其它瀏覽器:

見筆【更喜歡還原運動技術 PLUS! [分叉]](https://codepen.io/smashingmag/pen/porbPXG) 米歇爾·巴克。

請參閱 Pen Preferred Reduction Motion Technique PLUS! [分叉] 米歇爾·巴克。

儘管如此,這種技術似乎是一種更尊重的顯示 GIF 的方式,這可能會讓用戶感到沮喪。

瀏覽器支持和最終想法

幾年前, prefers-reduced-motion在所有現代瀏覽器中都有出色的支持。 正如我們所看到的,通過採用減少運動優先的方法,不支持的瀏覽器將簡單地獲得reduced-motion後備。 今天沒有理由不使用它來使您的網站更易於訪問。

自定義切換絕對有一席之地,並且可以極大地改善不了解此設置或其作用的用戶的體驗。 用戶的缺點是不一致 - 如果每個開發人員都被迫提出自己的解決方案,用戶需要在每個網站的不同位置尋找動作切換。

感覺這裡缺少的層是browsers 。 我很想看到瀏覽器實現reduced-motion切換,用戶可以輕鬆訪問的地方,這樣人們就知道在哪裡可以找到它,而不管他們正在瀏覽的網站是什麼。 它也可能會鼓勵開發人員花更多時間確保運動可訪問性。

相關資源

  • 5 級媒體查詢規範,萬維網聯盟 (W3C)
  • prefers-reduced-motion ,MDN Web Docs,Mozilla
  • 減少運動靈敏度的設計,Val Head,Smashing Magazine
  • 採用無運動優先的動畫方法,Tatiana Mac
  • 縮減動畫技術,Take 2,Chris Coyier,CSS-Tricks
  • 重溫prefers-reduced-motion , The Reduced Motion Media Query, Eric Bailey, CSS-Tricks
  • 減少運動以提高可訪問性,Lindsey Kopacz