Menu

CSS Grid: cột, hàng, fr, gap và grid-template-areas

CSS grid xếp các phần tử theo hàng và cột cùng lúc. Tìm hiểu display: grid, grid-template-columns, đơn vị fr, repeat() và minmax(), auto-fill và auto-fit, đặt item bằng grid-column và grid-template-areas, với một grid trực tiếp để bạn sửa và đo.

Trang này có trình soạn thảo chạy trực tiếp. Sửa, chạy và xem đầu ra ngay lập tức.

Một grid trong ba dòng

Đặt display: grid cho container và liệt kê các cột bằng grid-template-columns. Các phần tử con lấp vào các ô theo thứ tự, từ trái sang phải trong tiếng Anh, và một hàng mới bắt đầu mỗi khi các cột đã đầy:

Bảy item, ba cột: hai hàng đầy đủ và hàng thứ ba có item 7 ở cột đầu tiên. Mọi cột đều rộng bằng nhau, và mọi item trong một hàng đều cao bằng nhau, nên các cạnh thẳng hàng theo cả hai chiều. Đó là điều grid làm được mà flexbox không có.

Playground grid

Nhập bất kỳ giá trị grid-template-columns nào, hoặc bấm vào một mẫu có sẵn. Phần hiển thị cho biết chiều rộng các cột mà trình duyệt tính ra (từ getComputedStyle) và số hàng các item cần dùng:

Vài điều đáng xem: 1fr 2fr làm cột thứ hai rộng đúng gấp đôi cột đầu. 200px 1fr giữ 200px và dành phần còn lại cho cột thứ hai. auto 1fr auto cho hai cột ngoài rộng theo nội dung. repeat(4, 100px) để lại khoảng trống ở cuối vì không có cột nào co giãn. Một giá trị không hợp lệ, như 1fr 2, sẽ bị bỏ qua và grid giữ giá trị hợp lệ gần nhất.

Đơn vị fr

fr nghĩa là "một phần của không gian trống". Trình duyệt trừ trước các cột cố định (px, rem, %, nội dung auto) và các khoảng gap, rồi chia phần còn lại cho các cột fr theo con số của chúng.

grid-template-columns trong container rộng 600px, không có gapChiều rộng các cột
1fr 1fr 1fr200, 200, 200
1fr 2fr200, 400
100px 1fr 1fr100, 250, 250
1fr 50%300, 300

fr không giống %: phần trăm cộng với gap có thể vượt quá 100% và tràn ra ngoài, còn các cột fr luôn chỉ chia phần còn lại sau khi đã trừ gap.

repeat(), minmax() và grid responsive không cần media query

repeat(4, 1fr) là 1fr 1fr 1fr 1fr. minmax(120px, 1fr) là một cột không bao giờ hẹp hơn 120px và giãn ra để nhận một phần không gian. Kết hợp chúng với auto-fill hoặc auto-fit thay cho số lượng, grid sẽ tạo nhiều cột nhất có thể vừa:

.cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 16px;
}

Chỉ một khai báo đó cho ra số cột rộng ít nhất 180px nhiều nhất mà container chứa được: nhiều cột trên màn hình rộng, một cột trên điện thoại, không cần media query. Sự khác biệt giữa auto-fill và auto-fit lộ ra khi số item ít hơn số cột:

Container chứa được năm cột 100px. auto-fill giữ cả năm cột, nên A, B và C mỗi item rộng 112px và còn lại hai cột trống. auto-fit thu gọn các cột trống, nên ba item giãn ra mỗi item khoảng 187px.

Đặt item: grid-column và grid-row

Các đường grid được đánh số từ 1 ở mép bắt đầu. grid-column: 1 / 3 nghĩa là "từ đường 1 đến đường 3", tức hai cột. span 2 nghĩa là "hai cột tính từ chỗ item rơi vào", còn -1 là đường cuối cùng:

Item màu tối lấp đầy cả hàng đầu tiên. Item màu xanh phủ một khối 2 x 2, item màu hổ phách phủ hai hàng. Item a và b tự lấp vào các ô còn lại: grid đặt mọi item có thể vào ô trống kế tiếp. grid-auto-rows: 60px đặt chiều cao cho những hàng bạn không khai báo bằng grid-template-rows.

grid-template-areas: đặt tên cho các phần của bố cục

Với bố cục trang, hãy đặt tên các vùng và vẽ chúng bằng chữ. Mỗi chuỗi là một hàng, mỗi từ là một ô, và một item gia nhập một vùng bằng grid-area:

Header và footer trải qua cả hai cột vì tên của chúng lấp đầy cả hai ô trong hàng. Hàng giữa là 1fr, nên nó lấy toàn bộ chiều cao còn lại của 280px. Để xếp chồng mọi thứ trên điện thoại, một media query chỉ cần vẽ lại các vùng thành một cột: grid-template-areas: "header" "side" "main" "footer" với grid-template-columns: 1fr. Trang media query trình bày mẫu này.

