Đã bao giờ bạn code xong một chiếc thẻ (card) xịn sò, thu nhỏ kéo to trình duyệt thấy mọi thứ rất hoàn hảo. Nhưng đến khi nhét nó vào một cái sidebar chật chội thì... bùm, giao diện vỡ nát. Tại sao ư? Vì media queries chỉ quan tâm đến kích thước màn hình, chứ không hề biết cái "hộp" chứa component đó to nhỏ ra sao.
Đó là lúc Container Queries xuất hiện để cứu rỗi giao diện của bạn.
Nỗi đau mang tên Media Queries
Từ trước đến nay, chúng ta quen dùng @media (min-width: 768px) để thay đổi layout. Cách này rất ổn để chia cột toàn trang. Nhưng khi làm việc ở cấp độ component, nó lại tạo ra một thảm họa về bảo trì code.

Thử tưởng tượng bạn thiết kế một component danh sách sản phẩm. Khi ở trang chủ (không gian rộng), nó nằm ngang. Khi bị tống vào sidebar (không gian hẹp), nó phải nằm dọc. Nếu dùng media queries, bạn phải viết những đoạn code CSS cực kỳ lắt léo, kẹp thêm các class modifier lằng nhằng để ép nó hiển thị đúng chỗ.
Media queries gắn chặt component vào khung nhìn trình duyệt (viewport), khiến chúng mất đi tính tái sử dụng (reusable) thực sự. Đem sang một vị trí khác trong dự án là lỗi layout ngay.
Chính sự cồng kềnh trong việc quản lý class và logic đan chéo này là lý do nhiều người phải cất công tìm cách Tailwind CSS v4 giúp bạn dẹp loạn file CSS khổng lồ. Nhưng dù xài tool xịn đến đâu, bản chất vấn đề vẫn nằm ở tư duy responsive.
Vậy làm sao để component "tự biết thân biết phận"?
Container Queries: Chân ái của Component hiện đại
Thay vì hỏi trình duyệt "màn hình rộng bao nhiêu", Container Queries cho phép component hỏi thằng cha bọc ngoài nó: "Ê, cái hộp này rộng bao nhiêu để em còn liệu đường sắp xếp?".
Cách dùng tính năng này thực sự rất đơn giản. Đầu tiên, bạn khai báo phần tử cha là một "container":
.wrapper {
container-type: inline-size;
container-name: card-wrapper;
}
Sau đó, thay vì dùng @media, bạn dùng @container để style cho thằng con bên trong:
.card {
display: flex;
flex-direction: column;
}
/* Nếu container rộng hơn 400px thì tự dàn ngang */
@container card-wrapper (min-width: 400px) {
.card {
flex-direction: row;
}
}
Mẹo nhỏ: Thuộc tính inline-size giúp container theo dõi kích thước theo chiều ngang. Nếu muốn theo dõi cả chiều cao, bạn có thể xài giá trị size (dù thực tế ít phổ biến hơn).
Đỉnh không? Lúc này, cái thẻ .card của bạn mang vứt đi đâu cũng sống được. Quẳng vào lưới 3 cột? Nó tự co dọc. Vứt ra phần nội dung chính? Nó tự trải ngang mà không cần đổi class.
Vũ khí bí mật: Đơn vị đo lường cqw
Khi xài Container Queries, CSS còn tặng kèm cho bạn một bộ đơn vị đo lường cực chất: cqw (container query width) và cqh (container query height). Nó hoạt động y hệt như vw hay vh, nhưng thay vì tính theo phần trăm màn hình thì nó lấy phần trăm của chính container đó.
.card-title {
font-size: max(1.5rem, 5cqw);
}
Dòng code trên có nghĩa là chữ sẽ tự động to dần theo kích thước của hộp chứa, nhưng rớt xuống dưới 1.5rem là ngừng lại. Khỏi cần viết cả chục dòng breakpoint để chỉnh size font lắt nhắt nữa.
Nó mở ra cả một chân trời mới về typography linh hoạt.
Chia chác thế nào: Khi nào dùng cái gì?
Nghe xịn là vậy, nhưng đừng vội vàng xóa sạch mọi chữ @media trong mã nguồn. Mỗi công cụ sinh ra đều có đất diễn riêng của nó.
- Media Queries: Dành cho macro-layout (bố cục tổng). Ví dụ: Ẩn hiện sidebar, chia lưới chính của toàn trang, gom menu thành hamburger icon trên điện thoại.
- Container Queries: Dành cho micro-layout (bố cục chi tiết). Cực kỳ hợp cho các UI element độc lập như Card, Form, List, hay khi bạn đang lên chiến thuật về cách Bento Grid giúp giao diện gọn gàng.
Tính năng xịn sò này giờ đã được hỗ trợ đầy đủ trên hầu hết các trình duyệt hiện đại (Chrome, Safari, Firefox). Khuyên thật là bạn nên lướt qua document chính thức từ MDN Web Docs để nắm rõ các edge-case.
Biết xài chiêu này, việc xây dựng component tại DIA DEMY sẽ nhàn hạ và thú vị hơn rất nhiều.
Giờ đây, UI của bạn đã tự co giãn trơn tru. Nhưng nếu component hoàn hảo đó bị "treo" vì chờ API tải dữ liệu quá chậm thì user vẫn sẽ bực mình dời đi. Làm sao để giữ luồng trải nghiệm không bị đứt đoạn lúc loading đây?




Vui lòng đăng nhập để bình luận.