jvinhit//lab

Search posts

Type to search across journal entries.

navigate open esc close

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.

9 MIN READ

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 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ố; n track thì có n + 1 line.
  • 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-columnsgrid-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, 10remTrack cố định
autoTheo content (hoặc không gian còn lại)
1frMột phần không gian còn lại
min-contentNhỏ nhất content có thể
max-contentLớn nhất content muốn
minmax(a, b)Kẹp giữa ab
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-fitauto-fill
Track rỗngCo về 0Giữ ở kích thước min
Hiệu ứngItem giãn lấp đầy hàngItem 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ínhPhạm viTrục
justify-items / justify-selfCell content / one itemInline
align-items / align-selfCell content / one itemBlock
justify-contentWhole gridInline
align-contentWhole gridBlock

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-flow lê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ínhNhiệm vụ
display: grid | inline-gridTạo grid
grid-template-columns / -rowsKích thước track explicit
grid-template-areasĐặt tên vùng
grid-templateShorthand
gap / row-gap / column-gapKhoảng cách
grid-auto-columns / -rowsKích thước track ngầm
grid-auto-flowHướng tự đặt + dense
justify-items / align-items / place-itemsCanh content trong cell
justify-content / align-content / place-contentCanh cả lưới
gridShorthand tổng

Trên item:

Thuộc tínhNhiệm vụ
grid-column / grid-rowĐặt theo line / span
grid-areaTên area, hoặc shorthand 4 line
justify-self / align-self / place-selfCanh 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

  1. Tràn vì 1fr: Track 1fr tôn trọng min-content. Dùng minmax(0, 1fr) để cho co.
  2. gap không phải margin: không có khoảng cách mép; hãy pad container.
  3. dense phá thứ tự tab: thứ tự hình ảnh lệch DOM — tránh với content tương tác.
  4. order chỉ thị giác: giống dense, không đổi thứ tự focus của DOM.
  5. shell 100% vs 100dvh: dùng min-height: 100dvh (không phải height) để content giãn được.
  6. Percent trong fr: tránh trộn track % với fr; chúng đo khác nhau và xung đột.

Bài tập

Dùng demo để kiểm tra đáp án.

  1. Dựng gallery card responsive: card tối thiểu 240px, giãn lấp đầy hàng, gap 1.25remkhông media query.
  2. Tạo holy-grail bằng grid-template-areas, rồi cho stack thành một cột dưới 640px và ẩn aside.
  3. Trong grid 4 cột, biến item đầu thành hero full-width bằng grid-column: 1 / -1, rồi bật grid-auto-flow: dense và quan sát reflow.
  4. 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-items vs place-content vs margin: 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: