Bài 9.1: Giới thiệu CSS Grid và thuộc tính

Bài 9.1: Giới thiệu CSS Grid và thuộc tính
Chào mừng bạn đến với thế giới của CSS Grid Layout! Nếu bạn đã từng "vật lộn" với việc tạo ra các bố cục phức tạp trên trang web, đặc biệt là những bố cục hai chiều (rows và columns cùng lúc), thì CSS Grid chính là "vị cứu tinh" mà bạn đang tìm kiếm. Khác với Flexbox (vốn tập trung vào bố cục một chiều), Grid được sinh ra để giải quyết bài toán tạo ra những layout lưới thực sự, mạnh mẽ và linh hoạt.
Trong bài viết này, chúng ta sẽ cùng nhau khám phá CSS Grid là gì và làm quen với những thuộc tính cơ bản nhưng cực kỳ mạnh mẽ của nó. Hãy sẵn sàng để nâng tầm kỹ năng bố cục web của bạn lên một đẳng cấp mới!
CSS Grid là gì?
CSS Grid Layout, hay còn gọi tắt là Grid, là một hệ thống bố cục hai chiều mạnh mẽ trong CSS. Nó cho phép bạn chia một vùng chứa thành các lưới (grid) gồm các hàng (rows) và cột (columns), sau đó đặt các phần tử con vào những vị trí xác định trong lưới đó.
Với Grid, bạn có thể tạo ra các bố cục phức tạp từ những thứ đơn giản như layout blog 2 cột, đến những layout dashboard hay gallery ảnh phức tạp một cách dễ dàng hơn rất nhiều so với các phương pháp truyền thống như float hay positioning, thậm chí cả Flexbox trong một số trường hợp.
Hai thành phần chính: Grid Container và Grid Items
Để làm việc với Grid, chúng ta cần xác định hai thành phần chính:
- Grid Container: Là phần tử cha mà chúng ta muốn áp dụng bố cục lưới cho các phần tử con của nó. Để biến một phần tử thành Grid Container, chúng ta sử dụng thuộc tính
display
. - Grid Items: Là các phần tử con trực tiếp của Grid Container. Chúng sẽ được sắp xếp và định vị bên trong lưới.
Hãy bắt đầu bằng cách biến một phần tử thành Grid Container:
.container {
display: grid; /* Biến phần tử này thành một Grid Container */
}
Khi bạn áp dụng display: grid
cho một phần tử, các phần tử con trực tiếp của nó sẽ trở thành Grid Items và sẵn sàng được bố trí theo kiểu lưới.
Các thuộc tính cho Grid Container
Các thuộc tính được áp dụng cho Grid Container sẽ định nghĩa cấu trúc của lưới (số lượng và kích thước hàng/cột), khoảng cách giữa các hàng/cột, và cách các Grid Items được căn chỉnh bên trong lưới.
1. display
display: grid;
: Tạo ra một Grid Container cấp block (chiếm toàn bộ chiều rộng khả dụng).display: inline-grid;
: Tạo ra một Grid Container cấp inline (chỉ chiếm không gian vừa đủ cho nội dung).
.block-grid {
display: grid;
}
.inline-grid {
display: inline-grid; /* Sẽ hoạt động giống như một inline-block */
}
Giải thích: Hầu hết các trường hợp sẽ sử dụng display: grid;
. inline-grid
hữu ích khi bạn muốn container lưới nằm cùng hàng với các phần tử inline khác.
2. grid-template-columns và grid-template-rows
Đây là hai thuộc tính cực kỳ quan trọng. Chúng dùng để định nghĩa số lượng, kích thước và tên của các cột (grid-template-columns
) và hàng (grid-template-rows
) trong lưới của bạn một cách rõ ràng (explicit).
Bạn có thể sử dụng nhiều đơn vị khác nhau:
px
: Kích thước cố định theo pixel.%
: Kích thước theo phần trăm của container.em
,rem
: Kích thước tương đối theo font-size.fr
(fraction unit): Đơn vị phần phân số của không gian còn lại. Đây là đơn vị đặc biệt của Grid, giúp tạo ra các cột/hàng linh hoạt rất dễ dàng.1fr
nghĩa là chiếm 1 phần trong tổng số các phầnfr
có sẵn.auto
: Kích thước tự động dựa trên nội dung hoặc không gian còn lại.min-content
: Kích thước nhỏ nhất có thể mà nội dung không bị tràn.max-content
: Kích thước lớn nhất cần thiết để hiển thị toàn bộ nội dung trên một dòng.repeat()
: Hàm tiện ích để lặp lại một mẫu kích thước. Ví dụ:repeat(3, 1fr)
tương đương với1fr 1fr 1fr
.repeat(2, 50px 1fr)
tương đương với50px 1fr 50px 1fr
.minmax(min, max)
: Hàm định nghĩa một phạm vi kích thước cho một hàng hoặc cột. Ví dụ:minmax(100px, 1fr)
nghĩa là hàng/cột này sẽ có chiều cao/rộng ít nhất là 100px và tối đa là 1fr (chiếm phần không gian còn lại).
Ví dụ:
.container {
display: grid;
/* Định nghĩa 3 cột: cột 1 rộng 100px, cột 2 chiếm 1 phần không gian còn lại, cột 3 rộng tự động */
grid-template-columns: 100px 1fr auto;
/* Định nghĩa 2 hàng: hàng 1 cao tự động, hàng 2 cao 150px */
grid-template-rows: auto 150px;
}
Giải thích: Chúng ta đã tạo ra một lưới có 3 cột và 2 hàng với các kích thước khác nhau.
Ví dụ với repeat()
:
.container {
display: grid;
/* Định nghĩa 4 cột, mỗi cột chiếm 1/4 không gian khả dụng */
grid-template-columns: repeat(4, 1fr);
/* Định nghĩa 3 hàng, mỗi hàng cao ít nhất 50px và tối đa tự động */
grid-template-rows: repeat(3, minmax(50px, auto));
}
Giải thích: Tạo lưới 4x3 nhanh chóng và linh hoạt.
3. gap, row-gap, column-gap
Các thuộc tính này dùng để thêm khoảng cách (gutter) giữa các hàng và cột.
gap
: Thuộc tính viết tắt cho cảrow-gap
vàcolumn-gap
. Cú pháp:gap: <row-gap> <column-gap>;
. Nếu chỉ có một giá trị, nó áp dụng cho cả hàng và cột.row-gap
: Khoảng cách giữa các hàng.column-gap
: Khoảng cách giữa các cột.
Ví dụ:
.container {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(2, 100px);
/* Khoảng cách 20px giữa các hàng và 10px giữa các cột */
gap: 20px 10px;
/* Tương đương với:
row-gap: 20px;
column-gap: 10px;
*/
}
Giải thích: Dễ dàng tạo khoảng trống giữa các item mà không cần dùng margin cho từng item.
4. justify-items và align-items
Các thuộc tính này dùng để căn chỉnh các Grid Items bên trong ô lưới của chúng (single item alignment).
justify-items
: Căn chỉnh theo chiều ngang (column axis).align-items
: Căn chỉnh theo chiều dọc (row axis).
Các giá trị phổ biến:
start
: Căn chỉnh về phía đầu (trái/trên).end
: Căn chỉnh về phía cuối (phải/dưới).center
: Căn giữa.stretch
: Kéo dài item để lấp đầy ô (mặc định).
Ví dụ:
.container {
display: grid;
grid-template-columns: repeat(3, 1fr);
height: 200px; /* Cần có kích thước container để thấy rõ align-items */
/* Căn giữa tất cả item theo chiều ngang trong ô của chúng */
justify-items: center;
/* Căn giữa tất cả item theo chiều dọc trong ô của chúng */
align-items: center;
}
.item {
width: 50px; /* Item nhỏ hơn ô để thấy hiệu ứng căn chỉnh */
height: 50px;
background-color: lightblue;
}
Giải thích: Mặc dù item chỉ rộng/cao 50px, chúng sẽ được đặt ở giữa ô lưới có kích thước lớn hơn nhờ justify-items: center;
và align-items: center;
.
5. justify-content và align-content
Các thuộc tính này dùng để căn chỉnh toàn bộ lưới bên trong Grid Container khi lưới không chiếm hết không gian của container (grid alignment).
justify-content
: Căn chỉnh toàn bộ lưới theo chiều ngang (column axis).align-content
: Căn chỉnh toàn bộ lưới theo chiều dọc (row axis).
Các giá trị phổ biến:
start
: Căn lưới về phía đầu container.end
: Căn lưới về phía cuối container.center
: Căn lưới ra giữa container.stretch
: Kéo dài các hàng/cột rõ ràng (grid-template-rows
/columns
) để lấp đầy container (chỉ khi kích thước làauto
).space-around
: Phân phối không gian trống xung quanh mỗi hàng/cột.space-between
: Phân phối không gian trống giữa các hàng/cột (không có ở hai đầu).space-evenly
: Phân phối không gian trống đều nhau giữa các hàng/cột và ở hai đầu.
Ví dụ:
.container {
display: grid;
/* Các cột có kích thước cố định, nhỏ hơn chiều rộng container */
grid-template-columns: repeat(3, 100px);
grid-template-rows: repeat(2, 80px);
width: 500px; /* Container rộng hơn tổng chiều rộng các cột */
height: 300px; /* Container cao hơn tổng chiều cao các hàng */
background-color: #eee; /* Để dễ nhìn container */
/* Căn giữa toàn bộ lưới theo chiều ngang trong container */
justify-content: center;
/* Phân phối không gian đều giữa các hàng theo chiều dọc */
align-content: space-between;
}
Giải thích: Toàn bộ khối lưới (3x2 item) sẽ được đặt ở giữa container theo chiều ngang, và các hàng sẽ có khoảng trống bằng nhau giữa chúng theo chiều dọc.
6. grid-auto-columns và grid-auto-rows
Các thuộc tính này định nghĩa kích thước cho các hàng và cột được tạo ra một cách ngầm định (implicit grid), tức là khi có nhiều Grid Items hơn số lượng ô được định nghĩa rõ ràng bằng grid-template-columns
/rows
, hoặc khi một item được đặt vào một vị trí nằm ngoài lưới rõ ràng.
grid-auto-columns
: Kích thước cho các cột ngầm định.grid-auto-rows
: Kích thước cho các hàng ngầm định.
Giá trị thường dùng là auto
hoặc một kích thước cụ thể (100px
, 1fr
, minmax(...)
).
Ví dụ:
.container {
display: grid;
grid-template-columns: repeat(3, 100px); /* Định nghĩa 3 cột rõ ràng */
/* Không định nghĩa grid-template-rows */
/* Các hàng ngầm định sẽ có chiều cao tối thiểu 50px */
grid-auto-rows: minmax(50px, auto);
}
/* Nếu có nhiều hơn 3 items, item thứ 4, 5, ... sẽ tạo ra các hàng mới */
/* Các hàng này sẽ có chiều cao theo grid-auto-rows */
Giải thích: Grid sẽ tự động tạo ra các hàng mới khi cần thiết và các hàng đó sẽ có chiều cao tự động dựa trên grid-auto-rows
. Tương tự với grid-auto-columns
nếu bạn không định nghĩa grid-template-columns
hoặc đặt item vào cột ngoài phạm vi.
7. grid-auto-flow
Thuộc tính này kiểm soát cách các Grid Items tự động được đặt vào lưới khi bạn không chỉ định vị trí cụ thể cho chúng.
row
(mặc định): Items sẽ lấp đầy các hàng trước, tạo ra các hàng mới khi hết chỗ trên hàng hiện tại.column
: Items sẽ lấp đầy các cột trước, tạo ra các cột mới khi hết chỗ trong cột hiện tại.dense
: Thuật toán "đóng gói" item sẽ cố gắng lấp đầy các khoảng trống nhỏ hơn trong lưới, bất kể thứ tự mã nguồn, nhằm tối ưu không gian. Có thể làm thay đổi thứ tự hiển thị của item.
Ví dụ:
.container {
display: grid;
grid-template-columns: repeat(3, 100px);
grid-auto-rows: 80px;
grid-auto-flow: column; /* Item sẽ lấp đầy theo chiều cột */
}
/* Item 1, 2, 3 sẽ nằm ở cột 1, hàng 1, 2, 3 (nếu có đủ hàng)
Item 4, 5, 6 sẽ nằm ở cột 2, hàng 1, 2, 3, ...
*/
Giải thích: Thay vì xếp từ trái sang phải (hết hàng xuống hàng mới), các item sẽ xếp từ trên xuống dưới (hết cột sang cột mới).
8. grid-template-areas
Thuộc tính này cho phép bạn tạo ra bố cục bằng cách đặt tên cho các khu vực trong lưới và sau đó "vẽ" bố cục đó bằng các tên. Đây là một cách rất trực quan để tạo ra các layout phức tạp.
Cú pháp: Sử dụng các chuỗi string, mỗi string là một hàng. Trong mỗi string, sử dụng tên khu vực (hoặc .
cho ô trống), cách nhau bằng dấu cách. Các ô cùng tên liền kề (ngang hoặc dọc) sẽ tạo thành một khu vực lớn hơn.
Ví dụ HTML:
<div class="container">
<header>Header</header>
<nav>Navigation</nav>
<main>Main Content</main>
<footer>Footer</footer>
</div>
Ví dụ CSS:
.container {
display: grid;
/* Định nghĩa bố cục bằng tên khu vực */
grid-template-areas:
"header header header"
"nav main main"
"nav main main"
"footer footer footer";
/* Định nghĩa kích thước cho các cột và hàng tương ứng với bố cục trên */
grid-template-columns: 150px 1fr 1fr; /* Cột nav rộng 150px, 2 cột main chia đều phần còn lại */
grid-template-rows: auto 1fr auto auto; /* Hàng header tự động, hàng main chiếm phần còn lại, footer tự động */
gap: 10px; /* Thêm khoảng cách giữa các khu vực */
}
/* Gán các phần tử con vào khu vực tương ứng */
header { grid-area: header; background: lightblue; }
nav { grid-area: nav; background: lightgreen; }
main { grid-area: main; background: lightyellow; }
footer { grid-area: footer; background: lightcoral; }
Giải thích: Chúng ta đã định nghĩa một bố cục 4x3 (4 hàng, 3 cột) và đặt tên cho các khu vực. Sau đó, sử dụng thuộc tính grid-area
trên các item để gán chúng vào khu vực đã đặt tên. Kết quả là một layout header-nav-main-footer kinh điển được tạo ra một cách rất dễ đọc và dễ quản lý.
Các thuộc tính cho Grid Items
Các thuộc tính được áp dụng cho Grid Items sẽ định vị và căn chỉnh từng item riêng lẻ bên trong lưới.
1. grid-column-start, grid-column-end, grid-row-start, grid-row-end
Các thuộc tính này cho phép bạn đặt một Grid Item vào một vị trí cụ thể trong lưới bằng cách chỉ định các đường kẻ (grid lines) mà item đó bắt đầu và kết thúc.
grid-column-start
: Đường kẻ cột item bắt đầu.grid-column-end
: Đường kẻ cột item kết thúc.grid-row-start
: Đường kẻ hàng item bắt đầu.grid-row-end
: Đường kẻ hàng item kết thúc.
Grid tạo ra các đường kẻ được đánh số, bắt đầu từ 1. Đối với 3 cột, sẽ có 4 đường kẻ (1, 2, 3, 4). Đối với 2 hàng, sẽ có 3 đường kẻ (1, 2, 3).
Bạn cũng có thể sử dụng từ khóa span <số>
để chỉ định item sẽ chiếm bao nhiêu hàng hoặc cột kể từ vị trí bắt đầu.
Ví dụ:
.container {
display: grid;
grid-template-columns: repeat(4, 1fr); /* Có 5 đường kẻ cột: 1, 2, 3, 4, 5 */
grid-template-rows: repeat(3, 100px); /* Có 4 đường kẻ hàng: 1, 2, 3, 4 */
gap: 10px;
}
.item-1 {
grid-column-start: 2; /* Bắt đầu từ đường kẻ cột thứ 2 */
grid-column-end: 5; /* Kết thúc ở đường kẻ cột thứ 5 (chiếm cột 2, 3, 4) */
grid-row-start: 1; /* Bắt đầu từ đường kẻ hàng thứ 1 */
grid-row-end: 3; /* Kết thúc ở đường kẻ hàng thứ 3 (chiếm hàng 1, 2) */
background: orange;
}
.item-2 {
grid-column-start: 1;
grid-column-end: span 2; /* Chiếm 2 cột kể từ đường kẻ 1 (tức là cột 1 và 2) */
grid-row-start: 3;
grid-row-end: span 1; /* Chiếm 1 hàng kể từ đường kẻ 3 (tức là hàng 3) */
background: purple;
}
Giải thích: item-1
chiếm vùng từ đường kẻ cột 2 đến 5 và đường kẻ hàng 1 đến 3. item-2
chiếm 2 cột bắt đầu từ đường kẻ cột 1 và 1 hàng bắt đầu từ đường kẻ hàng 3.
2. grid-column và grid-row
Đây là các thuộc tính viết tắt của các thuộc tính start/end ở trên.
grid-column
: Viết tắt củagrid-column-start
vàgrid-column-end
. Cú pháp:grid-column: <start-line> / <end-line-or-span>;
.grid-row
: Viết tắt củagrid-row-start
vàgrid-row-end
. Cú pháp:grid-row: <start-line> / <end-line-or-span>;
.
Ví dụ:
.container {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-template-rows: repeat(3, 100px);
gap: 10px;
}
.item-1 {
grid-column: 2 / 5; /* Bắt đầu từ cột 2, kết thúc ở cột 5 */
grid-row: 1 / 3; /* Bắt đầu từ hàng 1, kết thúc ở hàng 3 */
background: orange;
}
.item-2 {
grid-column: 1 / span 2; /* Bắt đầu từ cột 1, chiếm 2 cột */
grid-row: 3 / span 1; /* Bắt đầu từ hàng 3, chiếm 1 hàng */
background: purple;
}
Giải thích: Cách viết gọn hơn, mang lại kết quả tương tự ví dụ trước.
3. grid-area
Đây là thuộc tính viết tắt mạnh mẽ nhất cho Grid Item. Nó có hai cách dùng:
- Gán item vào một khu vực đã đặt tên (khi sử dụng
grid-template-areas
trên container). - Viết tắt cho cả 4 thuộc tính start/end: Cú pháp:
grid-area: <row-start> / <column-start> / <row-end> / <column-end>;
.
Ví dụ (kết hợp với grid-template-areas
):
.container {
display: grid;
grid-template-areas:
"header header"
"nav main"
"footer footer";
grid-template-columns: 100px 1fr;
grid-template-rows: auto 1fr auto;
}
/* Gán item vào khu vực tên 'main' */
main {
grid-area: main;
background: lightyellow;
}
/* Gán item vào khu vực tên 'header' */
header {
grid-area: header;
background: lightblue;
}
/* ... và tương tự cho nav, footer */
Giải thích: Cách dùng này rất clean và dễ hiểu, đặc biệt với các bố cục phức tạp được định nghĩa bằng grid-template-areas
.
Ví dụ (viết tắt lines):
.container {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(2, 100px);
}
/* Item này sẽ chiếm vùng từ hàng 1 cột 1 đến hàng 2 cột 3 */
.item-1 {
grid-area: 1 / 1 / 3 / 4; /* row-start / column-start / row-end / column-end */
background: orange;
}
Giải thích: Cách viết tắt này tuy ngắn gọn nhưng khó đọc hơn cách dùng start/end riêng lẻ hoặc cách dùng với area names, nên thường ít được dùng hơn trừ khi bố cục rất đơn giản.
4. justify-self và align-self
Các thuộc tính này dùng để căn chỉnh một Grid Item cụ thể bên trong ô lưới của nó. Chúng hoạt động tương tự justify-items
và align-items
ở container, nhưng chỉ áp dụng cho item được chọn.
justify-self
: Căn chỉnh item theo chiều ngang trong ô của nó.align-self
: Căn chỉnh item theo chiều dọc trong ô của nó.
Các giá trị tương tự justify-items
và align-items
: start
, end
, center
, stretch
.
Ví dụ:
.container {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(2, 100px);
height: 300px;
background-color: #eee;
/* Mặc định tất cả item đều stretch */
}
.item-2 {
width: 50px; /* Làm item nhỏ hơn ô để thấy hiệu ứng */
height: 50px;
background: yellow;
/* Căn item 2 về cuối ô theo chiều ngang */
justify-self: end;
/* Căn item 2 về giữa ô theo chiều dọc */
align-self: center;
}
Giải thích: item-2
sẽ nằm ở góc dưới bên phải của ô lưới mà nó thuộc về (theo mặc định hoặc vị trí được chỉ định), sau đó được căn chỉnh riêng lẻ theo justify-self
và align-self
.
Comments