שאילתת המדיה prefers-reduced-motion מזהה אם המשתמש ביקש ממערכת ההפעלה לצמצם את כמות האנימציה או התנועה שבה היא משתמשת.
לא כולם אוהבים אנימציות או מעברים דקורטיביים, וחלק מהמשתמשים סובלים מחוסר נוחות כתוצאה מתנועה, כשהם נתקלים בגלילה בפרלקס, באפקטים של שינוי מרחק התצוגה ועוד. שאילתת המדיה לפי העדפות המשתמש prefers-reduced-motion
מאפשרת לכם לעצב גרסה של האתר עם תנועה מופחתת למשתמשים שהביעו את ההעדפה הזו.
יותר מדי תנועה בעולם האמיתי ובאינטרנט
לפני כמה ימים, גלשתי על הקרח עם הילדים שלי. היה יום מקסים, השמש זרחה והאגם היה מלא באנשים ⛸. הבעיה היחידה היא שאני לא מתמודד טוב עם המון אנשים. עם כל כך הרבה מטרות נעות, אי אפשר להתמקד בשום דבר, ובסופו של דבר מתבלבלים ומקבלים תחושה של עומס חזותי מוחלט, כמעט כמו שצופים במושבה של נמלים 🐜.
לפעמים אותו הדבר יכול לקרות באינטרנט: מודעות מהבהבות, אפקטים מיוחדים של פרלקס, אנימציות חשיפות מפתיעות, סרטונים שפועלים בהפעלה אוטומטית ועוד – לפעמים האינטרנט יכול להיות די מבלבל… לשמחתנו, בניגוד לחיים האמיתיים, יש לכך פתרון. שאילתה של מדיה ב-CSS prefers-reduced-motion
מאפשרת למפתחים ליצור גרסה של דף למשתמשים שמעדיפים תנועה מופחתת. הפעולות האלה יכולות להיות מגוונות, החל ממניעת הפעלה אוטומטית של סרטונים ועד להשבתת אפקטים דקורטיביים מסוימים, או עיצוב מחדש של דף מסוים עבור משתמשים מסוימים.
לפני שנצלול לתוך התכונה, אשמח להרחיב על השימוש באנימציות באינטרנט. אם רוצים, אפשר גם לדלג על המידע הרקע ולעבור ישירות לפרטים הטכניים.
אנימציה באינטרנט
אנימציה משמשת לעיתים קרובות כדי לספק משוב למשתמש, למשל כדי להודיע לו שהפעולה התקבלה והיא בתהליך עיבוד. לדוגמה, באתר קניות, אפשר להוסיף אנימציה למוצר כדי שהוא 'יעוף' לעגלת קניות וירטואלית שמוצגת כסמל בפינה השמאלית העליונה של האתר.
תרחיש לדוגמה נוסף הוא שימוש בתנועה כדי לפרוץ לתפיסת המשתמש באמצעות שילוב של מסכי שלד, מטא-נתונים לפי הקשר ותצוגות מקדימות של תמונות באיכות נמוכה, כדי להעסיק את המשתמש במשך זמן רב ולגרום לחוויה כולה להרגיש מהירה יותר. הרעיון הוא לספק למשתמשים הקשר לגבי מה שעומד לקרות, ובמקביל לטעון את הדברים מהר ככל האפשר.
לבסוף, יש אפקטים דקורטיביים כמו גרדיאנטים מונפשים, גלילה בפרלקס, סרטונים ברקע ועוד כמה. הרבה משתמשים נהנים מהאנימציות האלה, אבל חלק מהמשתמשים לא אוהבים אותן כי הן מסיחות את דעתם או מאטות את התהליך. במקרה הגרוע ביותר, המשתמשים עלולים לסבול מחוסר יציבות בתנועה (motion sickness) כאילו מדובר בחוויה מהחיים האמיתיים, ולכן עבור המשתמשים האלה הפחתת האנימציות היא חובה רפואית.
הפרעה בספקטרום הווסטיבולרי שמופיעה בתגובה לתנועה
חלק מהמשתמשים מתקשים להתרכז או חשים בחילה כשהם צופים בתוכן מונפש. לדוגמה, אנימציות גלילה יכולות לגרום להפרעות שיווי משקל כשאלמנטים שאינם האלמנט הראשי שמשויך לגלילה זזים הרבה. לדוגמה, אנימציות של גלילה בפרלקס יכולות לגרום להפרעות שיווי משקל כי רכיבי הרקע נעים בקצב שונה מרכיבי החזית. תגובות של הפרעות ווסטיבולריות (באוזן הפנימית) כוללות סחרחורת, בחילה וכאבי ראש מסוג מיגרנה, ולפעמים נדרש מנוחה במיטה כדי להתאושש.
הסרת תנועה במערכות הפעלה
כבר הרבה זמן יש במערכות הפעלה רבות הגדרות נגישות שמאפשרות לציין העדפה לתנועה מופחתת. בצילום המסך הבא מוצגת ההעדפה הפחתת התנועה ב-macOS Mojave, ובצילום המסך הבא מוצגת ההעדפה הסרת אנימציות ב-Android Pie. אם מסמנים את ההעדפות האלה, מערכת ההפעלה לא משתמשת באפקטים דקורטיביים כמו אנימציות של הפעלת אפליקציות. גם האפליקציות עצמן יכולות וצריך להקפיד על ההגדרה הזו ולהסיר את כל האנימציות הלא נחוצות.
הסרת תנועה באינטרנט
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. קודם כול, כדאי לך להקדיש כמה שניות כדי ליהנות מהבדיחה, היא מצחיקה מאוד ואחכה. עכשיו, כשחזרנו, אשמח להציג את ההדגמה. כשגוללים, כל קטגוריה של סטטוס 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.