Căn chỉnh bên trong ô

Grid item mặc định giãn ra lấp đầy ô của nó. Các thuộc tính sau di chuyển item bên trong ô:

Thuộc tínhĐặt trênDi chuyển
justify-itemscontainermọi item dọc theo hàng (trục inline)
align-itemscontainermọi item lên xuống (trục block)
place-itemscontainerviết tắt: place-items: center căn giữa theo cả hai chiều
justify-self / align-selfitemmột item
justify-content / align-contentcontainertoàn bộ các track, khi grid nhỏ hơn container

display: grid; place-items: center; là cách ngắn nhất để căn giữa một phần tử con trong hộp.

Grid hay flexbox

Grid là hai chiều: bạn quyết định các cột (và hàng), nội dung lấp vào đó, nên mọi thẻ trong thư viện đều rộng bằng nhau kể cả ở hàng cuối. Flexbox là một chiều: các item tự lấy kích thước theo nội dung dọc theo một đường duy nhất. Hai thứ kết hợp rất tốt: grid cho trang và thư viện thẻ, flexbox bên trong mỗi thẻ cho hàng tiêu đề. Trang flexbox trình bày nửa còn lại.

Thứ tự và khả năng tiếp cận

grid-template-areas, grid-row, grid-column và order có thể đặt item ở bất kỳ đâu, nhưng trình đọc màn hình và phím Tab vẫn đi theo thứ tự HTML. Giữ thứ tự trong mã nguồn có ý nghĩa (header, điều hướng, nội dung chính, footer) và dùng grid để sắp xếp nó, không phải để chữa một thứ tự HTML vô lý.

Lỗi thường gặp

  • Đặt display: grid trên các item. Thuộc tính này đặt trên phần tử cha; chỉ con trực tiếp mới là grid item.
  • Dùng phần trăm cùng với gap. grid-template-columns: 50% 50% cộng gap: 16px sẽ tràn ra 16px. Dùng 1fr 1fr.
  • Dùng auto-fill khi bạn muốn auto-fit. Với ít item, auto-fill để lại các cột trống. Chuyển sang auto-fit để giãn các item.
  • Một cột 1fr rộng hơn phần của nó. Cột 1fr không co nhỏ hơn nội dung dài nhất của nó (một URL dài, một ảnh rộng). Dùng minmax(0, 1fr) để nó co được.
  • Chuỗi vùng không phải hình chữ nhật. Mỗi vùng được đặt tên phải tạo thành một hình chữ nhật, và mỗi chuỗi hàng phải có cùng số ô, nếu không cả khai báo grid-template-areas sẽ bị bỏ qua.
  • Quên rằng số thứ tự đường bắt đầu từ 1. Ba cột có bốn đường: 1 / 4 hoặc 1 / -1 trải qua cả ba cột.

Câu hỏi thường gặp

CSS grid là gì?

Một hệ thống bố cục đặt các phần tử theo hàng và cột cùng một lúc. Bạn đặt display: grid cho container, mô tả các cột bằng grid-template-columns (và các hàng nếu cần), rồi các phần tử con trực tiếp lấp vào các ô theo thứ tự.

1fr trong CSS grid nghĩa là gì?

fr là một phần của không gian trống trong grid container. grid-template-columns: 1fr 1fr 1fr cho ba cột bằng nhau, còn 1fr 2fr làm cột thứ hai rộng gấp đôi cột đầu. Kích thước cố định và khoảng gap được trừ ra trước; các cột fr chia nhau phần còn lại.

auto-fill và auto-fit khác nhau thế nào?

Cả hai đều tạo nhiều cột nhất có thể. auto-fill giữ lại các cột trống, nên khi có ít item, chúng vẫn hẹp và để lại khoảng trống ở cuối hàng. auto-fit thu gọn các cột trống, nên các item giãn ra lấp đầy hàng. Khi có đủ item để lấp đầy hàng, hai cách trông giống nhau.

Làm sao cho một grid item chiếm hai cột?

Dùng grid-column: span 2 cho item, hoặc cho nó đường bắt đầu và kết thúc: grid-column: 1 / 3 phủ cột 1 và 2. grid-column: 1 / -1 trải hết chiều rộng, vì -1 là đường cuối cùng.

Khi nào nên dùng grid thay vì flexbox?

Dùng grid khi hàng và cột phải thẳng hàng với nhau: thư viện thẻ, form có nhãn căn đều, trang có header, thanh bên và footer. Dùng flexbox cho một hàng hoặc một cột mà các item tự lấy kích thước theo nội dung, như thanh điều hướng.

grid-gap có giống gap không?

Có. grid-gap, grid-row-gap và grid-column-gap là tên cũ. Trình duyệt vẫn chấp nhận chúng như tên gọi khác, nhưng hãy viết gap, row-gap và column-gap, những thuộc tính dùng được cả trong flexbox.

Hình minh họa các ngôn ngữ lập trình của Coddy

Học lập trình cùng Coddy

Bắt đầu