Giới thiệu
Lưới 4 cột (4-column grid) là pattern phổ biến cho dashboard, portfolio, product grid, team section. Bài viết trình bày cách tạo với CSS Grid hiện đại và so sánh với cách cũ dùng float.
Ví dụ hiện đại: CSS Grid (Khuyến nghị)
<!DOCTYPE html>
<html lang="vi">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>4-Column Grid Layout</title>
<style>
* { box-sizing: border-box; margin: 0; padding: 0; }
body { font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif; background: #f5f5f5; padding: 2rem; }
.grid4 {
max-width: 1200px; margin: 0 auto;
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 24px;
}
.gridItem {
background: white;
border-radius: 16px;
padding: 2rem;
text-align: center;
min-height: 300px;
display: flex; flex-direction: column; justify-content: center;
box-shadow: 0 4px 12px rgba(0,0,0,0.06);
transition: transform 0.3s, box-shadow 0.3s;
}
.gridItem:hover { transform: translateY(-6px); box-shadow: 0 16px 32px rgba(0,0,0,0.1); }
.gridItem h3 { font-size: 1.5rem; color: white; margin: 0; }
.gridItem p { color: rgba(255,255,255,0.9); margin-top: 0.5rem; }
/* Màu gradient cho từng cột */
.gridItem:nth-child(1) { background: linear-gradient(135deg, #ff6b6b, #ee5a5a); }
.gridItem:nth-child(2) { background: linear-gradient(135deg, #4ecdc4, #3dbdb5); }
.gridItem:nth-child(3) { background: linear-gradient(135deg, #a66cfe, #9055ff); }
.gridItem:nth-child(4) { background: linear-gradient(135deg, #ff6b9b, #ee5a8a); }
/* Responsive: Tự động chuyển cột */
@media (max-width: 1024px) { .grid4 { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 600px) { .grid4 { grid-template-columns: 1fr; } }
</style>
</head>
<body>
<h1 style="text-align:center; margin-bottom:0.5rem; color:#2c3e50;">4-Column Grid Layout</h1>
<p style="text-align:center; color:#666; margin-bottom:2rem;">Responsive: 4 cột → 2 cột (≤1024px) → 1 cột (≤600px)</p>
<div class="grid4">
<div class="gridItem"><h3>Cột 1</h3><p>Nội dung cột đầu tiên</p></div>
<div class="gridItem"><h3>Cột 2</h3><p>Nội dung cột thứ hai</p></div>
<div class="gridItem"><h3>Cột 3</h3><p>Nội dung cột thứ ba</p></div>
<div class="gridItem"><h3>Cột 4</h3><p>Nội dung cột thứ tư</p></div>
</div>
</body>
</html>
So sánh: CSS Grid vs Float (Cách cũ)
Cách cũ: Float + Width % + Clearfix
/* Float approach - NOT RECOMMENDED */
.grid4 { overflow: hidden; } /* Clearfix hack */
.gridItem {
float: left;
width: 25%; /* 100% / 4 */
padding: 20px;
box-sizing: border-box;
height: 300px; /* Cần height cố định cho equal height */
}
@media (max-width: 600px) { .gridItem { width: 100%; } }
Bảng so sánh
| Tiêu chí | Float (Cũ) | CSS Grid (Mới) |
|---|---|---|
| Equal height columns | Cần height cố định / flex hack | Tự động (default stretch) |
| Gap giữa cột | Margin phức tạp, tính toán % | gap: 24px đơn giản |
| Responsive | Media query thay đổi width % | Media query thay đổi grid-template-columns |
| Source order independence | Khó | order property dễ dàng |
| Vertical centering | Cần flex/table-cell hack | align-items: center trên grid |
| Code maintainability | Thấp | Cao |
Biến thể nâng cao
1. Auto-fit Grid (Không cần media query)
.grid4 {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 24px;
}
Tự động: >1000px→4 cột, 750-1000px→3 cột, 500-750px→2 cột, <500px→1 cột.
2. Asymmetric 4-column (Featured + 3 normal)
.grid4 {
grid-template-columns: 2fr 1fr 1fr 1fr; /* Item đầu gấp 2 lần */
}
@media (max-width: 900px) { grid-template-columns: 1fr 1fr; }
@media (max-width: 600px) { grid-template-columns: 1fr; }
3. Masonry Layout (CSS-only - Experimental)
.masonryGrid {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-template-rows: masonry; /* Chỉ Firefox behind flag, Chrome chưa hỗ trợ */
gap: 20px;
}
Masonry thực sự (Pinterest-style) hiện nay vẫn cần JS (Masonry.js) hoặc CSS Columns (column-count: 4; column-gap: 20px;) - nhưng columns không kiểm soát được hàng ngang.
Best Practices
- Luôn dùng
gapthay vì margin trên item. - Container nên có
max-widthvàmargin: 0 auto. - Item dùng
min-heightthay vìheightcố định để nội dung dài không bị tràn. - Test với nội dung thực tế (tiêu đề dài, mô tả ngắn, hình ảnh tỷ lệ khác nhau).