לאחרונה נוספה תמיכה יציבה בכל מנועי הדפדפנים המודרניים ביכולת לשלוח שאילתות לגבי הגודל של הרכיב הראשי בקוד, וגם לגבי ערכי יחידות השאילתה של מאגרים.
עם זאת, מפרט ההכללה כולל יותר משאילתות לגבי גודל. הוא מאפשר גם לשלוח שאילתות לגבי ערכי הסגנון של הורה. החל מגרסה 111 של Chromium, תוכלו להחיל אילוץ סגנון על ערכי מאפיינים מותאמים אישית ולבצע שאילתה לרכיב הורה לגבי הערך של מאפיין מותאם אישית.
המשמעות היא שיש לנו שליטה לוגית רבה יותר בסגנונות ב-CSS, ואפשר להפריד טוב יותר בין הלוגיקה של האפליקציה ושכבת הנתונים שלה לבין הסגנונות שלה.
המפרט של מודול הכליאת של CSS ברמה 3, שכולל שאילתות לגבי גודל וסגנון, מאפשר לשלוח שאילתות לגבי כל סגנון מהאב, כולל זוגות של נכס וערך כמו font-weight: 800
. עם זאת, במהלך ההשקה של התכונה הזו, שאילתות סגנון פועלות כרגע רק עם ערכי מאפיינים מותאמים אישית של CSS. השיטה הזו עדיין שימושית מאוד לשילוב סגנונות ולהפרדת נתונים מעיצוב. נראה איך משתמשים בשאילתות סגנון עם מאפיינים מותאמים אישית של CSS:
תחילת העבודה עם שאילתות סגנון
נניח שיש לנו את הקוד הבא ב-HTML:
<ul class="card-list">
<li class="card-container">
<div class="card">
...
</div>
</li>
</ul>
כדי להשתמש בשאילתות סגנון, קודם צריך להגדיר רכיב מאגר. לשם כך, צריך להשתמש בגישה שונה במקצת בהתאם לשאלה אם שולחים שאילתה להורה ישיר או עקיף.
שליחת שאילתות להורים ישירים
בניגוד לשאילתות סגנון, אין צורך להחיל את המגבלה באמצעות המאפיין container-type
או container
על .card-container
כדי ש-.card
יוכל לשלוח שאילתות לגבי הסגנונות של ההורה הישיר שלו. עם זאת, אנחנו צריכים להחיל את הסגנונות (ערכים של מאפיינים מותאמים אישית במקרה הזה) על מאגר (.card-container
במקרה הזה) או על כל אלמנט שמכיל את הרכיב שאנחנו מחילים עליו סגנון ב-DOM. אנחנו לא יכולים להחיל סגנונות שאנחנו שולחים עליהם שאילתה על האלמנט הישיר שאנחנו מעצבים באמצעות השאילתה הזו, כי זה עלול לגרום ללופים אינסופיים.
כדי לשלוח שאילתה ישירות להורה, אפשר לכתוב:
/* styling .card based on the value of --theme on .card-container */
@container style(--theme: warm) {
.card {
background-color: wheat;
border-color: brown;
...
}
}
יכול להיות ששמתם לב ששאילתת הסגנון עוטפת את השאילתה ב-style()
. המטרה היא להבדיל בין ערכי המידה לבין הסגנונות. לדוגמה, אפשר לכתוב שאילתה לגבי רוחב המאגר כ-@container (min-width: 200px) { … }
. הסגנונות יחולו אם מאגר האב יהיה ברוחב של 200 פיקסלים לפחות. עם זאת, min-width
יכול להיות גם מאפיין CSS, ואפשר להריץ שאילתה לגבי הערך של min-width
ב-CSS באמצעות שאילתות סגנון. לכן כדאי להשתמש ב-wrapper של style()
כדי להבהיר את ההבדל: @container style(min-width: 200px) { … }
.
עיצוב של רכיבי הורה לא ישירים
אם רוצים לשלוח שאילתה לגבי סגנונות של רכיב שאינו הורה ישיר, צריך להקצות לרכיב הזה container-name
. לדוגמה, אפשר להחיל סגנונות על .card
על סמך הסגנונות של .card-list
על ידי הקצאת container-name
ל-.card-list
והפניה אליו בשאילתת הסגנון.
/* styling .card based on the value of --moreGlobalVar on .card-list */
@container cards style(--moreGlobalVar: value) {
.card {
...
}
}
באופן כללי, מומלץ לתת שמות לקונטיינרים כדי להבהיר על מה אתם שולחים שאילתה ולאפשר גישה לקונטיינרים האלה בקלות רבה יותר. דוגמה אחת למקרה שבו האפשרות הזו שימושית היא אם רוצים להגדיר סגנון לאלמנטים ב-.card
ישירות. בלי קונטיינר בעל שם ב-.card-container
, הם לא יכולים לשלוח שאילתה ישירות אליו.
אבל כל זה ברור הרבה יותר בפועל. ריכזנו כאן כמה דוגמאות:
שאילתות סגנון בפעולה
שאילתות סגנון שימושיות במיוחד כשיש לכם רכיב לשימוש חוזר עם כמה וריאציות, או כשאין לכם שליטה על כל הסגנונות אבל אתם צריכים להחיל שינויים במקרים מסוימים. בדוגמה הזו מוצגת קבוצה של כרטיסי מוצרים שיש להם את אותו רכיב כרטיס. בכרטיסי מוצרים מסוימים מופיעים פרטים או הערות נוספים, כמו 'חדש' או 'מלאי נמוך', שמופעל על ידי מאפיין מותאם אישית בשם --detail
. בנוסף, אם המוצר נמצא בסטטוס 'מלאי נמוך', הוא מופיע עם רקע של גבול אדום כהה. סביר להניח שהמידע מהסוג הזה עובר עיבוד בשרת, וניתן להחיל אותו על הכרטיסים באמצעות סגנונות בתוך שורות, כך:
<div class="product-list">
<div class="product-card-container" style="--detail: new">
<div class="product-card">
<div class="media">
<img .../>
<div class="comment-block"></div>
</div>
</div>
<div class="meta">
...
</div>
</div>
<div class="product-card-container" style="--detail: low-stock">
...
</div>
<div class="product-card-container">
...
</div>
...
</div>
בעזרת הנתונים המובְנים האלה, אפשר להעביר ערכים אל --detail
ולהשתמש במאפיין ה-CSS המותאם אישית הזה כדי להחיל את הסגנונות:
@container style(--detail: new) {
.comment-block {
display: block;
}
.comment-block::after {
content: 'New';
border: 1px solid currentColor;
background: white;
...
}
}
@container style(--detail: low-stock) {
.comment-block {
display: block;
}
.comment-block::after {
content: 'Low Stock';
border: 1px solid currentColor;
background: white;
...
}
.media-img {
border: 2px solid brickred;
}
}
הקוד שלמעלה מאפשר לנו להחיל צ'יפ על --detail: low-stock
ו---detail: new
, אבל יכול להיות ששמתם לב למיותר מסוים בקוד. נכון לעכשיו, אין אפשרות להריץ שאילתות רק על נוכחות של --detail
עם @container style(--detail)
, מה שיאפשר שיתוף יעיל יותר של סגנונות ופחות חזרות. היכולת הזו נמצאת כרגע בבדיקה בקבוצת העבודה.
כרטיסי מזג אוויר
בדוגמה הקודמת השתמשנו במאפיין מותאם אישית אחד עם כמה ערכים אפשריים כדי להחיל סגנונות. אבל אפשר גם לשלב בין כמה נכסים מותאמים אישית ולהשתמש בהם ובשאילתות לגביהם. בדוגמה הבאה של כרטיס מזג האוויר:
כדי לקבוע את הסגנון של סמלי הרקע והפסים בצבעים משתנים בכרטיסים האלה, מחפשים מאפייני מזג אוויר כמו 'מעונן', 'גשום' או 'שמשי':
@container style(--sunny: true) {
.weather-card {
background: linear-gradient(-30deg, yellow, orange);
}
.weather-card:after {
content: url(<data-uri-for-demo-brevity>);
background: gold;
}
}
כך תוכלו לעצב כל כרטיס בהתאם למאפיינים הייחודיים שלו. אבל אפשר גם להגדיר סגנון לשילובים של מאפיינים (מאפיינים מותאמים אישית) באמצעות הקומבינטור and
, באותו אופן שבו משתמשים בו בשאילתות מדיה. לדוגמה, יום שהוא גם מעונן וגם שמשי ייראה כך:
@container style(--sunny: true) and style(--cloudy: true) {
.weather-card {
background: linear-gradient(24deg, pink, violet);
}
.weather-card:after {
content: url(<data-uri-for-demo-brevity>);
background: violet;
}
}
הפרדת נתונים מהעיצוב
בשני הדמואים האלה, יש יתרון מבני בהפרדה בין שכבת הנתונים (DOM שיומר בדף) לבין הסגנונות שחלים. הסגנונות נכתבים כאפשרויות שונות שקיימות בסגנון הרכיבים, ואילו נקודת קצה יכולה לשלוח את הנתונים שבהם היא תשתמש כדי להגדיר את הסגנון של הרכיב. אפשר להשתמש בערך יחיד, כמו במקרה הראשון, ולעדכן את הערך --detail
, או במספר משתנים, כמו במקרה השני (הגדרת --rainy
או --cloudy
או --sunny
. והחלק הכי טוב הוא שאפשר גם לשלב את הערכים האלה. בדיקה של --sunny
וגם של --cloudy
עשויה להציג סגנון של 'חלקית מעונן'.
אפשר לעדכן את ערכי המאפיינים בהתאמה אישית באמצעות JavaScript בצורה חלקה, גם בזמן הגדרת מודל ה-DOM (כלומר בזמן פיתוח הרכיב במסגרת) וגם בכל שלב באמצעות <parentElem>.style.setProperty('--myProperty’, <value>)
. I
הנה דוגמה שבה כמה שורות קוד מעדכנות את --theme
של לחצן ומחילות סגנונות באמצעות שאילתות סגנון והמאפיין המותאם אישית הזה (--theme
):
מעצבים את הכרטיס באמצעות שאילתות סגנון. קוד ה-JavaScript שמשמש לעדכון הערכים של המאפיינים המותאמים אישית הוא:
const themePicker = document.querySelector('#theme-picker')
const btnParent = document.querySelector('.btn-section');
themePicker.addEventListener('input', (e) => {
btnParent.style.setProperty('--theme', e.target.value);
})
התכונות שמפורטות במאמר הזה הן רק ההתחלה. שאילתות בקונטיינרים יכולות לעזור לכם ליצור ממשקים דינמיים ורלוונטיים. ספציפית לשאילתות סגנון, עדיין יש כמה בעיות פתוחות. אחת מהן היא הטמעת שאילתות סגנון לסגנונות CSS מעבר למאפיינים מותאמים אישית. האפשרות הזו כבר כלולה ברמת המפרט הנוכחית, אבל עדיין לא הופעלה באף דפדפן. הערכת ההקשר הבוליאני צפויה להתווסף לרמת המפרט הנוכחית אחרי פתרון הבעיה הקיימת, ואילו שאילתות טווח מתוכננות לרמה הבאה של המפרט.