prefers-reduced-motion 媒體查詢會偵測使用者是否要求作業系統盡量減少動畫或動態效果。
並非所有人都喜歡裝飾性動畫或轉場效果,有些使用者遇到視差捲動、縮放效果等時,甚至會感到暈眩。使用者偏好媒體查詢 prefers-reduced-motion 可讓您為表示這項偏好的使用者,設計動作減少的網站變體。
現實生活和網頁上的動作過多
前幾天,我帶孩子去溜冰。當天陽光普照,天氣晴朗,溜冰場擠滿了人 ⛸。但問題是,我不太能應付人潮。目標太多,我無法專注於任何事情,最後感到迷失,而且視覺資訊過載,幾乎就像盯著蟻丘 🐜 一樣。
有時網路上也會發生這種情況:閃爍的廣告、花俏的視差效果、令人驚豔的揭露動畫、自動播放的影片等,有時會讓人感到相當煩躁…
幸好,與現實生活不同的是,網路上有解決方案。開發人員可以透過 CSS 媒體查詢 prefers-reduced-motion 為偏好減少動態效果的使用者建立網頁變體。這包括避免自動播放影片、停用純裝飾效果,以及為特定使用者徹底重新設計網頁。
在深入探討這項功能之前,讓我們先回顧一下網頁動畫的用途。如有需要,您也可以略過背景資訊,直接查看技術詳細資料。
網頁上的動畫
動畫通常用於向使用者提供意見回饋,例如通知使用者系統已收到並正在處理某項動作。舉例來說,在購物網站上,產品可能會以動畫形式「飛入」虛擬購物車,並顯示在網站右上角的圖示中。
另一個用途是運用動態效果影響使用者觀感,方法是混合使用骨架畫面、情境中繼資料和低品質圖片預覽,藉此佔用使用者大量時間,讓整體體驗感覺更快。這個概念是為使用者提供即將發生的事件的脈絡,同時盡快載入內容。
最後,還有裝飾效果,例如動畫漸層、視差捲動、背景影片等。雖然許多使用者喜歡這類動畫,但部分使用者不喜歡,因為他們覺得動畫會干擾或拖慢速度。在最糟的情況下,使用者甚至可能像現實生活一樣暈車,因此對這些使用者來說,減少動畫是醫療上的必要措施。
運動觸發的前庭光譜障礙
部分使用者會因動畫內容而感到分心或噁心。舉例來說,如果與捲動相關聯的主要元素以外的元素大幅移動,捲動動畫可能會導致前庭功能障礙。舉例來說,視差捲動動畫可能會導致前庭功能障礙,因為背景元素移動的速度與前景元素不同。前庭 (內耳) 疾病的反應包括頭暈、噁心和偏頭痛,有時需要臥床休息才能恢復。
在作業系統上移除動態效果
許多作業系統長期以來都提供無障礙設定,可指定偏好減少動作。以下螢幕截圖顯示 macOS Mojave 的「減少動作」偏好設定,以及 Android Pie 的「移除動畫」偏好設定。勾選這些偏好設定後,作業系統就不會使用裝飾效果,例如應用程式啟動動畫。應用程式本身也可以且應該遵守這項設定,並移除所有不必要的動畫。
在網頁版上移除動態效果
媒體查詢層級 5 也將減少動作的使用者偏好設定帶到網路上。作者可透過媒體查詢測試及查詢使用者代理程式或顯示裝置的值或功能,而不必考慮要轉譯的文件。媒體查詢 prefers-reduced-motion 用於偵測使用者是否已設定作業系統偏好設定,盡量減少動畫或動態效果的使用量。可設為下列兩個值:
no-preference:表示使用者在基礎作業系統中未設定偏好設定。在布林值環境中,這個關鍵字值會評估為false。reduce:表示使用者已設定作業系統偏好設定,指出介面應盡量減少動作或動畫,最好是移除所有非必要的動作。
在 CSS 和 JavaScript 環境中使用媒體查詢
與所有媒體查詢一樣,prefers-reduced-motion 可從 CSS 環境和 JavaScript 環境進行檢查。
為說明這兩種做法,假設我有一個重要的註冊按鈕,希望使用者點選。我可以定義吸引注意力的「震動」動畫,但身為優良的網路公民,我只會為明確同意使用動畫的使用者播放動畫,不會為其他人播放,因為這些使用者可能已停用動畫,或使用不瞭解媒體查詢的瀏覽器。
/*
If the user has expressed their preference for
reduced motion, then don't use animations on buttons.
*/
@media (prefers-reduced-motion: reduce) {
button {
animation: none;
}
}
/*
If the browser understands the media query and the user
explicitly hasn't set a preference, then use animations on buttons.
*/
@media (prefers-reduced-motion: no-preference) {
button {
/* `vibrate` keyframes are defined elsewhere */
animation: vibrate 0.3s linear infinite both;
}
}
為說明如何使用 JavaScript 處理 prefers-reduced-motion,假設我已使用 Web Animations API 定義複雜的動畫。使用者偏好設定變更時,瀏覽器會動態觸發 CSS 規則,但對於 JavaScript 動畫,我必須自行監聽變更,然後手動停止可能正在進行的動畫 (或在使用者允許時重新啟動):
const mediaQuery = window.matchMedia('(prefers-reduced-motion: reduce)');
mediaQuery.addEventListener('change', () => {
console.log(mediaQuery.media, mediaQuery.matches);
// Stop JavaScript-based animations.
});
請注意,實際媒體查詢必須以括號括住:
window.matchMedia('prefers-reduced-motion: reduce');
window.matchMedia('(prefers-reduced-motion: reduce)');
從 <picture> 環境使用媒體查詢
有趣的使用案例是讓動畫 AVIF、WebP 或 GIF 的播放取決於 media 屬性。如果 (prefers-reduced-motion: no-preference) 評估結果為 true,則可安全顯示動畫版,否則顯示靜態版:
<picture>
<!-- Animated versions. -->
<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)"
/>
<!-- Static versions. -->
<img src="nyancat.png" alt="Nyan cat" width="250" height="250" />
</picture>
請參閱以下範例。你可以試著切換裝置的動作偏好設定,看看有什麼不同。
在要求時瞭解使用者的偏好設定
網站可選擇在要求時,透過 Sec-CH-Prefers-Reduced-Motion 用戶端提示標頭取得使用者的動態偏好設定,讓伺服器內嵌正確的 CSS,提升效能。
示範
我根據 Rogério Vicente 的精彩 🐈 HTTP 狀態貓建立了一個小型示範。首先,請花點時間欣賞這個笑話,這真的很好笑,我會等。歡迎回來!接下來,我將介紹示範。捲動時,每個 HTTP 狀態貓會交替從右側或左側出現。這是 60 FPS 的流暢動畫,但如先前所述,部分使用者可能不喜歡或甚至會因此感到暈眩,因此示範程式會尊重 prefers-reduced-motion。這項功能甚至可以動態運作,因此使用者可以即時變更偏好設定,無須重新載入。如果使用者偏好減少動態效果,系統會移除不必要的顯示動畫,只留下一般捲動動作。以下螢幕側錄影片顯示實際運作的範例:
prefers-reduced-motion示範影片
結論
尊重使用者偏好是現代網站的關鍵,瀏覽器也提供越來越多功能,協助網頁開發人員達成這個目標。另一個推出的範例是 prefers-color-scheme,可偵測使用者偏好淺色或深色配色。如要瞭解所有相關資訊,請參閱我的文章「Hello Darkness, My Old Friend」🌒。prefers-color-scheme
CSS 工作群組正在將更多使用者偏好設定媒體查詢標準化,例如 prefers-reduced-transparency (偵測使用者是否偏好降低透明度)、prefers-contrast (偵測使用者是否要求系統增加或減少相鄰顏色之間的對比度),以及 inverted-colors (偵測使用者是否偏好反轉顏色)。
(額外) 強制在所有網站上減少動態效果
並非所有網站都會使用 prefers-reduced-motion,或可能不夠顯眼,無法滿足您的需求。
如果基於任何原因想停止所有網站上的動態效果,其實可以這麼做。如要達成這個目標,其中一種做法是在您瀏覽的每個網頁中,插入含有下列 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: 1ms !important;
transition-delay: -1ms !important;
}
}
運作方式是先前的 CSS 會將所有動畫和轉場效果的持續時間覆寫為極短的時間,因此不再明顯。部分網站必須執行動畫才能正常運作 (可能是因為特定步驟必須觸發 animationend 事件),因此較激進的 animation: none !important; 方法不適用。即使是先前的解決方法,也無法保證在所有網站上都能成功 (例如,無法停止使用 Web Animations API 啟動的動作),因此發現問題時,請務必停用該方法。
資源
- 《媒體查詢第 5 級》規格的最新編輯者草案。
prefers-reduced-motion「Chrome 平台狀態」。prefers-reduced-motionChromium 錯誤。- Blink 實作意圖貼文。
特別銘謝
特別感謝 Stephen McGruer 在 Chrome 中實作
prefers-reduced-motion,並與 Rob Dodson 共同審查這份文件。