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

שמים 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 באמת תלויקשורים לזכוכית. גללו כמה שבא לכם.
perspective, backdrop-filter, contain: paint.הבעיה שהם פותרים דמיינו את התרחיש הזה:
<div style="filter: blur(10px);"> <p>הטקסט הזה אמור להיות מטושטש</p> <div style="position: fixed;">האם זה אמור להיות מטושטש?</div></div>אם האלמנט עם fixed היה נשאר יחסי ל-viewport, הוא היה:
- מרונדר מחוץ לשכבה המסוננת
- לא מקבל את אפקט הטשטוש
- שובר את ההיררכיה החזותית (הצאצא בורח מהאפקט החזותי של ההורה)
הטקסט הזה אמור להיות מטושטש
ילד fixed, חתום בתוך div מטושטש.
אתם אולי לא רואים בסיבות האלה בעיה, אבל עבור הדפדפנים וה-w3c הן כן בעיה, כי הן מתנגשות עם פילוסופיית ה-cascade של CSS. מבחינה טכנית אפשר היה ליצור חריגה, אבל היא הייתה דורשת רינדור יקר יותר.
איך מתקנים את זה?
אפשר לתקן את הבעיה בשתי דרכים:
- להסיר מהאלמנט ההורה את הסטייל שהופך אותו ל-
containing block - לציין מיקום לאלמנטים עם 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.