Media Queries đã không còn là lựa chọn duy nhất
Media Queries đã thống trị kỷ nguyên Responsive suốt hơn một thập kỷ. Tuy nhiên, công cụ này có một hạn chế lớn: nó chỉ quan tâm đến kích thước màn hình (viewport). Điều này gây khó khăn khi bạn muốn tái sử dụng một component ở nhiều vị trí khác nhau.
Thử nghĩ về một chiếc “Card” giới thiệu sản phẩm. Trên Desktop, nó nằm trong Grid 3 cột và hiển thị rất đẹp. Nhưng khi bạn kéo đúng chiếc Card đó vào một Sidebar hẹp, Media Queries trở nên vô dụng. Dù màn hình vẫn là 1920px, không gian thực tế của Card lúc này chỉ còn khoảng 300px. Kết quả? Component bị vỡ layout hoặc tràn khung.
Trong một dự án Dashboard gần đây, team mình từng phải duy trì hàng chục class như .card--sidebar hay .card--small. Khi chuyển sang Container Queries, chúng mình đã loại bỏ được khoảng 40% logic CSS dư thừa. Component giờ đây tự quyết định: “Nếu vùng chứa của tôi rộng hơn 400px, tôi sẽ nằm ngang. Nếu nhỏ hơn, tôi tự động chuyển sang dạng dọc”.
Nói cách khác, Component giờ đây có khả năng tự nhận thức không gian thay vì phụ thuộc một cách thụ động vào trình duyệt.
Triển khai Container Queries trong 2 bước
Hiện tại, Container Queries đã được hỗ trợ trên 91% trình duyệt toàn cầu (theo CanIUse). Bạn có thể dùng trực tiếp với CSS thuần mà không cần cài thêm thư viện. Quy trình thiết lập cực kỳ đơn giản.
Đầu tiên, hãy xác định phần tử cha là “vùng chứa”:
.parent-container {
/* Biến phần tử này thành một 'thước đo' cho các con */
container-type: inline-size;
/* Đặt tên để tránh nhầm lẫn nếu có nhiều container chồng nhau */
container-name: product-grid;
}
Giá trị inline-size là lựa chọn phổ biến nhất. Nó cho phép các phần tử con kiểm tra chiều rộng (width) của cha. Nếu dùng size, bạn sẽ kiểm tra được cả chiều cao, nhưng lúc đó bạn bắt buộc phải set cứng chiều cao cho cha.
Xây dựng Component “biết tuốt”
Hãy cùng thực hành với một chiếc Card thông minh. Mục tiêu là giúp nó tự biến hình dù đặt ở bất kỳ đâu trong layout.
1. Cấu trúc HTML cơ bản
<div class="card-wrapper">
<div class="custom-card">
<img src="thumb.jpg" alt="Product">
<div class="content">
<h2>Tên sản phẩm</h2>
<p>Mô tả chi tiết sản phẩm...</p>
</div>
</div>
</div>
2. Biến Wrapper thành Container
.card-wrapper {
container-type: inline-size;
width: 100%;
}
3. Viết Query cho Component
Thay vì @media, chúng ta sử dụng @container. Cách viết này giúp logic hiển thị đi kèm trực tiếp với component.
/* Style mặc định: Dạng dọc cho không gian hẹp */
.custom-card {
display: flex;
flex-direction: column;
gap: 16px;
}
/* Khi vùng chứa rộng từ 500px trở lên */
@container (min-width: 500px) {
.custom-card {
flex-direction: row;
align-items: center;
}
.custom-card img {
width: 200px;
}
}
Sức mạnh thực sự nằm ở chỗ: Nếu bạn ném Card này vào col-md-3 của Bootstrap, nó hiện dạng dọc. Ném vào col-md-12, nó tự chuyển sang ngang. Bạn không cần bận tâm màn hình người dùng là 1024px hay 2K nữa.
Sử dụng đơn vị đo lường mới (cqw, cqh)
Container Queries còn mang đến bộ đơn vị cực kỳ linh hoạt. Bạn có thể điều chỉnh font-size tỉ lệ thuận với độ rộng của chính component đó:
cqw: 1% chiều rộng của container.cqh: 1% chiều cao của container.
Ví dụ, để tiêu đề luôn cân đối với kích thước card:
.custom-card h2 {
font-size: clamp(1rem, 8cqw, 2rem);
}
Kinh nghiệm Debug và Fallback
Làm việc với Container Queries đôi khi sẽ khiến bạn bối rối vì co giãn trình duyệt không làm CSS thay đổi ngay lập tức. Hãy tận dụng Chrome DevTools.
Khi inspect, bạn sẽ thấy badge “container” cạnh element. Click vào đó, trình duyệt sẽ highlight vùng chứa đang được truy vấn. Nếu CSS không ăn, hãy kiểm tra ngay xem bạn đã khai báo container-type cho phần tử cha gần nhất chưa.
Với các dự án cần hỗ trợ trình duyệt cũ (như IE hoặc Safari đời thấp), hãy sử dụng @supports:
@supports not (container-type: inline-size) {
/* Viết CSS fallback bằng Flexbox hoặc Media Queries tại đây */
.custom-card { flex-direction: column; }
}
Đừng cố biến mọi thứ thành Container Queries. Hãy dành nó cho những UI Component mang tính tái sử dụng cao. Với layout tổng thể của trang như Header hay Footer, Media Queries vẫn là lựa chọn tối ưu và đơn giản nhất.

