Giúp chọn cú pháp để lồng CSS

Hai cú pháp cạnh tranh cần sự trợ giúp của bạn trong việc xác định cú pháp nào sẽ được đề xuất cho một đề xuất đặc tả.

Tính năng lồng CSS là một tiện ích bổ sung cú pháp thuận tiện, cho phép thêm CSS vào bên trong một bộ quy tắc. Nếu đã sử dụng SCSS, Less hoặc Stylus, thì chắc chắn bạn đã thấy một vài phiên bản của quy tắc này:

.nesting {
  color: hotpink;

  > .is {
    color: rebeccapurple;

    > .awesome {
      color: deeppink;
    }
  }
}

Sau khi được trình tiền xử lý biên dịch thành CSS thông thường, CSS này sẽ chuyển thành CSS thông thường như sau:

.nesting {
  color: hotpink;
}

.nesting > .is {
  color: rebeccapurple;
}

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

Chúng tôi đang cân nhắc kỹ lưỡng việc sử dụng phiên bản CSS chính thức của cú pháp này và có sự phân chia về lựa chọn ưu tiên. Vì vậy, chúng tôi muốn nhờ cộng đồng giúp chúng tôi đưa ra quyết định cuối cùng. Phần còn lại của bài đăng này sẽ giới thiệu các lựa chọn về cú pháp để bạn có thể nắm được thông tin và tham gia khảo sát ở cuối bài.

Tại sao ví dụ chính xác về việc lồng ở trên không thể là cú pháp cho việc lồng CSS?

Có một số lý do khiến bạn không thể sử dụng cú pháp lồng ghép phổ biến nhất như hiện tại:

  1. Phân tích cú pháp không rõ ràng
    Một số bộ chọn lồng nhau có thể trông giống hệt như các thuộc tính và trình tiền xử lý có thể phân giải và quản lý chúng tại thời điểm tạo. Các công cụ trình duyệt sẽ không có cùng các khả năng, bộ chọn không bao giờ được diễn giải một cách lỏng lẻo.

  2. Xung đột khi phân tích cú pháp tiền xử lý
    Cách lồng CSS không được làm hỏng các tiền xử lý hoặc quy trình lồng hiện có của nhà phát triển. Điều này sẽ gây phiền toái và thiếu tôn trọng đối với những hệ sinh thái và cộng đồng đó.

  3. Đang chờ :is()
    Việc lồng cơ bản không cần :is() nhưng việc lồng phức tạp hơn thì cần. Hãy xem Ví dụ 3 để biết thông tin giới thiệu sơ lược về danh sách bộ chọn và việc lồng ghép. Hãy tưởng tượng rằng danh sách bộ chọn nằm ở giữa một bộ chọn thay vì ở đầu. Trong những trường hợp đó, bạn cần có :is() để nhóm các bộ chọn ở giữa một bộ chọn khác.

Tổng quan về những điểm chúng tôi so sánh

Chúng tôi muốn triển khai đúng tính năng lồng CSS và vì vậy, chúng tôi sẽ mời cộng đồng tham gia. Các phần sau đây sẽ giúp mô tả 3 phiên bản có thể có mà chúng tôi đang đánh giá. Sau đó, chúng ta sẽ xem xét một số ví dụ về cách sử dụng để so sánh và ở cuối sẽ có một bản khảo sát ngắn hỏi bạn thích cách nào hơn.

Cách 1: @nest

Đây là cú pháp được chỉ định hiện tại trong CSS Nesting 1. Công cụ này cung cấp một cách thuận tiện để lồng các kiểu nối bằng cách bắt đầu các bộ chọn lồng mới bằng &. Thao tác này cũng cung cấp @nest như một cách để đặt ngữ cảnh & ở bất kỳ đâu bên trong một bộ chọn mới, chẳng hạn như khi bạn không chỉ nối các đối tượng. Phương thức này linh hoạt và tối giản nhưng bạn cần nhớ @nest hoặc & tuỳ thuộc vào trường hợp sử dụng của bạn.

Cách 2: @nest restricted

Đây là một lựa chọn thay thế nghiêm ngặt hơn, nhằm mục đích giảm chi phí đã đề cập khi ghi nhớ hai phương pháp lồng nhau. Cú pháp bị hạn chế này chỉ cho phép lồng ghép xảy ra sau @nest, nên không có mẫu tiện lợi chỉ cho phép nối. Loại bỏ sự mơ hồ của lựa chọn, tạo ra một cách dễ nhớ để lồng ghép, nhưng hy sinh sự súc tích để tuân theo quy ước.

Cách 3: Dấu ngoặc

Để tránh cú pháp kép hoặc sự lộn xộn không cần thiết liên quan đến các đề xuất @nest, Miriam SuzanneElika Etemad đã đề xuất một cú pháp thay thế dựa trên các dấu ngoặc nhọn bổ sung. Điều này giúp cú pháp rõ ràng hơn, chỉ có thêm 2 ký tự và không có quy tắc @ mới. Tính năng này cũng cho phép nhóm các quy tắc lồng ghép theo loại lồng ghép bắt buộc, như một cách đơn giản hoá nhiều bộ chọn được lồng ghép tương tự.

Ví dụ 1 – Lồng trực tiếp

@nest

.foo {
  color: #111;

  & .bar {
    color: #eee;
  }
}

@nest always

.foo {
  color: #111;

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

dấu ngoặc

.foo {
  color: #111;

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

Dịch vụ so sánh giá (CSS) tương đương

.foo {
  color: #111;
}

.foo .bar {
  color: #eee;
}

Ví dụ 2: Lồng ghép phức tạp

@nest

.foo {
  color: blue;

  &.bar {
    color: red;
  }
}

@nest always

.foo {
  color: blue;

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

dấu ngoặc

.foo {
  color: blue;

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

Dịch vụ so sánh giá (CSS) tương đương

.foo {
  color: blue;
}

.foo.bar {
  color: red;
}

Ví dụ 3: Danh sách bộ chọn và việc lồng ghép

@nest

.foo, .bar {
  color: blue;

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

@nest always

.foo, .bar {
  color: blue;

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

dấu ngoặc

.foo, .bar {
  color: blue;

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

Dịch vụ so sánh giá (CSS) tương đương

.foo, .bar {
  color: blue;
}

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

Ví dụ 4 – Nhiều cấp

@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;
    }
  }
}

dấu ngoặc

figure {
  margin: 0;

  {
    & > figcaption {
      background: lightgray;

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

Dịch vụ so sánh giá (CSS) tương đương

figure {
  margin: 0;
}

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

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

Ví dụ 5 – Lồng ghép đối tượng hoặc thay đổi đối tượng mẹ

@nest

.foo {
  color: red;

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

@nest always

.foo {
  color: red;

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

dấu ngoặc

.foo {
  color: red;

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

Dịch vụ so sánh giá (CSS) tương đương

.foo {
  color: red;
}

.parent .foo {
  color: blue;
}

Ví dụ 6 – Kết hợp việc lồng trực tiếp và lồng theo cấp trên

@nest

.foo {
  color: blue;

  @nest .bar & {
    color: red;

    &.baz {
      color: green;
    }
  }
}

@nest always

.foo {
  color: blue;

  @nest .bar & {
    color: red;

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

dấu ngoặc

.foo {
  color: blue;

  {
    .bar & {
      color: red;

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

Dịch vụ so sánh giá (CSS) tương đương

.foo {
  color: blue;
}

.bar .foo {
  color: red;
}

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

Ví dụ 7 – Lồng truy vấn nội dung nghe nhìn

@nest

.foo {
  display: grid;

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

hoặc rõ ràng / mở rộng

.foo {
  display: grid;

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

@nest always (is always explicit)

.foo {
  display: grid;

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

dấu ngoặc

.foo {
  display: grid;

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

hoặc rõ ràng / mở rộng

.foo {
  display: grid;

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

Dịch vụ so sánh giá (CSS) tương đương

.foo {
  display: grid;
}

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

Ví dụ 8 – Nhóm lồng nhau

@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;
    }
  }
}

dấu ngoặc

fieldset {
  border-radius: 10px;

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

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

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

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

Dịch vụ so sánh giá (CSS) tương đương

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;
}

Ví dụ 9 – Nhóm lồng ghép phức tạp "Bồn rửa nhà bếp"

@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;
  }
}

dấu ngoặc

dialog {
  border: none;

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

    & > form {
      display: grid;

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

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

Dịch vụ so sánh giá (CSS) tương đương

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;
}

Đã đến lúc bỏ phiếu

Hy vọng bạn cảm thấy đó là một bản so sánh công bằng và một mẫu cú pháp của các lựa chọn mà chúng tôi đang đánh giá. Vui lòng xem xét kỹ các lựa chọn này và cho chúng tôi biết bạn muốn chọn lựa chọn nào bên dưới. Chúng tôi trân trọng sự giúp đỡ của bạn trong việc phát triển tính năng lồng CSS thành một cú pháp mà tất cả chúng ta đều sẽ biết và yêu thích!

Tham gia khảo sát!