@container và :has(): hai API thích ứng mới và mạnh mẽ xuất hiện trong Chromium 105

Truy vấn vùng chứa và :has() là sự kết hợp hoàn hảo trong khả năng thích ứng. Thật may là cả hai tính năng này đều ra mắt cùng nhau trong Chromium 105. Đây là một bản phát hành lớn với hai tính năng được yêu cầu nhiều dành cho giao diện phản hồi!

Truy vấn vùng chứa: tóm tắt

Truy vấn vùng chứa cho phép nhà phát triển truy vấn bộ chọn mẹ để biết thông tin về kích thước và kiểu, giúp phần tử con có thể sở hữu logic tạo kiểu thích ứng, bất kể vị trí của bộ chọn đó trên trang web.

Thay vì dựa vào khung nhìn để nhập dữ liệu định kiểu, chẳng hạn như không gian có sẵn, giờ đây, nhà phát triển cũng có thể truy vấn kích thước của các phần tử trong trang. Khả năng này có nghĩa là một thành phần sở hữu logic tạo kiểu thích ứng. Điều này giúp thành phần bền bỉ hơn nhiều vì logic định kiểu được gắn với thành phần này, bất kể nó xuất hiện ở đâu trên trang.

Sử dụng truy vấn vùng chứa

Để tạo bằng các truy vấn vùng chứa, trước tiên bạn phải đặt vùng chứa trên phần tử mẹ. Bạn có thể thực hiện việc này bằng cách đặt container-type trên vùng chứa mẹ. Bạn có thể có một thẻ với hình ảnh và một số nội dung văn bản giống như sau:

Thẻ gồm hai cột.

Để tạo truy vấn vùng chứa, hãy đặt container-type trên vùng chứa thẻ:

.card-container {
  container-type: inline-size;
}

Việc đặt container-type thành inline-size sẽ truy vấn kích thước hướng cùng dòng của thành phần mẹ. Trong các ngôn ngữ Latinh như tiếng Anh, đây sẽ là chiều rộng của thẻ, vì văn bản chạy theo thứ tự từ trái sang phải.

Bây giờ, chúng ta có thể dùng vùng chứa đó để áp dụng kiểu cho bất kỳ phần tử con nào bằng cách sử dụng @container:

.card {
  display: grid;
  grid-template-columns: 1fr 1fr;
}

@container (max-width: 400px) {
  .card {
    grid-template-columns: 1fr;
  }
}

Bộ chọn mẹ :has()

Lớp giả lập :has() của CSS cho phép nhà phát triển kiểm tra xem phần tử mẹ có chứa phần tử con có tham số cụ thể hay không.

Ví dụ: p:has(span) cho biết bộ chọn đoạn (p), có span bên trong. Bạn có thể sử dụng thuộc tính này để tạo kiểu cho chính đoạn văn bản gốc hoặc tạo kiểu cho bất kỳ nội dung nào trong đoạn đó. Một ví dụ hữu ích là figure:has(figcaption) để tạo kiểu cho phần tử figure có chứa chú thích. Bạn có thể xem nhiều thông tin hơn về :has() trong bài viết này của Jhey Tompkins.

Truy vấn vùng chứa và :has()

Bạn có thể kết hợp sức mạnh lựa chọn gốc của :has() với sức mạnh truy vấn mẹ của các truy vấn vùng chứa để tạo một số kiểu nội tại thực sự linh động.

Hãy mở rộng ví dụ đầu tiên với thẻ tên lửa. Nếu bạn có thẻ nhưng không có hình ảnh thì sao? Có thể bạn muốn tăng kích thước của tiêu đề và điều chỉnh bố cục lưới thành một cột để tiêu đề trông có chủ ý hơn khi không có hình ảnh.

Văn bản lớn hơn trên thẻ không có hình ảnh và hiển thị trong một cột.

Trong ví dụ này, thẻ chứa hình ảnh có mẫu lưới hai cột, trong khi thẻ không có hình ảnh có bố cục một cột. Ngoài ra, thẻ không có hình ảnh sẽ có tiêu đề lớn hơn. Để viết mã này bằng :has(), hãy sử dụng CSS sau.

.card:has(.visual) {
  grid-template-columns: 1fr 1fr;
}

Bạn đang tìm một phần tử có lớp visual để áp dụng kiểu hai cột ở trên. Một hàm CSS gọn gàng khác là :not(). Đây là một phần có cùng thông số với :has() nhưng đã tồn tại lâu hơn và có hỗ trợ trình duyệt tốt hơn. Bạn thậm chí có thể kết hợp :has():not(), như sau:

.card:not(:has(.visual)) h1 {
  font-size: 4rem;
}

Trong mã trên, bạn đang viết một bộ chọn để tạo kiểu cho h1 trong một thẻ không chứa lớp visual. Đây là cách bạn có thể điều chỉnh kích thước phông chữ rất rõ ràng.

Kết hợp kiến thức đã học

Bản minh hoạ ở trên cho thấy sự kết hợp của :has(), :not()@container, nhưng các truy vấn vùng chứa thực sự nổi bật khi bạn có thể thấy cùng một phần tử được sử dụng ở nhiều nơi. Hãy thêm phong cách và hiển thị các thẻ này trong một lưới cùng nhau.

Giờ đây, bạn có thể thực sự thấy được sức mạnh của CSS hiện đại. Chúng ta có thể viết các kiểu rõ ràng bằng cách sử dụng các kiểu được nhắm mục tiêu để xây dựng logic dựa trên logic và tạo ra các thành phần thực sự mạnh mẽ. Với hai tính năng mạnh mẽ này đã ra mắt trong Chromium 105 và được hỗ trợ trên nhiều trình duyệt, quả là thời điểm thú vị cho nhà phát triển giao diện người dùng!