תחילת העבודה עם שאילתות סגנון

היכולת להריץ שאילתות על גודל שורה של הורה וערכי יחידות של שאילתות קונטיינרים השיגה לאחרונה תמיכה יציבה בכל מנועי הדפדפנים המודרניים.

תמיכה בדפדפן

  • 105
  • 105
  • 110
  • 16

מקור

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

תמיכה בדפדפן

  • 111
  • 111
  • x
  • x

מקור

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

המפרט של CSS Containment Module Level 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, ואתם יכולים לשלוח שאילתה על ערך ה-CSS של min-width באמצעות שאילתות סגנון. לכן צריך להשתמש ב-wrapper של style() כדי להבהיר את ההבדל: @container style(min-width: 200px) { … }.

עיצוב של הורים לא ישירים

אם רוצים להריץ שאילתה על סגנונות של רכיב כלשהו שאינו הורה ישיר, צריך לתת לרכיב הזה container-name. לדוגמה, אפשר להחיל סגנונות על .card על סמך הסגנונות של .card-list. לשם כך, נותנים ל-.card-list את הערך container-name, ומפנים אליו בשאילתת הסגנון.

/* styling .card based on the value of --moreGlobalVar on .card-list */
@container cards style(--moreGlobalVar: value) {
  .card {
    ...
  }
}

באופן כללי, מומלץ לתת למאגרי התגים שמות כדי שיהיה ברור מה השאילתה וכדי לאפשר גישה קלה יותר לקונטיינרים האלה. דוגמה אחת לאפשרות הזו היא אם רוצים לעצב רכיבים ישירות בתוך .card. בלי מאגר תגים בעל שם ב-.card-container, הם לא יכולים להריץ עליו שאילתות ישירות.

אבל בפועל, הרבה יותר הגיוני. דוגמאות:

עיצוב שאילתות בפעולה

תמונת הדגמה עם מספר כרטיסי מוצר, חלקם עם תגים מסוג &#39;חדש&#39; או &#39;מלאי נמוך&#39; והכרטיס &#39;מלאי נמוך&#39; עם רקע אדום.

שאילתות סגנון שימושיות במיוחד כאשר יש רכיב לשימוש חוזר עם מספר וריאציות, או כאשר אין לכם שליטה על כל הסגנונות אבל אתם צריכים להחיל שינויים במקרים מסוימים. בדוגמה הזו מוצגת קבוצה של כרטיסי מוצרים עם אותו רכיב בכרטיס. בחלק מכרטיסי המוצרים יש הערות או פרטים נוספים, כמו 'חדש' או 'מלאי נמוך', שמופעלים על ידי נכס מותאם אישית בשם --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 (כלומר, בזמן בניית הרכיב ב-framework), או לעדכן אותו בכל שלב באמצעות <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 מעבר לנכסים מותאמים אישית. זה כבר חלק מרמת המפרט הנוכחית, אבל הוא עדיין לא מוטמע באף דפדפן. הערכת ההקשר הבוליאנית צפויה להתווסף לרמת המפרט הנוכחית לאחר פתרון הבעיה שנשארה, ואילו הרצת שאילתות טווח מתוכננת לרמת המפרט הבאה.