איך בוחרים תחביר לקינון CSS

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

Adam Argyle
Adam Argyle
Miriam Suzanne
Miriam Suzanne

עיבוי CSS הוא תוספת נוחה לתחביר שמאפשרת להוסיף CSS בתוך קבוצת כללים. אם השתמשתם ב-SCSS, ב-Less או ב-Stylus, סביר להניח שתראו כמה גרסאות של הקוד הזה:

.nesting {
  color: hotpink;

  > .is {
    color: rebeccapurple;

    > .awesome {
      color: deeppink;
    }
  }
}

לאחר הידור ל-CSS רגיל על ידי המהדר, הקוד הופך ל-CSS רגיל באופן הבא:

.nesting {
  color: hotpink;
}

.nesting > .is {
  color: rebeccapurple;
}

.nesting > .is > .awesome {
  color: deeppink;
}

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

למה הדוגמה המדויקת להטמעה בתוך הטמעה שמוצגת למעלה לא יכולה להיות התחביר להטמעה בתוך הטמעה ב-CSS?

יש כמה סיבות לכך שלא ניתן להשתמש בתחביר ההטמעה הנפוץ ביותר כפי שהוא:

  1. ניתוח לא ברור
    חלק מהבוררים בתצוגת עץ יכולים להיראות בדיוק כמו נכסים, ועיבוד מקדים יכול לפתור אותם ולנהל אותם בזמן ה-build. למנועי הדפדפנים לא יהיו אותן יכולות, ולכן אסור לפרש את הבוררים באופן רופף.

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

  3. Waiting for :is()
    לא צריך את :is() להטמעה בסיסית, אבל צריך אותה להטמעה מורכבת יותר. בדוגמה מס' 3 מופיעה מבוא קצר לרשימות של בוחרים ולעיצוב בתוך עיצוב. נניח שרשימה של בוררים הייתה באמצע בורר במקום בהתחלה. במקרים כאלה, צריך להשתמש ב-:is() כדי לקבץ את הבוררים באמצע בורר אחר.

סקירה כללית של הנתונים שאנחנו משווים

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

אפשרות 1: ‏@nest

זהו התחביר שצוין כרגע ב-CSS Nesting 1. היא מספקת דרך נוחה להטמיע סגנונות להוספה על ידי התחלת בוררים חדשים בתצוגת עץ עם &. הוא גם מציע את @nest כדרך למקם את ההקשר של & בכל מקום בתוך בורר חדש, למשל כשלא רק מצרפים נושאים. הפתרון הזה גמיש ומינימלי, אבל צריך לזכור את @nest או &, בהתאם לתרחיש לדוגמה.

אפשרות 2: @nest restricted

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

אפשרות 3: סוגריים

כדי להימנע מהסינטקס הכפול או מהעומס הנוסף שמאפיין את ההצעות ל-@nest, Miriam Suzanne ו-Elika Etemad הציעו סינטקס חלופי שמבוסס על סוגריים מסולסלים נוספים. כך אפשר לכתוב את התחביר בצורה ברורה, עם שני תווים נוספים בלבד, בלי כללי at-rule חדשים. הוא גם מאפשר לקבץ כללים בתצוגת עץ לפי סוג ההטמעה הנדרש, כדי לפשט מספר בוחרים בתצוגת עץ דומה.

דוגמה 1 – עץ ישיר

‎@nest

.foo {
  color: #111;

  & .bar {
    color: #eee;
  }
}

@nest תמיד

.foo {
  color: #111;

  @nest & .bar {
    color: #eee;
  }
}

סוגריים

.foo {
  color: #111;

  {
    & .bar {
      color: #eee;
    }
  }
}

CSS שווה ערך

.foo {
  color: #111;
}

.foo .bar {
  color: #eee;
}

דוגמה 2 – עיטוף מורכב

‎@nest

.foo {
  color: blue;

  &.bar {
    color: red;
  }
}

@nest תמיד

.foo {
  color: blue;

  @nest &.bar {
    color: red;
  }
}

סוגריים

.foo {
  color: blue;

  {
    &.bar {
      color: red;
    }
  }
}

CSS שווה ערך

.foo {
  color: blue;
}

.foo.bar {
  color: red;
}

דוגמה 3 – רשימות של בוחרים והטמעה בתוך רשימה

‎@nest

.foo, .bar {
  color: blue;

  & + .baz,
  &.qux {
    color: red;
  }
}

@nest תמיד

.foo, .bar {
  color: blue;

  @nest & + .baz,
  &.qux {
    color: red;
  }
}

סוגריים

.foo, .bar {
  color: blue;

  {
    & + .baz,
    &.qux {
      color: red;
    }
  }
}

CSS שווה ערך

.foo, .bar {
  color: blue;
}

:is(.foo, .bar) + .baz,
:is(.foo, .bar).qux {
  color: red;
}

דוגמה 4 – כמה רמות

‎@nest

figure {
  margin: 0;

  & > figcaption {
    background: lightgray;

    & > p {
      font-size: .9rem;
    }
  }
}

@nest תמיד

figure {
  margin: 0;

  @nest & > figcaption {
    background: lightgray;

    @nest & > p {
      font-size: .9rem;
    }
  }
}

סוגריים

figure {
  margin: 0;

  {
    & > figcaption {
      background: lightgray;

      {
        & > p {
          font-size: .9rem;
        }
      }
    }
  }
}

