المساعدة في اختيار بنية لتداخل CSS

هناك صيغتان متنافستان تحتاجان إلى مساعدتك في تحديد الصيغة التي يجب الترويج لها لتصبح مرشّحة للمواصفات.

تتيح إضافة بنية 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. التحليل اللغوي الغامض
    يمكن أن تبدو بعض أدوات الاختيار المتداخلة تمامًا مثل الخصائص والمعالجات المسبقة وتكون قادرة على حلّها وإدارتها في وقت الإنشاء. لن تتوفّر الإمكانات نفسها في محركات المتصفحات، ويجب ألا يتم تفسير أدوات الاختيار بشكل غير دقيق مطلقًا.

  2. تعارضات تحليل المعالجة المسبقة
    يجب ألا يؤدي أسلوب التداخل في CSS إلى تعطيل المعالجات المسبقة أو سير عمل التداخل الحالي للمطوّرين. سيؤدي ذلك إلى إزعاج هذه الأنظمة المتكاملة والمنتديات وعدم مراعاة احتياجاتها.

  3. في انتظار :is()
    لا يتطلّب التداخل الأساسي :is()، ولكنّه ضروري للتداخل الأكثر تعقيدًا. راجِع المثال رقم 3 للحصول على مقدّمة بسيطة حول قوائم أدوات الاختيار والدمج. لنفترض أنّ قائمة أدوات الاختيار هذه كانت في منتصف أداة اختيار بدلاً من بدايتها، في هذه الحالات، يكون الرمز :is() مطلوبًا من أجل تجميع أدوات الاختيار في منتصف أداة اختيار أخرى.

نظرة عامة على ما نقارنه

نريد أن نضمن أنّ ميزة التداخل في CSS تعمل على أكمل وجه، لذا سنشارك المجتمع في هذه العملية. ستساعد الأقسام التالية في وصف الإصدارات الثلاثة المحتملة التي نقيّمها. بعد ذلك، سنستعرض بعض الأمثلة على الاستخدام للمقارنة، وفي النهاية، سيظهر استطلاع بسيط يسألك عن الخيار الذي تفضّله بشكل عام.

الخيار 1: @nest

هذه هي البنية المحدّدة الحالية في CSS Nesting 1. توفّر هذه الطريقة وسيلة سهلة لتضمين أنماط الإلحاق من خلال بدء أدوات اختيار جديدة مضمّنة باستخدام &. توفّر هذه الميزة أيضًا @nest كطريقة لوضع سياق & في أي مكان داخل أداة اختيار جديدة، مثلاً عندما لا تكون بصدد إضافة مواضيع فقط. وهي مرنة وبسيطة، ولكنها تتطلّب تذكُّر @nest أو & حسب حالة الاستخدام.

الخيار 2: @nest restricted

هذا بديل أكثر صرامة، وذلك في محاولة لتقليل العبء المذكور بشأن تذكُّر طريقتَي تضمين. لا تسمح هذه البنية المحظورة بالتداخل إلا بعد @nest، لذا لا يتوفّر نمط مناسب للإضافة فقط. إزالة الغموض بشأن الخيار، وإنشاء طريقة واحدة سهلة التذكّر للتداخل، ولكن مع التضحية بالاختصار لصالح الاتفاقية

الخيار 3: الأقواس

لتجنُّب استخدام الصيغة المزدوجة أو التشويش الإضافي الناتج عن اقتراحات @nest، اقترحت ميريام سوزان وإليكا اعتماد صيغة بديلة تعتمد على أقواس معقوفة إضافية. يوفّر ذلك وضوحًا في بنية الجملة، مع حرفين إضافيين فقط، وبدون قواعد جديدة تبدأ بعلامة @. ويسمح أيضًا بتجميع القواعد المدمَجة حسب نوع الدمج المطلوب، وذلك بهدف تبسيط عدة محدّدات مدمَجة بشكل مشابه.

المثال 1: التضمين المباشر

@nest

.foo {
  color: #111;

  & .bar {
    color: #eee;
  }
}

‎@nest always

.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 always

.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 always

.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 always

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 always

.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 always

.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 always

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 always

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" لتصبح بنية مألوفة ومحبّبة للجميع.

المشاركة في الاستطلاع