שאילתת המדיה prefers-reduced-motion מזהה אם המשתמש ביקש ממערכת ההפעלה לצמצם את כמות האנימציה או התנועה שבה היא משתמשת.
לא כולם אוהבים אנימציות דקורטיביות או מעברים, וחלק מהמשתמשים חווים בחילה תוך כדי תנועה כשהם מתמודדים עם גלילה פרלקסית, אפקטים של שינוי מרחק התצוגה ועוד. השאילתה prefers-reduced-motion
של מדיה לפי העדפות המשתמש מאפשרת לכם לעצב גרסה של האתר עם תנועה מופחתת למשתמשים שהביעו את ההעדפה הזו.
יותר מדי תנועה בעולם האמיתי ובאינטרנט
ביום אחר, החלקה על הקרח עם הילדים שלי. זה היה יום מקסים, השמש זרחה וזירת הקרח מלאה באנשים ⛸. הבעיה היחידה עם זה: אני לא מתמודדת היטב עם המונים. כשיש כל כך הרבה מטרות נעות, אי אפשר להתמקד בשום דבר, ובסופו של דבר מתבלבלים ומקבלים תחושה של עומס חזותי מוחלט, כמעט כמו שצופים במושבה של נמלים 🐜.
לפעמים זה יכול לקרות באינטרנט: עם מודעות מהבהבות, אפקטים מיוחדים של פרלקס, אנימציות
מפתיעות, הפעלה אוטומטית של סרטונים ועוד, האינטרנט עלול לפעמים להיות די מוצף...
בשמחה, שלא כמו במציאות, יש פתרון לכך. שאילתת המדיה של CSS prefers-reduced-motion
מאפשרת למפתחים ליצור וריאנט של דף למשתמשים שמעדיפים להקטין את התנועה. הפעולות האלה יכולות להיות מגוונות, החל ממניעת הפעלה אוטומטית של סרטונים ועד להשבתת אפקטים דקורטיביים מסוימים, ועד לעיצוב מחדש של דף מסוים עבור משתמשים מסוימים.
לפני שנצלול לתוך התכונה, אשמח להרחיב על השימוש באנימציות באינטרנט. אם רוצים, אפשר גם לדלג על פרטי הרקע ולדלג ישירות לפרטים הטכניים.
אנימציה באינטרנט
אנימציה משמשת לעיתים קרובות כדי לספק משוב למשתמש, למשל כדי להודיע לו שפעולה כלשהי התקבלה והיא בתהליך עיבוד. לדוגמה, באתר קניות, אפשר להוסיף אנימציה למוצר כדי שהוא 'יעוף' לעגלת קניות וירטואלית שמוצגת כסמל בפינה השמאלית העליונה של האתר.
תרחיש לדוגמה נוסף הוא שימוש בתנועה כדי לפרוץ לתפיסת המשתמש באמצעות שילוב של מסכי שלד, מטא-נתונים לפי הקשר ותצוגות מקדימות של תמונות באיכות נמוכה, כדי להעסיק את המשתמש במשך זמן רב ולגרום לחוויה כולה להרגיש מהירה יותר. הרעיון הוא לספק למשתמשים הקשר לגבי מה שעומד לקרות, ובמקביל לטעון את הדברים מהר ככל האפשר.
לבסוף, יש אפקטים דקורטיביים כמו גרדיאנטים מונפשים, גלילה בפרלקס, סרטונים ברקע ועוד כמה. הרבה משתמשים נהנים מהאנימציות האלה, אבל חלק מהמשתמשים לא אוהבים אותן כי הן מסיחות את דעתם או מאיטות את התהליך. במקרה הגרוע ביותר, המשתמשים עלולים לסבול מחוסר נוחות כתוצאה מתנועה, כאילו מדובר בחוויה מהחיים האמיתיים. לכן, עבור המשתמשים האלה, הפחתת האנימציות היא חובה רפואית.
הפרעת ספקטרום וסטיבולרית שמופעלת על ידי תנועה
חלק מהמשתמשים מתקשים להתרכז או חשים בחילה כשהם צופים בתוכן מונפש. לדוגמה, אנימציות גלילה יכולות לגרום להפרעות שיווי משקל כשאלמנטים שאינם האלמנט הראשי שמשויך לגלילה זזים הרבה. לדוגמה, אנימציות של גלילה פרלקסית יכולות לגרום להפרעות וסטיבולריות כי רכיבי רקע זזים בקצב שונה מאלמנטים בחזית. תגובות של הפרעות ווסטיבולריות (באוזן הפנימית) כוללות סחרחורת, בחילה וכאבי ראש מסוג מיגרנה, ולפעמים נדרש מנוחה במיטה כדי להתאושש.
הסרת תנועה במערכות הפעלה
במערכות הפעלה רבות יש הגדרות נגישות לציון העדפה לגבי תנועה מופחתת למשך זמן רב. בצילומי המסך הבאים מוצגת ההעדפה Reduce motion של macOS Mojave וההעדפה הסרת אנימציות ב-Android Pi. כשהאפשרות הזו מסומנת, ההעדפות האלה גורמות למערכת ההפעלה לא להשתמש באפקטים דקורטיביים כמו אנימציות שמופעלות באפליקציה. גם האפליקציות עצמן יכולות וצריך להקפיד על ההגדרה הזו ולהסיר את כל האנימציות הלא נחוצות.
הסרת תנועה באינטרנט
Media Queries ברמה 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;
}
}
כדי להמחיש איך עובדים עם prefers-reduced-motion
באמצעות JavaScript, נניח שהגדרתם אנימציה מורכבת באמצעות Web Animations API. כללי CSS יופעלו באופן דינמי על ידי הדפדפן כשההעדפות של המשתמש ישתנו, אבל אני צריך להקשיב לשינויים בעצמי כדי להפסיק באופן ידני את האנימציות שעשויות לפעול (או להפעיל אותן מחדש אם המשתמש מאפשר לי):
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 status cats. קודם כול, כדאי לך להקדיש כמה רגעים כדי ליהנות מהבדיחה, היא מצחיקה מאוד ואחכה. עכשיו, כשחזרנו, אשמח להציג את ההדגמה. כשגוללים, כל קטגוריה של סטטוס HTTP מופיעה לסירוגין בצד שמאל או בצד ימין. זהו אנימציה חלקה מאוד של 60FPS, אבל כפי שצוין קודם, יכול להיות שחלק מהמשתמשים לא יאהבו אותה או אפילו יסבלו מבחילות תנועה בגללה, ולכן הדמו מתוכנן כך שיכבד את prefers-reduced-motion
. זה אפילו עובד באופן דינמי, כך שהמשתמשים יכולים לשנות את ההעדפה שלהם תוך כדי תנועה, ללא צורך בטעינה מחדש. אם המשתמש מעדיפים תנועה מופחתת, אנימציית החשיפה שלא לצורך תיעלם, ורק תנועת הגלילה הרגילה תיעלם. בסרטון הבא אפשר לראות את ההדגמה בפעולה:
מסקנות
כבוד להעדפות המשתמשים הוא גורם מפתח באתרים מודרניים, ודפדפנים חושפים יותר ויותר תכונות כדי לאפשר למפתחי אינטרנט לעשות זאת. דוגמה נוספת היא prefers-color-scheme
, שמזהה אם המשתמש מעדיף ערכת צבעים בהירה או כהה. אפשר לקרוא את כל הפרטים על prefers-color-scheme
במאמר שלי Hello Darkness, My Old Friend 🌒.
קבוצת העבודה ב-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), לכן חשוב להשבית אותה אם מבחינים בבעיות.
קישורים רלוונטיים
- טיוטת העורך האחרונה של המפרט של Media Queries Level 5.
prefers-reduced-motion
בסטטוס הפלטפורמה של Chrome.prefers-reduced-motion
באג ב-Chromium.- מסמנים את האפשרות כוונה להטמעת פרסום.
אישורים
תודה רבה ל-Stephen McGruer שהטמיע את prefers-reduced-motion
ב-Chrome, וביחד עם Rob Dodson גם בדק את המסמך הזה.
תמונה ראשית (Hero) של Hannah Cauhepe ב-Unsplash.