PDA

View Full Version : Refactor Media Queries, Container Queries: Tối ưu component, giảm phụ thuộc layout



kemntas
07-01-2026, 02:37 PM
Ví dụ thực tếCó một Product Card được dùng ở 3 nơi:


Trang danh sách sản phẩm (khu vực rộng)

Sidebar gợi ý (khu vực hẹp)

Popup / Widget (kích thước thay đổi)

Mục tiêu:


Khi không gian hẹp → card hiển thị gọn, chữ nhỏ, ảnh trên.

Khi không gian rộng → card dạng ngang, chữ to hơn.

Cách cũ: Dùng Media Queries (phụ thuộc màn hình)HTML


<div class="layout">
<aside class="sidebar">
<div class="product">
<img src="thumb.jpg" alt="">
<div class="info">
<h3>Áo Hoodie</h3>
<p>Chất liệu nỉ cao cấp</p>
</div>
</div>
</aside>

<main class="content">
<div class="product">
<img src="thumb.jpg" alt="">
<div class="info">
<h3>Áo Hoodie</h3>
<p>Chất liệu nỉ cao cấp</p>
</div>
</div>
</main>
</div>


CSS (Media Queries)


.product {
display: flex;
gap: 12px;
}

/* Mobile */
@media (max-width: 768px) {
.product {
flex-direction: column;
}
.product h3 { font-size: 14px; }
}

/* Desktop */
@media (min-width: 769px) {
.product {
flex-direction: row;
}
.product h3 { font-size: 16px; }
}


❌ Vấn đề

Trên desktop, cả card ở sidebar (hẹp) và content (rộng) đều dùng layout “rộng”.

Card trong sidebar trông bị chật, chữ to, ảnh lệch.

Component phụ thuộc viewport, không phụ thuộc không gian nó chiếm.

Mục tiêu refactor✔ Component tự thích nghi theo kích thước container
✔ Tái sử dụng card ở mọi layout không cần viết CSS riêng
✔ Giữ Media Queries cho layout tổng thể, không dùng cho component
Cách mới: Dùng Container QueriesBước 1: Khai báo container cho vùng chứa component


.wrapper {
container-type: inline-size; /* theo chiều ngang */
}


HTML (chỉ thêm class wrapper)


<div class="layout">
<aside class="sidebar wrapper">
<div class="product">
<img src="thumb.jpg" alt="">
<div class="info">
<h3>Áo Hoodie</h3>
<p>Chất liệu nỉ cao cấp</p>
</div>
</div>
</aside>

<main class="content wrapper">
<div class="product">
<img src="thumb.jpg" alt="">
<div class="info">
<h3>Áo Hoodie</h3>
<p>Chất liệu nỉ cao cấp</p>
</div>
</div>
</main>
</div>


Bước 2: Viết Container Queries cho component


.product {
display: flex;
gap: 12px;
align-items: center;
}

/* Khi container hẹp */
@container (max-width: 300px) {
.product {
flex-direction: column;
align-items: flex-start;
}
.product h3 { font-size: 14px; }
}

/* Khi container rộng */
@container (min-width: 301px) {
.product {
flex-direction: row;
}
.product h3 { font-size: 16px; }
}


Kết quả sau refactor

Vị trí
Kích thước thực tế
Hiển thị


Sidebar
Hẹp
Card dạng cột, chữ nhỏ


Content
Rộng
Card dạng hàng, chữ lớn


Popup
Tùy kích thước
Tự điều chỉnh




👉 Không cần quan tâm màn hình to hay nhỏ – chỉ cần quan tâm container.
Kết hợp Media + Container Queries (Best Practice)

Media Queries → xử lý layout tổng thể

Container Queries → xử lý component

Ví dụ


/* Layout theo màn hình */
@media (max-width: 768px) {
.layout {
grid-template-columns: 1fr;
}
}

/* Component theo container */
.wrapper { container-type: inline-size; }

@container (max-width: 300px) {
.product { flex-direction: column; }
}


Lợi ích thực tế✔ Component độc lập layout → dễ tái sử dụng
✔ Giảm CSS theo breakpoint → code gọn hơn
✔ Phù hợp tư duy design system / component-based UI
✔ Dễ maintain khi thay đổi bố cục trang
Lưu ý khi áp dụng

Chỉ đặt container-type ở wrapper hợp lý, tránh lồng quá sâu.

Không dùng cho quá nhiều phần tử nhỏ gây phức tạp.

Kiểm tra hỗ trợ trình duyệt nếu phải hỗ trợ thiết bị cũ.

Kết luậnRefactor từ Media Queries → Container Queries giúp:


Tách bạch rõ layout và component,

Làm UI thông minh theo không gian thực tế,

Phù hợp với xu hướng component-based frontend hiện nay.