העדפה לצמצום תנועה: לפעמים פחות תנועה היא יותר

שאילתת המדיה עם תנועה בצמצום העדפה מזהה אם המשתמש ביקש ממערכת ההפעלה למזער את כמות האנימציה או התנועה שהיא משתמשת בה.

לא כולם אוהבים אנימציות דקורטיביות או מעברים, וחלק מהמשתמשים חווים מיד מחלת תנועה כשהם מתמודדים עם גלילה פרלקסית, אפקטים של שינוי מרחק התצוגה וכן הלאה. שאילתת המדיה prefers-reduced-motion של העדפת המשתמש מאפשרת לעצב וריאציה של האתר בצמצום תנועה למשתמשים שמביעים את ההעדפה הזו.

תמיכה בדפדפן

  • 74
  • 79
  • 63
  • 10.1

מקור

יותר מדי תנועה במציאות ובאינטרנט

ביום אחר, החלקה על הקרח עם הילדים שלי. זה היה יום מקסים, השמש זרחה וזירת הקרח מלאה באנשים ⛸. הבעיה היחידה עם זה: אני לא מתמודדת היטב עם המונים. כשכל כך הרבה ממטרים נעשים, אני לא מצליח להתמקד באף דבר ובסוף איבדתי תחושה של עומס יתר ויזואלי מלא, כמעט כמו בוהה בנמל 🐜.

המון כפות רגליים של אנשים שמחליקים על הקרח.
עומס יתר ויזואלי בחיים האמיתיים.

לפעמים זה יכול לקרות באינטרנט: עם מודעות מהבהבות, אפקטים מיוחדים של פרלקס, אנימציות מפתיעות, הפעלה אוטומטית של סרטונים וכן הלאה, האינטרנט עלול לפעמים להיות די מוצף... באמת, שלא כמו במציאות, יש פתרון לכך. שאילתת המדיה של CSS prefers-reduced-motion מאפשרת למפתחים ליצור וריאנט של דף למשתמשים שמעדיפים להקטין את התנועה. כל דבר יכול להיות כל דבר, החל מהימנעות מהפעלה אוטומטית של סרטונים ועד השבתה של אפקטים מסוימים דקורטיביים בלבד ועד עיצוב מחדש של הדף למשתמשים מסוימים.

לפני שנתעמק בתכונה, ניקח צעד אחד לאחור ונחשוב על אילו אנימציות משתמשים באינטרנט. אם רוצים, אפשר גם לדלג על פרטי הרקע ולדלג ישר לפרטים הטכניים שבהמשך.

אנימציה באינטרנט

לרוב משתמשים באנימציה כדי לתת משוב למשתמש, למשל כדי להודיע לו שהתקבלה פעולה שנמצאת בעיבוד. לדוגמה, באתר קניות, ניתן להוסיף אנימציה של מוצר כדי "לטוס" לעגלת קניות וירטואלית, בתור סמל בפינה השמאלית העליונה של האתר.

עוד תרחיש לדוגמה הוא שימוש בתנועה כדי לפרוץ לתפיסת המשתמש על-ידי שימוש בשילוב של מסכי שלד, מטא-נתונים לפי הקשר ותצוגות מקדימות של תמונות באיכות נמוכה כדי לתפוס חלק גדול מהזמן של המשתמש ולהרגיש יותר מהר. הרעיון הוא לתת למשתמש הקשר לגבי מה שצפוי, ובינתיים, לטעון את הדברים במהירות האפשרית.

לסיום, יש אפקטים דקורטיביים כמו אנימציה הדרגתית, גלילת פרלקס, סרטוני רקע ועוד. משתמשים רבים נהנים מאנימציות כאלה, אבל יש משתמשים שלא אוהבים אותן כי הם מרגישים שדעתם מוסחת או מואטת. במקרה הגרוע ביותר, המשתמשים עלולים אפילו לסבול ממחלת תנועה כאילו מדובר בחוויה אמיתית, ולכן עבורם זו צורך רפואי.

