Bài 9: CSS Grid – Bố cục 2 chiều + Responsive cơ bản
🎯 Mục tiêu
- Hiểu CSS Grid là gì và khác Flexbox ở điểm nào
- Biết tạo lưới bằng
display: grid - Biết dùng:
grid-template-columns,gap,repeat(),minmax() - Biết responsive cơ bản để grid tự co theo màn hình
📘 Lý thuyết ngắn
1) Khi nào dùng Grid?
- Dùng Grid khi bạn cần bố cục 2 chiều (hàng và cột)
- Dùng Flexbox khi bạn cần sắp xếp 1 chiều (hàng hoặc cột)
2) Ví dụ grid cơ bản
.container {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
gap: 12px;
}
3) Responsive grid “tự co” bằng minmax
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
Ý nghĩa: mỗi cột tối thiểu 220px, nếu đủ chỗ thì tự tăng và tự xếp thêm cột. Khi màn hình nhỏ, nó tự giảm số cột xuống 2 → 1.
🧾 Thuộc tính Grid hay dùng
| Thuộc tính | Ý nghĩa | Ví dụ |
|---|---|---|
display |
Bật Grid | display: grid; |
grid-template-columns |
Khai báo số cột | 1fr 1fr 1fr |
gap |
Khoảng cách giữa ô | gap: 16px; |
repeat() |
Lặp cột nhanh | repeat(3, 1fr) |
minmax() |
Min–max của cột | minmax(220px, 1fr) |
💻 Code mẫu (Gallery card bằng Grid + JS lọc nhanh)
<!doctype html>
<html lang="vi">
<head>
<meta charset="utf-8">
<title>Bài 9 - CSS Grid</title>
<style>
body{
font-family: Arial;
padding: 24px;
background: #f7f8fa;
line-height: 1.7;
}
.wrap{
max-width: 1000px;
margin: 0 auto;
}
h1{
text-align: center;
margin-top: 0;
}
.toolbar{
display: flex;
gap: 10px;
flex-wrap: wrap;
justify-content: center;
margin: 14px 0 18px;
}
.btn{
padding: 10px 14px;
border: 0;
border-radius: 10px;
cursor: pointer;
background: #111;
color: #fff;
font-weight: 600;
}
.btn.blue{ background:#2563eb; }
.btn.gray{ background:#374151; }
.grid{
display: grid;
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
gap: 16px;
}
.card{
background: #fff;
border: 1px solid #e5e5e5;
border-radius: 12px;
padding: 14px;
}
.thumb{
width: 100%;
height: 140px;
border-radius: 12px;
background: #e5e7eb;
display:flex;
align-items:center;
justify-content:center;
font-weight: 700;
color:#111;
margin-bottom: 10px;
}
.tag{
display:inline-block;
font-size: 12px;
padding: 2px 10px;
border-radius: 999px;
background:#eef2ff;
border:1px solid #dbeafe;
margin-right: 6px;
}
.hidden{ display:none; }
</style>
</head>
<body>
<div class="wrap">
<h1>Gallery card bằng CSS Grid</h1>
<div class="toolbar">
<button class="btn blue" data-filter="all">Tất cả</button>
<button class="btn" data-filter="html">HTML</button>
<button class="btn" data-filter="css">CSS</button>
<button class="btn gray" data-filter="js">JavaScript</button>
</div>
<div class="grid" id="grid">
<div class="card" data-cat="html">
<div class="thumb">HTML</div>
<h3>Bài HTML</h3>
<p>Tạo cấu trúc trang.</p>
<span class="tag">html</span>
</div>
<div class="card" data-cat="css">
<div class="thumb">CSS</div>
<h3>Bài CSS</h3>
<p>Làm đẹp giao diện.</p>
<span class="tag">css</span>
</div>
<div class="card" data-cat="js">
<div class="thumb">JS</div>
<h3>Bài JavaScript</h3>
<p>Tạo tương tác.</p>
<span class="tag">js</span>
</div>
<div class="card" data-cat="css">
<div class="thumb">CSS</div>
<h3>Grid nâng cao</h3>
<p>Lưới tự co theo màn hình.</p>
<span class="tag">css</span>
</div>
<div class="card" data-cat="html">
<div class="thumb">HTML</div>
<h3>Semantic</h3>
<p>Viết HTML chuẩn ý nghĩa.</p>
<span class="tag">html</span>
</div>
</div>
</div>
<script>
const buttons = document.querySelectorAll(".toolbar .btn");
const cards = document.querySelectorAll(".card");
buttons.forEach(btn => {
btn.addEventListener("click", () => {
const filter = btn.dataset.filter;
cards.forEach(card => {
const cat = card.dataset.cat;
if(filter === "all" || cat === filter){
card.classList.remove("hidden");
} else {
card.classList.add("hidden");
}
});
});
});
</script>
</body>
</html>
👉 Copy code → lưu thành bai9.html → mở bằng Chrome.
Thử thu nhỏ màn hình để thấy số cột tự đổi. Bấm nút lọc để ẩn/hiện card.
✍️ Bài tập
- Thêm ít nhất 3 card mới (tự đặt nội dung).
- Đổi
minmax(220px, 1fr)thànhminmax(280px, 1fr)và quan sát thay đổi. - Thêm nút lọc “CSS + JS” (hiển thị cả 2 loại).
- (Nâng cao) Khi đang lọc, làm nút đang chọn đổi màu.
✅ Đáp án gợi ý
1) Nút lọc CSS + JS
<button class="btn" data-filter="cssjs">CSS + JS</button>
2) Xử lý trong JS
if(filter === "cssjs"){
if(cat === "css" || cat === "js"){
card.classList.remove("hidden");
} else {
card.classList.add("hidden");
}
}
3) Đổi màu nút đang chọn (gợi ý)
buttons.forEach(b => b.classList.remove("active"));
btn.classList.add("active");
📌 Danh sách bình luận