Dạng lồng ghép

Việc lồng các quy tắc kiểu CSS có thể giúp biểu định kiểu của bạn được sắp xếp gọn gàng hơn, dễ đọc hơn và dễ duy trì hơn.

Tổng quan

Bây giờ, bạn đã tìm hiểu về bộ chọn, có lẽ bạn đang thắc mắc về cách sắp xếp chúng một cách hiệu quả hơn trong biểu định kiểu. Hãy tưởng tượng bạn đang áp dụng kiểu cho các mục bên trong một phần "tính năng" trên trang web của mình. Với tính năng lồng ghép, bạn có thể nhóm các kiểu này bên trong quy tắc .feature như sau:

.feature {
  button {
    color: blue;
  }

  .link {
    color: red;
  }

  .text {
    font-size: 1.3em;
  }
}

Cách này cũng tương tự như khi bạn viết từng kiểu riêng biệt:

.feature button {
  color: blue;
}

.feature .link {
   color: red;
}

.feature .text {
   font-size: 1.3em;
}

Bạn có thể lồng bao nhiêu lớp tuỳ ý.

.feature {
  .heading {
    color: blue;

    a {
      color: green;
    }
  }
}

Nhóm và thiết lập mối quan hệ

Tính năng lồng ghép giúp bạn nhóm và thiết lập mối quan hệ giữa các quy tắc kiểu một cách ngắn gọn hơn.

Theo mặc định, quy tắc lồng nhau sẽ liên quan đến quy tắc bên ngoài dưới dạng một descendant combinator (bộ chọn kết hợp phần tử con). Sử dụng bộ chọn trên các quy tắc lồng nhau để thay đổi mối quan hệ.

/* targets headings that are siblings of the .feature element and come immediately after it */
.feature {
  + .heading {
    color: blue;
  }

/* targets all paragraphs that are direct children of the .feature element */
  > p {
    font-size: 1.3em;
  }
}

Xác định mối quan hệ rõ ràng bằng bộ chọn &

Bạn cũng có thể sử dụng bộ chọn & để rõ ràng hơn khi lồng các quy tắc kiểu. Hãy xem & là biểu tượng đại diện cho bộ chọn thành phần mẹ.

.feature {
 & button {
    color: blue;
  }
}

Điều này tương đương với việc viết các kiểu như sau:

.feature button {
  color: blue;
}

Khi cần có &

Nếu không có &, bộ chọn lồng nhau sẽ là bộ chọn con của bộ chọn gốc. Để tạo bộ chọn kết hợp, bạn & phải dùng.

.feature {
  &:last-child {
    /* Selects the .feature element that is the :last-child, equivalent to .feature:last-child */
  }
   
  & :last-child {
    /* Selects the :last-child inside of a .feature element, equivalent to .feature :last-child */
  }

  &.highlight {
    /* Selects .feature elements that also have a .highlight class, equivalent to .feature.highlight */
  }

  & .highlight {
     /* Selects elements inside of the .feature element with the class .highlight, equivalent to .feature .highlight */
  }
}

Bạn cũng có thể thay đổi bối cảnh và đặt bộ chọn & ở cuối bộ chọn con hoặc ở cả hai bên của bộ chọn con.


/* Targets buttons with an adjacent sibling button */
button {
  & + & {
    /* … */
  }
}
img {
  .my-component & {
    /* styles for images inside of `.my-component` ... */
  }
}

Trong ví dụ cuối cùng, chúng ta sẽ thêm kiểu cho hình ảnh bên trong một phần tử có lớp .my-component. Điều này có thể hữu ích nếu bạn đang làm việc trong một dự án mà bạn không thể thêm class hoặc id vào một phần tử.

Lồng ghép và mức độ cụ thể

Giống như :is(), bộ chọn lồng ghép lấy độ đặc hiệu của bộ chọn có độ đặc hiệu cao nhất trong danh sách bộ chọn của phần tử mẹ.

#main-header,
.intro {
  & a {
    color: green;
  }
}

.intro a {
  color: blue;
}

Quy tắc đầu tiên nhắm đến tất cả các đường liên kết bên trong các phần tử #main-header.intro, giúp các đường liên kết này có màu xanh lục.

Quy tắc thứ hai cố gắng ghi đè quy tắc này để các đường liên kết bên trong phần tử .intro có màu xanh dương.

Chúng ta có thể thấy lý do tại sao quy tắc này không hoạt động nếu xem xét mức độ cụ thể của từng quy tắc.

/* equivalent to :is(#main-header, .intro) a with a specificity of (1, 0, 1) */
#main-header,
.intro {
  & a {
    color: green;
  }
}

/* lower specificity of (0, 1, 1) */
.intro a {
  color: blue;
}

Vì quy tắc đầu tiên có một id trong danh sách bộ chọn và các quy tắc lồng nhau lấy độ đặc hiệu của bộ chọn có độ đặc hiệu cao nhất, nên quy tắc này có độ đặc hiệu cao hơn quy tắc thứ hai. Các đường liên kết có màu xanh lục ngay cả đối với những phần tử a không nằm trong một phần tử có bộ chọn #main-header.

Lồng ghép không hợp lệ

Tương tự như :is(), bộ chọn lồng ghép không thể biểu thị các phần tử giả.

blockquote, blockquote::before, blockquote::after {
  color: navy;

  & {
    border: 1px solid navy;
  }
}

Bạn có thể cho rằng blockquote và các phần tử giả của nó đều có văn bản và đường viền màu navy, nhưng không phải vậy. Vì bộ chọn & không thể biểu thị các phần tử giả, nên các kiểu đường viền lồng nhau sẽ chỉ áp dụng cho trích dẫn khối.

Khi tạo bộ chọn kết hợp bằng cách sử dụng & và bộ chọn loại, bộ chọn loại phải xuất hiện trước mà không có khoảng trắng ở giữa.

/* valid css nesting */
.feature {
  p& {
    font-weight: bold;
  }
}

/* invalid css nesting */
.feature {
  &p {
    font-weight: bold;
  }
}

Quy tắc này cho phép tính năng lồng CSS hoạt động cùng với các công cụ tiền xử lý như Sass. Trong Sass, việc viết &p sẽ nối bộ chọn gốc vào bộ chọn loại lồng nhau và kết quả sẽ là .featurep.

Lồng các quy tắc @

Bạn cũng có thể lồng các quy tắc nhóm có điều kiện CSS như @container, @media, @supports@layer.

.feature {
  @media (min-width: 40em) {
    /* ... */
  }

  @container (inline-size > 900px) {
    /* ... */
  }
}

.feature {
  @supports (display: grid) {
    /* ... */
  }
}

.feature {
  @layer component {
    h2 {
      /* ... */
    }
  }
}

Kiểm tra mức độ hiểu biết của bạn

Khi sử dụng tính năng Lồng CSS, bộ chọn & đại diện cho điều gì?

Bộ chọn con lồng nhau
Sai.
Bộ chọn phần tử mẹ
Chính xác!
bộ chọn anh chị em gần nhất
Sai.

Bạn chỉ có thể lồng tối đa 2 cấp.

Đúng
Sai.
Sai
Chính xác!

Những quy tắc @ nào có thể được lồng?

@media
Chính xác!
@container
Chính xác!
@import
Sai.
@supports
Chính xác!
@layer
Chính xác!