商品卡滑入、背景持續漂浮、按鈕點下去再放大,單看每個效果都不算誇張,放在同一頁卻可能讓人不舒服。有些使用者已在作業系統設定減少動態,網站可以透過prefers-reduced-motion讀到這個偏好,提供更穩定的畫面。
處理這個偏好時,重點是減少不必要的移動,並保留內容與操作。不要把整張商品卡藏起來,也不要讓只有動畫結束後才出現的文字永遠不顯示。先做出沒有動畫也完整可用的版面,再決定哪些效果值得加入。
從靜態基礎開始,比逐項補救更清楚
以下卡片預設就可看見。只有使用者沒有要求減少動態時,才加上短暫滑入與淡入。這是局部元件樣式,可先放在本機範例測試,無須修改全站CSS。
.template-card {
opacity: 1;
transform: none;
}
@keyframes card-enter {
from {
opacity: 0;
transform: translateY(18px);
}
to {
opacity: 1;
transform: none;
}
}
@media (prefers-reduced-motion: no-preference) {
.template-card {
animation: card-enter 300ms ease-out;
}
}
reduce表示使用者希望減少動態;no-preference表示沒有表達這個減少偏好,並不代表使用者主動要求動畫。範例採用保守的靜態預設,即使瀏覽器沒有套用這段media query,卡片仍然完整可見。
若原本的卡片基礎樣式是opacity:0,靠animation填入最後狀態,直接animation:none可能留下透明卡片。應把內容的正常狀態移回基礎樣式,動畫只描述短暫的過程。資料是否顯示與裝飾動畫是否播放,不應綁成同一件事。
既有元件可針對移動效果降低動態
若不能立刻改造所有元件,先找出大幅位移、縮放、視差與持續循環的效果,再為相應元件加入reduce規則。下面針對特定卡片與按鈕移除動畫及過場,同時清除卡片位移。
@media (prefers-reduced-motion: reduce) {
.template-card,
.preview-button {
animation: none;
transition: none;
}
.template-card {
opacity: 1;
transform: none;
}
}
不要直接用萬用選擇器把所有元素的所有效果改成極短時間,再假設功能都不受影響。有些程式依賴animationend或transitionend執行後續動作,完全移除效果後不一定仍會觸發原本流程;有些狀態提示需要改成穩定文字才能說清楚。針對具體元件處理,較容易檢查連帶影響。
若按鈕原本透過縮放表示點擊,可以保留穩定的顏色、邊框或文字狀態。表單送出中不一定需要持續旋轉的圖示,也可以顯示「正在送出」並維持清楚的停用或防重複提交行為。減少動態不等於讓使用者失去進度與完成回饋。
JavaScript效果也要讀同一個偏好
CSS規則只影響CSS控制的效果。用JavaScript啟動的動畫、canvas或動畫函式庫,可能需要另外處理。可以用matchMedia取得目前偏好,再依元件需求選擇靜態狀態或動畫;不要宣稱加一段CSS就能覆蓋所有動態來源。
const motion = window.matchMedia(
'(prefers-reduced-motion: reduce)'
);
function updateMotion() {
document.documentElement.dataset.motion =
motion.matches ? 'reduce' : 'normal';
}
updateMotion();
motion.addEventListener('change', updateMotion);
這段程式只保存偏好到資料屬性,沒有自行停止任何動畫。你的元件還需要讀取這個狀態,決定是否啟動、停止或重設效果。長時間開啟頁面的人可能改變系統偏好,因此change監聽可以讓畫面跟著更新;在元件框架裡,卸載時也應移除自己建立的監聽。
若JavaScript要求平滑捲動,可以在reduce時採用不平滑的選項,並確認專案CSS沒有又把捲動設成smooth。真正想驗的是使用者移到目標內容時,不需要經過長距離動畫,而非只看程式參數改成某個值。
用兩種偏好驗證同一份內容
測試前先列出效果的作用,會更容易決定如何替代。商品卡滑入只是裝飾,可直接拿掉;頁面載入中需要告訴人資料尚未準備好,可改用文字;抽屜展開表示內容出現,可直接顯示面板但保留開關狀態與焦點。不要把所有效果都當成相同類型,也不要因為某個動畫具有提示用途,就認為它一定必須持續移動。
若元件完成工作後需要執行清理,應讓完成流程由實際任務控制。表單提交成功由請求結果決定,不能只等動畫結束才啟用下一步;關閉面板則應確認狀態與焦點處理,在沒有過場時也能結束。這樣才能在reduce、動畫被打斷或頁面背景執行時保留一致行為。
調整動畫時,也別順手移除焦點框或錯誤提示的顏色。那些是操作資訊,未必需要位移效果。減少動態版本仍應保留足夠對比與清楚標示,讓使用者知道目前按到哪個控制項。先把穩定的資訊留下,再拿掉可有可無的移動,會比整個狀態樣式一併取消更合理。
本機Chromium案例在no-preference和reduce兩種模擬偏好下讀取卡片樣式與按鈕操作。一般偏好有card-enter動畫;減少動態時動畫名稱為none。兩種狀態都能看見同一個卡片標題、按鈕都能觸發計數。這是瀏覽器模擬案例,沒有宣稱真實作業系統或所有裝置已完成測試。
自己的頁面可從瀏覽器Rendering工具模擬prefers-reduced-motion,再按實際流程走一次。檢查初始載入、捲動出現內容、hover、開關面板、輪播與送出表單。不要只截下靜態畫面,因為有些問題在第二次操作或資料更新時才出現,例如返回列表後卡片仍透明。
也要測偏好在頁面開啟後切換的情形。動畫函式庫可能在初始化時只讀一次設定,系統改為減少動態後仍持續播放;或者停掉動畫卻沒有把元件放回可見位置。若元件支援動態更新,應確認停止之後的狀態;若只能初始化時決定,則明確調整實作,不要讓CSS與JavaScript互相矛盾。
循環內容與必要回饋分開處理
減少動態偏好不是處理所有自動播放內容的唯一規則。持續自動移動、閃爍或捲動的內容,還可能需要暫停、停止或隱藏控制;相關要求有觸發條件與例外,不能把reduce開關當成整頁符合無障礙要求的證明。對輪播而言,保留手動切換與清楚控制,比單純放慢速度更容易使用。
如果動態本來用來教操作,也要提供能靜態閱讀的步驟或關鍵畫面。避免只在動畫裡展示按哪個按鈕,停掉之後就什麼都沒有。商品列表則應保留名稱、價格與連結;成功提示保留完成訊息。每個效果都可以問一次:移除移動後,使用者還能否知道目前狀態與下一步?
與其一次把整頁效果全面關掉,可以先從最明顯的背景漂浮、視差和大範圍滑入開始,逐個元件留下穩定替代狀態。完成後再用桌面與窄螢幕核對內容、鍵盤焦點及操作。動態是表達方式,內容的可讀性與功能應在兩種偏好下都站得住。
參考資料
WCAG:Animation from Interactions
WAI:以reduce偏好避免動態
MDN:matchMedia
MDN:animation
WCAG:Pause, Stop, Hide

評論0