CSS שווה ערך

figure {
  margin: 0;
}

figure > figcaption {
  background: hsl(0 0% 0% / 50%);
}

figure > figcaption > p {
  font-size: .9rem;
}

דוגמה 5 – עץ הורה או שינוי הנושא

‎@nest

.foo {
  color: red;

  @nest .parent & {
    color: blue;
  }
}

@nest תמיד

.foo {
  color: red;

  @nest .parent & {
    color: blue;
  }
}

סוגריים

.foo {
  color: red;

  {
    .parent & {
      color: blue;
    }
  }
}

CSS שווה ערך

.foo {
  color: red;
}

.parent .foo {
  color: blue;
}

דוגמה 6 – שילוב של עץ עץ ישיר עם עץ הורה

‎@nest

.foo {
  color: blue;

  @nest .bar & {
    color: red;

    &.baz {
      color: green;
    }
  }
}

@nest תמיד

.foo {
  color: blue;

  @nest .bar & {
    color: red;

    @nest &.baz {
      color: green;
    }
  }
}

סוגריים

.foo {
  color: blue;

  {
    .bar & {
      color: red;

      {
        &.baz {
          color: green;
        }
      }
    }
  }
}

CSS שווה ערך

.foo {
  color: blue;
}

.bar .foo {
  color: red;
}

.bar .foo.baz {
  color: green;
}

דוגמה 7 – עיבוי של שאילתות מדיה

‎@nest

.foo {
  display: grid;

  @media (width => 30em) {
    grid-auto-flow: column;
  }
}

או באופן מפורש / מורחב

.foo {
  display: grid;

  @media (width => 30em) {
    & {
      grid-auto-flow: column;
    }
  }
}

@nest always (תמיד מפורש)

.foo {
  display: grid;

  @media (width => 30em) {
    @nest & {
      grid-auto-flow: column;
    }
  }
}

סוגריים

.foo {
  display: grid;

  @media (width => 30em) {
    grid-auto-flow: column;
  }
}

או באופן מפורש / מורחב

.foo {
  display: grid;

  @media (width => 30em) {
    & {
      grid-auto-flow: column;
    }
  }
}

CSS שווה ערך

.foo {
  display: grid;
}

@media (width => 30em) {
  .foo {
    grid-auto-flow: column;
  }
}

דוגמה 8 – קבוצות עץ

‎@nest

fieldset {
  border-radius: 10px;

  &:focus-within {
    border-color: hotpink;
  }

  & > legend {
    font-size: .9em;
  }

  & > div {
    & + div {
      margin-block-start: 2ch;
    }

    & > label {
      line-height: 1.5;
    }
  }
}

@nest תמיד

fieldset {
  border-radius: 10px;

  @nest &:focus-within {
    border-color: hotpink;
  }

  @nest & > legend {
    font-size: .9em;
  }

  @nest & > div {
    @nest & + div {
      margin-block-start: 2ch;
    }

    @nest & > label {
      line-height: 1.5;
    }
  }
}

סוגריים

fieldset {
  border-radius: 10px;

  {
    &:focus-within {
      border-color: hotpink;
    }
  }

  > {
    legend {
      font-size: .9em;
    }

    div {
      + div {
        margin-block-start: 2ch;
      }

      > label {
        line-height: 1.5;
      }
    }}
  }
}

CSS שווה ערך

fieldset {
  border-radius: 10px;
}

fieldset:focus-within {
  border-color: hotpink;
}

fieldset > legend {
  font-size: .9em;
}

fieldset > div + div {
  margin-block-start: 2ch;
}

fieldset > div > label {
  line-height: 1.5;
}

דוגמה 9 – קבוצת עץ מורכבת 'כל מה שאפשר'

‎@nest

dialog {
  border: none;

  &::backdrop {
    backdrop-filter: blur(25px);
  }

  & > form {
    display: grid;

    & > :is(header, footer) {
      align-items: flex-start;
    }
  }

  @nest html:has(&[open]) {
    overflow: hidden;
  }
}

@nest תמיד

dialog {
  border: none;

  @nest &::backdrop {
    backdrop-filter: blur(25px);
  }

  @nest & > form {
    display: grid;

    @nest & > :is(header, footer) {
      align-items: flex-start;
    }
  }

  @nest html:has(&[open]) {
    overflow: hidden;
  }
}

סוגריים

dialog {
  border: none;

  {
    &::backdrop {
      backdrop-filter: blur(25px);
    }

    & > form {
      display: grid;

      {
        & > :is(header, footer) {
          align-items: flex-start;
        }
      }
    }
  }

  {
    html:has(&[open]) {
      overflow: hidden;
    }
  }
}

CSS שווה ערך

dialog {
  border: none;
}

dialog::backdrop {
  backdrop-filter: blur(25px);
}

dialog > form {
  display: grid;
}

dialog > form > :is(header, footer) {
  align-items: flex-start;
}

html:has(dialog[open]) {
  overflow: hidden;
}

הגיע הזמן להצביע

אני מקווה שההשוואה הזו סיפקה לך תמונה מלאה של אפשרויות התחביר שאנחנו בוחנים. עליך לקרוא אותן בעיון ולציין את האפשרות המועדפת עליך בהמשך. תודה שעזרת לנו לשפר את ההטמעה של CSS בתחביר שכולנו נכיר ונאהב.

להשתתפות בסקר