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

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

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

תמיכה בדפדפן

  • 74
  • 79
  • 63
  • 10.1

מקור

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

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

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

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

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

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

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

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

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

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

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

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

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

צילום מסך של מסך ההגדרות של 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 הנכון מסיבות של ביצועים.

הדגמה (דמו)

יצרתי הדגמה קטנה על סמך 🐈 HTTP status cats המדהים של רוג'ריו ויסנטה. קודם כול, קח רגע כדי להודות לבדיחה. היא מצחיקה מאוד ואני אמתין. עכשיו שחזרת, אני רוצה להציג את ההדגמה. כשגוללים למטה, כל סטטוס HTTP מופיע לסירוגין מצד ימין או מצד שמאל. מדובר באנימציה חלקה של 60 FPS אבל כפי שתואר למעלה, יכול להיות שחלק מהמשתמשים לא יאהבו אותה או אפילו יקפיצו לה תנועה, ולכן גרסת ההדגמה מתוכנתת בהתאם לprefers-reduced-motion. הכלי פועל גם באופן דינמי, כך שהמשתמשים יכולים לשנות את ההעדפות שלהם תוך כדי תנועה ללא צורך בטעינה מחדש. אם משתמש מעדיף הפחתה בתנועה, אנימציות החשיפה שאינן נחוצות ייעלמו, ורק תנועת הגלילה הרגילה תישאר. הקלטת המסך שבהמשך מציגה את ההדגמה בפעולה:

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

מסקנות

חשוב לכבד את העדפות המשתמשים באתרים מודרניים, ודפדפנים חושפים יותר ויותר תכונות שמאפשרות למפתחי אתרים לעשות זאת. דוגמה נוספת שהושקה היא prefers-color-scheme, שמזהה אם המשתמש מעדיף ערכת צבעים בהירה או כהה. אתם יכולים לקרוא הכול על prefers-color-scheme במאמר שלי שלום Darkness, החבר הישן שלי 🌒.

קבוצת העבודה של 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) של האנה קוהפ ב-UnFlood.