הפרעה בספקטרום וסטיבולרית שמופעלת על ידי תנועה

חלק מהמשתמשים חווים הסתה או בחילה כתוצאה מתוכן אנימציה. לדוגמה, אנימציות של גלילה יכולות לגרום להפרעות וסטיבולריות כשאלמנטים אחרים מלבד הרכיב הראשי שמשויך לגלילה זזים הרבה. לדוגמה, אנימציות של גלילה פרלקסית יכולות לגרום להפרעות וסטיבולריות כי רכיבי רקע זזים בקצב שונה מאלמנטים בחזית. תגובות של הפרעה וסטיבולרית (האוזן הפנימית) כוללות סחרחורת, בחילה וכאבי ראש, ולפעמים דרושות מנוחה במיטה כדי להתאושש.

הסרת תנועה במערכות הפעלה

במערכות הפעלה רבות יש הגדרות נגישות לציון העדפה לגבי תנועה מופחתת למשך זמן רב. בצילומי המסך הבאים רואים את ההעדפה Reduce motion של macOS Mojave ואת ההעדפה הסרת אנימציות ב-Android Pi. כשהאפשרות הזו מסומנת, ההעדפות האלה גורמות למערכת ההפעלה לא להשתמש באפקטים דקורטיביים כמו אנימציות שמופעלות באפליקציה. גם האפליקציות עצמן יכולות וצריכות לפעול בהתאם להגדרה הזו, ולהסיר את כל האנימציות המיותרות.

צילום מסך של מסך ההגדרות ב-macOS, שתיבת הסימון 'הפחתת התנועה' מסומנת בו.
צילום מסך של מסך ההגדרות ב-Android שבו תיבת הסימון 'הסרת אנימציות' מסומנת.

הסרת תנועה באינטרנט

שאילתות מדיה ברמה 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 יופעלו באופן דינמי על ידי הדפדפן כשהעדפת המשתמש משתנה, אבל כשמדובר באנימציות של 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 status cats. קודם כל, תקדישו רגע כדי להבין את הבדיחה, היא מצחיקה מאוד ואני אמתין. עכשיו, אחרי שחזרתם, אני רוצה להציג את ההדגמה. כשגוללים למטה, כל חתול עם סטטוס HTTP מופיע לסירוגין מצד ימין או מצד שמאל. זוהי אנימציה חלקה של 60 FPS, אבל כפי שמתואר למעלה, יש משתמשים שלא יאהבו אותה או אפילו יחלו בה תנועה, ולכן ההדגמה מתוכנתת בהתאם ל-prefers-reduced-motion. זה אפילו עובד באופן דינמי, כך שהמשתמשים יכולים לשנות את ההעדפה שלהם תוך כדי תנועה, ללא צורך בטעינה מחדש. אם המשתמש מעדיפים תנועה מופחתת, אנימציות החשיפה שלא נחוצות ייעלמו, ורק תנועת הגלילה הרגילה תיעלם. בהקלטת המסך הבאה אפשר לראות את ההדגמה:

סרטון של אפליקציית ההדגמה prefers-reduced-motion

מסקנות

באתרים מודרניים חשוב לכבד את העדפות המשתמשים, והדפדפנים חושפים יותר ויותר תכונות שמאפשרות למפתחי אתרים לעשות זאת. דוגמה נוספת שהשקנו היא prefers-color-scheme, שמזהה אם המשתמשים מעדיפים ערכת צבעים בהירה או כהה. אפשר לקרוא את כל המידע על 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), לכן חשוב להשבית אותה כשמבחינים בתקלה.

אישורים

זו הכרת תודה פומבית לסטיבן מקגרואר שהטמיע את prefers-reduced-motion ב-Chrome וביחד עם רוב דודסון – גם כן כתב את המאמר הזה. תמונה ראשית (Hero) מאת חנה קאוהפה (Hanah Cauhepe) ב-Un אימייל.