תאריך פרסום: 14 באוגוסט 2025
עונת אירועי Google I/O מתקרבת לסיומה, ולכן בפוסט הזה נסכם את הרגעים הבולטים ביותר בנושא CSS וממשק משתמש לאינטרנט ששותפו באירועים שלנו השנה.
תכונות עוצמתיות להפליא שפעם מפתחים רק חלמו עליהן, הגיעו לדפדפנים ומשיגות תאימות בין דפדפנים מהר יותר מאי פעם. עם זאת, למרות ההתקדמות הזו, עדיין קשה להטמיע בצורה נכונה חלק מדפוסי ממשק המשתמש הנפוצים ביותר. לרוב צריך להסתמך על מסגרות JavaScript, על טריקים מורכבים של CSS ועל כמויות גדולות של קוד בהתאמה אישית כדי לבנות רכיבים שאמורים להיות פשוטים יותר.
צוות Chrome, בשיתוף פעולה עם ספקי דפדפנים אחרים, גופים לקביעת תקנים כמו CSSWG ו-WHATWG וקבוצות קהילתיות כמו Open UI, מתמקד בהפיכת דפוסי ממשק המשתמש הבסיסיים האלה לפשוטים ליישום.
תפריטי בחירה שאפשר להתאים אישית
רכיב ה-<select> חיוני לטפסים, אבל בעבר המבנה הפנימי שלו היה מוסתר על ידי הדפדפן, ולכן היה כמעט בלתי אפשרי ליצור סגנון CSS עקבי ומקיף. כדי ליצור <select> טוב יותר, צריך להבין את אבני הבניין שלו – Popover API ו-CSS Anchor Positioning API.
Popover API: עכשיו ב-Baseline
לתפריט נפתח מותאם אישית צריך להיות תיבת אפשרויות צפה שמופיעה מעל כל רכיבי ממשק המשתמש האחרים, שקל לסגור אותה ושמנהלת את המיקוד בצורה נכונה. Popover API מטפל בכל זה, והחל מהשנה הוא הגיע לסטטוס Baseline Newly available, כלומר הוא יציב בכל הדפדפנים המובילים.
כדי ליצור חלון קופץ צריך שני חלקים: אלמנט הפעלה (כמו <button>) ואלמנט החלון הקופץ עצמו. כדי לקשר ביניהם, צריך לתת לבועה את המאפיין id ואת המאפיין [popover], ואז להפנות אל id במאפיין [popovertarget] של הלחצן.
ה-API של חלונות קופצים מנהל את כל מחזור החיים של הרכיב, ומספק:
- רינדור בשכבה העליונה: לא צריך יותר להתעסק עם אינדקס-z.
- אפשרויות סגירה קלה: נסגר כשמשתמש לוחץ מחוץ לאזור של התוכן הקופץ.
- ניהול אוטומטי של המיקוד: הדפדפן מטפל בניווט באמצעות מקש Tab אל תוך חלון הקופץ ומחוצה לו.
- קישורים נגישים: מודל האינטראקציה הבסיסי מטופל באופן מקורי.
הרכיב <dialog> עובר שדרוג
התכונה popover היא עוצמתית, אבל היא לא תמיד הבחירה הנכונה. לדוגמה, באינטראקציות שחוסמות את הדף ודורשות משוב מהמשתמש, עדיף להשתמש בתיבת דו-שיח מודאלית <dialog>.
בעבר, <dialog> לא כלל חלק מהתכונות הנוחות של [popover], אבל המצב הזה משתנה. בעזרת המאפיין החדש closedby="any", תיבות דו-שיח מודאליות תומכות עכשיו בפונקציונליות של סגירה קלה, ונסגרות כשמשתמש לוחץ מחוץ לתיבה או לוחץ על מקש Escape.
בנוסף, רכיבי הפעלה של פקודות ([command] ו-[commandfor]) מספקים דרך הצהרתית ללא JavaScript לקשר לחצן לפעולה, כמו פתיחת תיבת דו-שיח באמצעות command="show-modal".
<dialog> Element + closedby=any + command invokers |
מאפיין אחד ([popover]) |
|
|---|---|---|
| שימוש ראשי | אינטראקציה עם חלון קופץ (הסכמי שימוש, הדרכות וכו') | ממשק משתמש זמני (תפריטים, תיאורי כלים, כרטיסים, התראות קצרות) |
| Light Dismiss-able | כן | כן |
| Traps Focus | כן | לא |
| דף חומרים אינרטיים | כן | לא |
| הפעלה הצהרתית | כן | כן |
| הטמעה | רכיב | מאפיין |
| רכיבים שמוצגים בשכבה העליונה | כן | כן |
| ניתן לעיצוב מלא | כן | כן |
מיקום של רכיבי עוגן ב-CSS
אחרי שחלון קופץ מופיע, צריך למקם אותו ביחס לאלמנט שפתח אותו. חישוב ידני של הערך הזה באמצעות JavaScript הוא מסובך ועלול לפגוע בביצועים.
מגרסה Chrome 125, אפשר להשתמש ב-CSS Anchor Positioning API. היכולת החדשה הזו מאפשרת לקשור באופן הצהרתי רכיב אחד לרכיב אחר, ולטפל באופן אוטומטי במיקום מחדש כשהרכיב מתקרב לקצה המסך. התכונה הזו היא חלק מ-Interop 2025, יוזמה חוצת-דפדפנים להשקת תכונות מבוקשות מאוד. כלומר, אפשר לצפות שהיא תהיה זמינה בכל הדפדפנים הגדולים עד סוף 2025.
אפשר לקשר באופן מפורש בין רכיבים באמצעות המאפיינים anchor-name ו-position-anchor, אבל עדכון במפרט וב-Chrome 133 יוצר קשר עקיף של עוגן בין <popover> לבין <button> שמפעיל אותו. השינוי הזה מפשט מאוד את הקוד, ועכשיו אפשר למקם את חלון הקופץ באמצעות שורה אחת של CSS, כמו: position-area: bottom span-left.
כלי העוגן מ-chrome.dev מראה לכם איך להשתמש ב-position-area כדי לקבל את המיקום הרצוי:
כדי להגדיר חלופות באמצעות position-try-fallbacks, אפשר להגדיר את הדפדפן כך שישנה את המיקום של העוגנים כדי שלא יצאו מהמסך. בהדגמה הבאה מוצג חלון קופץ שמשתמש במאפיין הזה ללוגיקה מובנית של מיקום מחדש:
<select>
אחרי ששילבנו את אבני הבניין האלה בגרסאות קודמות, סוף סוף הגיעו ל-Chrome 134 סגנונות מקוריים לאינטרנט עבור רכיבי <select>. העדכון כולל את המאפיין החדש appearance, פסאודו-אלמנטים חדשים ואת האלמנט <selectedcontent>.
כדי לבטל את הנעילה של ההתאמה האישית, צריך להחיל את appearance: base-select; על הרכיב <select> ועל פסאודו-הרכיב החדש שלו ::picker(select), שמטרגט את התפריט הנפתח של האפשרויות. הפעולה הזו חושפת חלקים פנימיים חדשים לעיצוב, כולל:
-
<selectedcontent>: מייצג את התוכן של האפשרות שנבחרה שמוצגת בכפתור. -
::picker-icon: סמל החץ לתפריט הנפתח -
<option>:checkedו-::checkmark: לעיצוב האפשרות שנבחרה וסימן הווי שמציין אותה
כך אפשר להציג תוכן עשיר באפשרויות ולשלוט באופן מדויק על התצוגה. לדוגמה, אפשר להציג סמל וכתובית ברשימת האפשרויות, אבל להסתיר אותם במצב הסגור באמצעות display: none בתוך selectedcontent.
היתרון הכי גדול הוא שאפשר לשפר את ה-API הזה בהדרגה. בדפדפנים שלא תומכים בתכונות האלה, המשתמשים עדיין יקבלו רכיב בחירה פונקציונלי שמותאם לאינטרנט. אתם מקבלים מראה מותאם אישית תוך שמירה על הנגישות המובנית, הניווט במקלדת והשילוב של טופס של רכיב הבחירה המקורי באינטרנט.
קרוסלות
קרוסלות נמצאות בכל מקום באינטרנט, ולא רק בחלקים המרכזיים של דפי האינטרנט. האיסור הזה כולל תוכן שאפשר לגלול אופקית בפריסות צפופות, כמו ממשק משתמש של חנות אפליקציות. אבל עדיין קשה ליצור קרוסלות באינטרנט, ויש הרבה שיקולים כמו ניהול מצב, גלילה לא חלקה, אינטראקטיביות ונגישות. אבל אם חושבים על זה, קרוסלות הן בעצם אזורי גלילה משוכללים עם תכונות נוספות בממשק המשתמש.
איך מתחילים להשתמש ב-scrollers
כדי ליצור קרוסלה, מתחילים עם רשימת פריטים שגולשים מהגבולות של הקונטיינר שלהם. כדי להסתיר את סרגל הגלילה האופקי ועדיין לאפשר גלילה של התוכן, משתמשים ב-scrollbar-width: none. בנוסף, כדי שהגלילה תהיה חלקה, משתמשים ב-scroll-snap-type וב-scroll-snap-align, וכך מוודאים שהפריטים יקפצו למקומם כשהמשתמש גולל.
הקודם והבא עם ::scroll-button
האלמנט הווירטואלי החדש ::scroll-button(), שנוסף ל-Chrome 135, מורה לדפדפן ליצור לחצני 'הבא' ו'הקודם' נגישים עם שמירת מצב. הדפדפן מטפל אוטומטית בתפקידי ה-ARIA הנכונים, בסדר הכרטיסיות ואפילו משבית את הלחצנים כשמגיעים להתחלה או לסוף – והכול ללא JavaScript נוסף.
כדי להפעיל את לחצני הגלילה, צריך לספק להם תוכן ותווית נגישה, כך:
.carousel {
&::scroll-button(left) {
content: "⬅" / "Scroll Previous";
}
&::scroll-button(right) {
content: "⮕" / "Scroll Next";
}
}
מומלץ להשתמש במיקום עוגן ב-CSS כדי להגדיר את הסגנון של הלחצנים האלה ולמקם אותם ביחס לקרוסלה הראשית שלהם.
ניווט ישיר באמצעות ::scroll-marker
במקרה של נקודות או תמונות ממוזערות, פסאודו-האלמנטים ::scroll-marker ו-::scroll-marker-group משייכים את סמני הניווט ישירות לפריטים במיכל הגלילה. הדפדפן מתייחס לקבוצה כמו אל tablist ומטפל בניווט באמצעות המקלדת.
בדומה ללחצני גלילה, כדי להפעיל את סמני הגלילה צריך להשתמש במאפיין content ולספק תווית נגישה. בדוגמה הבאה, נעשה שימוש במאפיין data כדי להגדיר את התווית של סמן הגלילה. בנוסף, כדי למקם את סמני הגלילה ב-::scroll-marker-group, צריך להשתמש במאפיין scroll-marker-group. לבסוף, כדי לעצב את הסמן הפעיל, צריך להשתמש במחלקת ה-pseudo החדשה :target-current. הנה דוגמה לאופן שבו זה יכול להיראות בקרוסלה בסיסית:
.carousel {
scroll-marker-group: after;
> li::scroll-marker {
content: ''/ attr(data-name);
}
> li::scroll-marker:target-current {
background: blue;
}
}
שאילתות לגבי מצב הגלילה
תכונות חדשות של CSS שקשורות לגלילה מאפשרות ליצור קרוסלות דינמיות ואינטראקטיביות יותר. שאילתת מצב הגלילה היא שאילתת מדיה חדשה שחלה על סמך מצב רכיב הגלילה. יש שלושה סוגים שונים של שאילתות לגבי מצב הגלילה, שאפשר לגשת אליהן באמצעות scroll-state() בהצהרת @container. סוגי המשנה הם:
-
scroll-state(snapped): מתאים כשאלמנט נמצא במיקום 'מוצמד'. בקרוסלות, זה קורה כשהפריט נצמד למרכז הקרוסלה. -
scroll-state(stuck): עיצוב של רכיב, כמו כותרת, כשהרכיב ההורה שלו הופך לנייח. scroll-state(scrollable): להוסיף אינדיקטורים ויזואליים, כמו הבהרה, כדי להראות שיש עוד תוכן שאפשר לגלול אליו.
מסכם הכול
שילוב של פרימיטיבים חדשים של קרוסלות CSS, שאילתות של מצב הגלילה ומיקום עוגן, מקל עליכם ליצור קרוסלות מותאמות אישית ואינטראקטיביות. אפשר גם לשלב אנימציות מבוססות-גלילה כדי לקשר אנימציות ישירות למיקום הגלילה, וליצור אפקטים יעילים כמו שינוי גודל ודהייה של פריטים בזמן הגלילה לתצוגה. האנימציות האלה פועלות מחוץ לשרשור הראשי, ומאפשרות חוויה חלקה במיוחד.
קרוסלת התמונות האינטראקטיבית הזו משלבת שאילתות scroll-state(), ::scroll-button, ::scroll-marker, מיקום עוגן CSS ו-:target-current.
בנוסף, אפשר להשתמש במאפיין חדש שנקרא interactivity כדי לעזור למשתמשים להתמקד בתוכן הפעיל. interactivity: inert מאפשר למשתמש להחיל אינרטיות באמצעות CSS, כך שפריטים בקרוסלה שלא מוצגים במסך לא ניתנים למיקוד ומוסרים מעץ הנגישות.
כרטיסים צפים אינטראקטיביים
כרטיסי מידע – חלונות קופצים עשירים שמופיעים כשמעבירים את העכבר מעל שם משתמש או קישור – הם מאוד שימושיים, אבל ידועים כקשים לבנייה נכונה. יכולים לעבור חודשים עד שצוות ייעודי יצליח להגדיר את העיכובים, את הטיפול באירועים ואת התמיכה בהתאמה רחבה בצורה נכונה. אבל אנחנו עובדים על פתרון הצהרתי חדש שאמור לפתור את הבעיה הזו אחת ולתמיד.
חלונות קופצים שמופעלים על סמך תחומי עניין עם [interestfor]
הקסם העיקרי שמאחורי כרטיסי מידע הצהרתיים הוא מאפיין[interestfor]. התכונה הזו, שעתידה לצאת בקרוב, מביאה את העוצמה של חלונות קופצים, אבל מפעילה אותם על סמך 'התעניינות' של המשתמש. לדוגמה, התעניינות של משתמש במכשיר הצבעה תהיה הצבעה עם העכבר, ניווט באמצעות מקש Tab במקלדת או לחיצה ארוכה או הקשה על מסכי מגע. האינטראקציה בנייד עדיין לא נפתרה.
כדי להמיר חלון קופץ מבוסס-קליקים לחלון קופץ מבוסס-תחומי עניין, צריך ליצור רכיב הפעלה, שיכול להיות <button> או <a>, ולהקצות לו מאפיין [interestfor] ששווה ל-id של הרכיב [popover]. כך זה נראה ב-HTML:
<button interestfor="profile-callout">
...
</button>
<div id="profile-callout" popover>
...
</div>
הדפדפן מטפל בכל הלוגיקה המורכבת של האירועים, כולל:
- אירועי כניסה ויציאה: מעבר עם העכבר מעל רכיב במכשירים עם מצביע מדויק, ניווט באמצעות מקש Tab במקלדת, לחיצה ארוכה או מגע במכשירים עם מצביע גס.
- השהיות של אירועים: אפשר לשלוט בהשהיות של כניסה ויציאה באמצעות מאפיין CSS יחיד.
התכונה הזו תומכת בתכונות אחרות של חלונות קופצים, כמו תמיכה בשכבה העליונה, שבה החלון הקופץ מוצג בשכבה חדשה מעל שאר עץ ה-DOM. הקישורים של רכיבי ה-semantics ומודל עץ הנגישות הבסיסי מטופלים באופן מקורי.
אמצעי הפעלה של סגנונות
הפעלת נושאים של התעניינות כוללת כמה יכולות חדשות. אחת מהן היא היכולת לשלוט בעיכובים בכניסה וביציאה באמצעות מאפיין CSS: interest-target-delay. השנייה היא היכולת להגדיר סגנון לרכיב ההפעלה בהתאם לשאלה אם יש בו נושא התעניינות או לא, באמצעות פסאודו-מחלקה :has-interest.
[interesttarget] {
interest-target-delay: 0s 1s;
&:has-interest {
background: yellow;
}
}
popover="hint" וממשק משתמש רב-תכליתי
חלק חשוב בפאזל של רכיבי ההפעלה של נושאים הוא סוג חדש של חלון קופץ: popover="hint". ההבדל העיקרי בינו לבין חלונות קופצים אחרים הוא שחלון קופץ של רמז לא סוגר חלונות קופצים אחרים כשהוא נפתח. זה מושלם לתיאורי כלים או לכרטיסי תצוגה מקדימה שצריכים להופיע בלי לסגור תפריט או חלון צ'אט שכבר פתוחים.
Browser Support
popover=auto | popover=manual | popover=hint | |
|---|---|---|---|
סגירה מהירה (באמצעות קליק מחוץ לחלון או מקש esc) | כן | לא | כן |
סגירה של רכיבי popover=auto אחרים כשהרכיב נפתח | כן | לא | לא |
סגירה של רכיבי popover=hint אחרים כשהרכיב נפתח | כן | לא | כן |
סגירה של רכיבי popover=manual אחרים כשהרכיב נפתח | לא | לא | לא |
אפשר לפתוח ולסגור את ה-popover באמצעות JS (showPopover() או hidePopover()) | כן | כן | כן |
| ניהול ברירת המחדל של המיקוד לנקודת עצירה הבאה של הכרטיסייה | כן | כן | כן |
אפשר להסתיר או להחליף עם popovertargetaction | כן | כן | כן |
אפשר לפתוח בתוך ההורה popover כדי שההורה יישאר פתוח | כן | כן | כן |
כך תוכלו ליצור ממשק משתמש רב-עוצמה ורב-תכליתי באופן הצהרתי. מעכשיו אפשר להגדיר לחצן יחיד עם חלון קופץ אוטומטי באמצעות popovertarget לפעולת הקליק העיקרית שלו (למשל, פתיחת חלונית ההתראות) וגם חלון קופץ עם רמז להפעלת עניין כדי להציג תיאור כלי מועיל כשמעבירים את מצביע העכבר מעל הלחצן.
העתיד הוא הצהרתי
התכונות שמתוארות כאן מייצגות שינוי מהותי לעבר פלטפורמת אינטרנט חזקה יותר ודקלרטיבית יותר. הדפדפן מטפל בעבודה המורכבת והחוזרת על עצמה של ניהול מצב ונגישות, ולכן אנחנו יכולים להסיר כמויות גדולות של JavaScript, לשפר את הביצועים ולהתמקד במה שאנחנו עושים הכי טוב: יצירת חוויות משתמש חדשניות ומושכות. אנחנו נמצאים בתקופה שבה ממש קל ליצור ממשקי משתמש לאינטרנט, וזו רק ההתחלה. אתם יכולים לעקוב אחרינו כאן בזמן שאנחנו עובדים על בניית אינטרנט חזק יותר ונגיש יותר.
מקורות מידע נוספים: