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

Bạn cần giúp đỡ để xác định cú pháp nào nên được ưu tiên cho một đề xuất thông số kỹ thuật.

Adam Argyle
Adam Argyle
Miriam Suzanne
Miriam Suzanne

Lồng CSS là một cú pháp bổ sung thuận tiện cho phép thêm CSS vào bên trong một 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 ngôn ngữ này:

.nesting {
  color: hotpink;

  > .is {
    color: rebeccapurple;

    > .awesome {
      color: deeppink;
    }
  }
}

Sau khi được trình biên dịch trước biên dịch thành CSS thông thường, mã 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 rất kỹ việc sử dụng phiên bản CSS chính thức của cú pháp này và chúng tôi có một số ý kiến khác nhau về việc này. Chúng tôi muốn nhờ cộng đồng giúp đỡ để giải quyết vấn đề này. Phần còn lại của bài đăng này sẽ giới thiệu các tuỳ chọn cú pháp để bạn có thể tham gia cuộc khảo sát ở cuối bài.

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

Có một vài lý do khiến bạn không thể sử dụng cú pháp lồng 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 xử lý trước có thể phân giải và quản lý các bộ chọn đó tại thời điểm tạo bản dựng. Các công cụ trình duyệt sẽ không có cùng các tính năng hỗ trợ, bộ chọn không được diễn giải một cách lỏng lẻo.

  2. Xung đột phân tích cú pháp của trình xử lý trước
    Cách lồng CSS không được làm hỏng trình xử lý trước hoặc quy trình làm việc lồng hiện có của nhà phát triển. Điều này sẽ gây gián đoạn 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 ghép cơ bản không cần :is() nhưng việc lồng ghép phức tạp hơn thì cần. Hãy xem Ví dụ #3 để biết thông tin giới thiệu ngắn gọn về danh sách bộ chọn và lồng ghép. Hãy tưởng tượ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ề nội dung chúng ta so sánh

Chúng tôi muốn làm đúng cách việc lồng CSS và theo tinh thần đó, chúng tôi sẽ đưa cộng đồng vào. 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 cùng sẽ có một bản khảo sát ngắn để hỏi bạn về phương thức bạn ưu tiên nhất.

Cách 1: @nest

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

Cách 2: @nest bị hạn chế

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

Cách 3: Dấu ngoặc đơn

Để tránh cú pháp kép hoặc sự lộn xộn liên quan đến các đề xuất @nest, Miriam SuzanneElika Etemad đã đề xuất một cú pháp thay thế dựa vào 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 hai ký tự và không có quy tắc at-rule mới nào. Phương thức 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ự nhau.

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

@nest

.foo {
  color: #111;

  & .bar {
    color: #eee;
  }
}

@nest luôn

.foo {
  color: #111;

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

dấu ngoặc đơn

.foo {
  color: #111;

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

CSS tương đương

.foo {
  color: #111;
}

.foo .bar {
  color: #eee;
}

Ví dụ 2 – Lồng ghép phức hợp

@nest

.foo {
  color: blue;

  &.bar {
    color: red;
  }
}

@nest luôn

.foo {
  color: blue;

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

dấu ngoặc đơn

.foo {
  color: blue;

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

CSS tương đương

.foo {
  color: blue;
}

.foo.bar {
  color: red;
}

Ví dụ 3 – Danh sách bộ chọn và lồng nhau

@nest

.foo, .bar {
  color: blue;

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

@nest luôn

.foo, .bar {
  color: blue;

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

dấu ngoặc đơn

.foo, .bar {
  color: blue;

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

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 luôn

figure {
  margin: 0;

  @nest & > figcaption {
    background: lightgray;

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

dấu ngoặc đơn

figure {
  margin: 0;

  {
    & > figcaption {
      background: lightgray;

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

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 phần tử mẹ hoặc thay đổi chủ đề

@nest

.foo {
  color: red;

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

@nest luôn

.foo {
  color: red;

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

dấu ngoặc đơn

.foo {
  color: red;

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

CSS tương đương

.foo {
  color: red;
}

.parent .foo {
  color: blue;
}

Ví dụ 6 – Kết hợp cách lồng trực tiếp và lồng mẹ

@nest

.foo {
  color: blue;

  @nest .bar & {
    color: red;

    &.baz {
      color: green;
    }
  }
}

@nest luôn

.foo {
  color: blue;

  @nest .bar & {
    color: red;

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

dấu ngoặc đơn

.foo {
  color: blue;

  {
    .bar & {
      color: red;

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

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 luôn (luôn rõ ràng)

.foo {
  display: grid;

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

dấu ngoặc đơn

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

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 luôn

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 đơn

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 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 luôn

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 đơn

dialog {
  border: none;

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

    & > form {
      display: grid;

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

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

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

Thời gian bỏ phiếu

Hy vọng bạn cảm thấy đó là một phép so sánh công bằng và một đĩa mẫu của các tuỳ chọn cú pháp mà chúng tôi đang đánh giá. Vui lòng xem xét kỹ các đề xuất này và cho chúng tôi biết bạn chọn đề xuất nào trong phần bên dưới. Cảm ơn bạn đã giúp chúng tôi nâng cấp tính năng lồng CSS lên 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!