עבור לתוכן
Alex Kovalev

איך פילטר גווני אפור שבר לי את כל הפופאפים

למה הוספת סטייל filter לאלמנט body שוברת אלמנטים עם fixed?

2דקות קריאה

שמים position: fixed על אלמנט - לאן הוא נדבק? ל-viewport, כמובן. חוץ מהמקרה שבו תוסף הנגישות שלכם מוסיף פילטר גווני אפור ל-body.

מסתבר שאלמנטים עם fixed לא תמיד מעוגנים ל-viewport. הם מעוגנים לcontaining block שלהם. בדרך כלל זה ה-viewport. אבל תכונות CSS מסוימות - כמו filter - יוצרות containing block חדש.

אז כש-.pojo-a11y-grayscale נוחת על ה-body שלכם, כל אלמנט עם fixed ממוקם עכשיו יחסית ל-<body> במקום ל-viewport. התפריט הדביק שלכם, המודאלים והכפתורים בפינה הימנית-תחתונה נופלים לתהומות העמוד שלכם, ממש מתחת לפוטר. הם עדיין “fixed”, רק מקובעים לדבר הלא נכון.

כלי נגישות
פילטר על
כלום
containing block
viewport
בועת צ׳אט
על המסך

סמנו "גווני אפור". ותעקבו אחרי הפינה השמאלית-תחתונה.

body.pojo-a11y-grayscale {
filter: grayscale(100%);
-webkit-filter: grayscale(100%);
-webkit-filter: grayscale(1);
-moz-filter: grayscale(100%);
-ms-filter: grayscale(100%);
-o-filter: grayscale(100%);
filter: gray;
}

למעשה, כל אחד מהכללים המוזכרים למטה יגרום לאותה תופעה

body {
transform: translateZ(0);
will-change: transform;
perspective: 1000px;
filter: grayscale(100%);
}

אבל למה?

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

על מה position: fixed באמת תלוי
100200300400500600700<html><footer><body>שכבה משלוviewportלהירשם לניוזלטר?בטחcontaining block: viewport
על <body>

קשורים לזכוכית. גללו כמה שבא לכם.

אותה נפילה עם perspective, backdrop-filter, contain: paint.

הבעיה שהם פותרים דמיינו את התרחיש הזה:

<div style="filter: blur(10px);">
<p>הטקסט הזה אמור להיות מטושטש</p>
<div style="position: fixed;">האם זה אמור להיות מטושטש?</div>
</div>

אם האלמנט עם fixed היה נשאר יחסי ל-viewport, הוא היה:

  1. מרונדר מחוץ לשכבה המסוננת
  2. לא מקבל את אפקט הטשטוש
  3. שובר את ההיררכיה החזותית (הצאצא בורח מהאפקט החזותי של ההורה)
לשחרר את הילד ה-fixed מהטשטוש
viewport

הטקסט הזה אמור להיות מטושטש

ילד fixed, חתום בתוך div מטושטש.

הטשטוש הוחלש מ-10px כדי שעוד יהיה אפשר לקרוא.

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

איך מתקנים את זה?

אפשר לתקן את הבעיה בשתי דרכים:

  1. להסיר מהאלמנט ההורה את הסטייל שהופך אותו ל-containing block
  2. לציין מיקום לאלמנטים עם fixed ביחס ל-containing block החדש

נחזור לאתר הוורדפרס עם התוסף Pojo Accessibility. בלחיצה הוא מוסיף ל-body את .pojo-a11y-grayscale: הבלוק מתחילת הפוסט. כל מה שאחרי השורה הראשונה שלו זה vendor prefixes ותחביר ישן לדפדפנים שכמעט נעלמו, אז למטה אני מדלג על החומה הזאת וכותב רק filter. אם אכפת לכם עדיין מדפדפנים עתיקים, תחזירו את ה-prefixes.

הייתי דורס את זה ככה:

body.pojo-a11y-grayscale {
filter: unset;
}
html:has(body.pojo-a11y-grayscale) {
filter: grayscale(100%);
}

היתרון: אנחנו לא נוגעים ב-JS, לא משנים איך התוסף או הטריגרים שלו עובדים, וזה מפורש. האפקט פשוט עובר מ-body ל-html. ו-html הוא החריג היחיד בספק: filter על אלמנט השורש לא יוצר containing block חדש, אז כל האלמנטים עם fixed חוזרים להיות יחסיים ל-viewport.

להעלות את הפילטר קומה
פילטר על
body.pojo-a11y-grayscale {
  filter: grayscale(100%);
}

הדרך של התוסף. ה-body חוטף את הפופאפ, אל מחוץ למסך.

רק ל-filter יש פטור בשורש; transform על html עדיין חוטף.

אופציה נוספת

היא לציין אחים במקום אב. אם יש לכם מבנה כזה

<html>
<body>
<div style="position:fixed">...</div>
<article>...</article>
</body>
</html>

אפשר להריץ את הפילטר ברמת האלמנט האח לזה שיש לו fixed, ככה:

/* מסירים את הפילטר של התוסף מה-body */
body.pojo-a11y-grayscale {
filter: unset;
}
body.pojo-a11y-grayscale > * {
filter: grayscale(100%);
}

כך או כך, הפופאפים מחלצים את עצמם מתחת לפוטר. בפעם הבאה שמשהו עם position: fixed מפסיק להיות fixed, אל תדבגו את האלמנט עצמו. תעלו במעלה האבות שלו ותחפשו filter, transform, perspective או will-change. סביר להניח שאחד מהם תפס לכם את ה-viewport.

ראו גם: לתקן פונט, עוד באג CSS באתר וורדפרס ישן אחר.

תגובות

התגובות נשמרות ב-GitHub Discussions (דרך giscus), אז כדי להצטרף לשיחה צריך חשבון GitHub.

אצייץ לך כשיעלה פוסט חדש

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

מעדיפים קורא RSS? יש פיד RSS.

© Alex Kovalev. כל הזכויות שמורות. · מדיניות פרטיות