CSS Grid — The Complete Guide to Every Property (with an Interactive Demo)
A complete, practical CSS Grid reference: tracks, the fr unit, minmax & auto-fit, template-areas, alignment, item placement, and every container/item property — with a live interactive demo.
Vì sao lại thêm một bài về Grid
Phần lớn tutorial Grid dạy bạn bốn thuộc tính rồi dừng. Rồi bạn gặp layout thật — dashboard, holy-grail shell, gallery responsive — và phải dùng hack mong manh. Bài này thì ngược lại: một bản đồ đầy đủ mọi thuộc tính Grid, nhóm theo nơi nó sống (container vs item), mỗi cái kèm ví dụ nhỏ nhất để hiểu ngay.
Hãy dùng kèm demo bên dưới — chỉnh control, đọc CSS sinh ra.
Demo trực tiếp
Bảy tab, mỗi tab một khái niệm: track builder, đơn vị fr, auto-fit + minmax, grid-template-areas, alignment, đặt vị trí item, và bảng tra thuộc tính đầy đủ.
Mở demo đầy đủ:
Mô hình tư duy
Grid là hai chiều: bạn kiểm soát hàng và cột cùng lúc. Ba danh từ là đủ để suy luận mọi grid:
- các cột và hàng.
- các đường phân cách có đánh số;
ntrack thì cón + 1line. - một giao điểm track, hoặc một hình chữ nhật gồm nhiều cell mà bạn đặt tên.
Mọi thứ bên dưới chỉ là chỉnh kích thước track, hoặc đặt item theo line/area.
.container {
display: grid; /* or inline-grid */
}
display: grid biến các con trực tiếp thành grid item. Text node và ::before/::after cũng thành item.
Phần 1 — Định nghĩa track
grid-template-columns và grid-template-rows khai báo grid explicit.
.container {
display: grid;
grid-template-columns: 200px 1fr 200px; /* fixed · flexible · fixed */
grid-template-rows: 64px 1fr; /* header · body */
gap: 16px; /* row & column gutter */
}
Vài cách định kích thước bạn sẽ thật sự dùng:
| Giá trị | Ý nghĩa |
|---|---|
200px, 10rem | Track cố định |
auto | Theo content (hoặc không gian còn lại) |
1fr | Một phần không gian còn lại |
min-content | Nhỏ nhất content có thể |
max-content | Lớn nhất content muốn |
minmax(a, b) | Kẹp giữa a và b |
fit-content(x) | max-content, max-content nhưng giới hạn ở x |
khoảng cách
.container {
gap: 16px; /* both axes */
gap: 12px 24px; /* row-gap column-gap */
column-gap: 24px; /* individually */
}
gap chỉ thêm khoảng cách giữa các track, không bao giờ ở mép ngoài.
Thử ngay: mở tab Tracks của demo và đổi columns, rows, gap, số item.
Phần 2 — Đơn vị fr
fr phân chia không gian còn lại sau khi trừ track cố định và gap. Đây là điều quan trọng nhất cần thấm:
/* 120px is removed first; the remaining width splits 1 : 2 */
grid-template-columns: 120px 1fr 2fr;
fr tham lam nhưng vẫn để ý content: một track 1fr sẽ không co nhỏ hơn min-content của content trừ khi bạn dùng minmax(0, 1fr).
/* The classic "why won't my grid item shrink?" fix */
grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
Mẹo minmax(0, 1fr) là cách chữa khi text hay chart tràn ra ngoài grid item.
Thử ngay: tab fr unit cho bạn trộn một cột cố định với nhiều track
fr.
Phần 3 — Responsive không cần media query
Pattern Grid hữu ích nhất:
.gallery {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
gap: 1rem;
}
Đọc từ phải sang trái: mỗi cột tối thiểu 220px, tối đa 1fr; trình duyệt nhồi nhiều cột nhất mà chiều rộng cho phép. Không breakpoint.
auto-fit và auto-fill
Khác biệt chỉ lộ ra khi item ít hơn số cột:
auto-fit | auto-fill | |
|---|---|---|
| Track rỗng | Co về 0 | Giữ ở kích thước min |
| Hiệu ứng | Item giãn lấp đầy hàng | Item giữ size; còn khoảng trống |
Thử ngay: tab auto-fit / minmax có slider chiều rộng container để bạn xem cột wrap.
Phần 4 — Vùng đặt tên
Đặt tên vùng bằng ASCII, rồi thả item vào. Đây là cách dễ đọc nhất để dựng page shell:
.app {
display: grid;
grid-template-columns: 200px 1fr 200px;
grid-template-rows: auto 1fr auto;
grid-template-areas:
"header header header"
"nav main aside"
"footer footer footer";
min-height: 100dvh;
}
.app > header { grid-area: header; }
.app > nav { grid-area: nav; }
.app > main { grid-area: main; }
.app > aside { grid-area: aside; }
.app > footer { grid-area: footer; }
Vài luật hay khiến người ta vấp:
- Mỗi chuỗi hàng phải có cùng số cột.
- Tên lặp lại để span phải tạo thành hình chữ nhật.
- Dùng
.cho ô trống. - Định nghĩa lại areas trong media query là cách reflow sang mobile.
@media (max-width: 640px) {
.app {
grid-template-columns: 1fr;
grid-template-areas:
"header"
"main"
"nav"
"footer";
}
.app > aside { display: none; }
}
Thử ngay: tab template-areas chuyển giữa holy-grail, dashboard, và stacked.
Phần 5 — Canh chỉnh
Grid có hai phạm vi alignment, nhầm chúng là nguyên nhân bối rối số 1:
- canh content trong từng cell.
- canh cả lưới trong container khi lưới nhỏ hơn container.
Và hai trục:
- trục inline (hàng / ngang trong LTR).
- trục block (cột / dọc).
.container {
/* content inside every cell */
justify-items: center; /* inline axis */
align-items: center; /* block axis */
place-items: center; /* shorthand: align-items / justify-items */
/* the whole grid within the container */
justify-content: space-between;
align-content: center;
place-content: center / space-between;
}
/* override one item */
.featured {
justify-self: end;
align-self: start;
place-self: start end; /* align-self / justify-self */
}
| Thuộc tính | Phạm vi | Trục |
|---|---|---|
justify-items / justify-self | Cell content / one item | Inline |
align-items / align-self | Cell content / one item | Block |
justify-content | Whole grid | Inline |
align-content | Whole grid | Block |
Thử ngay: tab Alignment mở cả bốn thuộc tính container cùng lúc.
Phần 6 — Đặt item
Mặc định item tự chảy vào cell trống kế tiếp. Ghi đè vị trí bằng số line hoặc span:
.hero {
grid-column: 1 / 3; /* from line 1 to line 3 → spans 2 columns */
grid-row: 1 / 2;
}
.full-bleed {
grid-column: 1 / -1; /* first line to LAST line — full width */
}
.wide {
grid-column: span 2; /* span 2 tracks from wherever it lands */
}
Đếm line bắt đầu từ 1 ở trái/trên; -1 là line cuối. grid-area là shorthand bốn giá trị:
/* grid-area: row-start / col-start / row-end / col-end */
.card { grid-area: 1 / 1 / 3 / 3; }
grid-auto-flow và track ngầm
Khi item rơi ra ngoài grid explicit, Grid tạo track ngầm, kích thước theo grid-auto-rows / grid-auto-columns:
.masonry-ish {
grid-template-columns: repeat(3, 1fr);
grid-auto-rows: 120px; /* every implicit row is 120px */
grid-auto-flow: row dense; /* backfill holes left by spanning items */
}
dense lấp lại các lỗ hổng do item lớn để lại — tuyệt cho gallery, nhưng có thể đảo thứ tự hình ảnh so với DOM, ảnh hưởng luồng keyboard/tab.
Thử ngay: tab Item placement áp
grid-column/grid-row/grid-auto-flowlên một item được tô sáng.
Phần 7 — Line đặt tên & subgrid
Bạn có thể đặt tên line và tham chiếu thay vì số:
.container {
grid-template-columns: [full-start] 1fr [content-start] minmax(0, 64rem) [content-end] 1fr [full-end];
}
.content { grid-column: content-start / content-end; }
.bleed { grid-column: full-start / full-end; }
repeat() kèm tên tạo line tự đánh số như col 1, col 2:
grid-template-columns: repeat(3, [col] 1fr);
.item { grid-column: col 2 / span 1; }
subgrid cho grid lồng nhau kế thừa line track của cha để con căn thẳng hàng xuyên component:
.card {
display: grid;
grid-template-rows: subgrid; /* adopt the parent's row tracks */
grid-row: span 3;
}
Để xem subgrid/masonry sâu hơn, đọc:
Toàn bộ thuộc tính trong một bảng
Trên container:
| Thuộc tính | Nhiệm vụ |
|---|---|
display: grid | inline-grid | Tạo grid |
grid-template-columns / -rows | Kích thước track explicit |
grid-template-areas | Đặt tên vùng |
grid-template | Shorthand |
gap / row-gap / column-gap | Khoảng cách |
grid-auto-columns / -rows | Kích thước track ngầm |
grid-auto-flow | Hướng tự đặt + dense |
justify-items / align-items / place-items | Canh content trong cell |
justify-content / align-content / place-content | Canh cả lưới |
grid | Shorthand tổng |
Trên item:
| Thuộc tính | Nhiệm vụ |
|---|---|
grid-column / grid-row | Đặt theo line / span |
grid-area | Tên area, hoặc shorthand 4 line |
justify-self / align-self / place-self | Canh riêng item này |
order | Đổi thứ tự trong auto-flow |
Tab All properties trong demo là bảng tra y hệt, để cạnh ví dụ trực tiếp.
Cạm bẫy thực chiến
- Tràn vì
1fr: Track1frtôn trọngmin-content. Dùngminmax(0, 1fr)để cho co. gapkhông phải margin: không có khoảng cách mép; hãy pad container.densephá thứ tự tab: thứ tự hình ảnh lệch DOM — tránh với content tương tác.orderchỉ thị giác: giốngdense, không đổi thứ tự focus của DOM.- shell
100%vs100dvh: dùngmin-height: 100dvh(không phảiheight) để content giãn được. - Percent trong
fr: tránh trộn track%vớifr; chúng đo khác nhau và xung đột.
Bài tập
Dùng demo để kiểm tra đáp án.
- Dựng gallery card responsive: card tối thiểu
240px, giãn lấp đầy hàng, gap1.25rem— không media query. - Tạo holy-grail bằng
grid-template-areas, rồi cho stack thành một cột dưới640pxvà ẩnaside. - Trong grid 4 cột, biến item đầu thành hero full-width bằng
grid-column: 1 / -1, rồi bậtgrid-auto-flow: densevà quan sát reflow. - Nâng cao: Căn giữa một phần tử cả hai trục chỉ bằng Grid, theo nhiều cách (
place-itemsvsplace-contentvsmargin: auto) và giải thích khi nào chúng khác nhau.
Gợi ý lời giải
/* 1 */
.gallery { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 1.25rem; }
/* 2 — see Part 4; swap grid-template-areas in the media query and display:none the aside */
/* 3 */
.grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); grid-auto-flow: dense; }
.grid > :first-child { grid-column: 1 / -1; }
/* 4 — any of these centers a single child */
.a { display: grid; place-items: center; } /* aligns the item in its cell */
.b { display: grid; place-content: center; } /* aligns the whole (1-cell) grid */
.c { display: grid; } .c > * { margin: auto; } /* auto margins eat free space */place-items căn item trong track; place-content căn khối track trong container — giống nhau với một cell full-size, khác khi track nhỏ hơn container.
Tổng kết
Grid nhỏ gọn: vài thuộc tính container để chỉnh track, vài thuộc tính item để đặt vị trí, và hai phạm vi alignment. Khi fr, minmax, auto-fit, và grid-template-areas thành phản xạ, phần lớn layout chỉ còn vài dòng CSS trung thực.
Cứ mở demo trong lúc code: