12 điểm bởi GN⁺ 2025-11-27 | 1 bình luận | Chia sẻ qua WhatsApp
  • CSS Subgrid là một tính năng cho phép mở rộng cấu trúc Grid hiện có vượt qua các giới hạn trước đây, để cả các phần tử DOM con bên dưới cũng có thể tham gia vào cấu trúc lưới của phần tử cha
  • Trước đây chỉ các phần tử con trực tiếp mới có thể tham gia vào Grid, nhưng với subgrid, các cấu trúc lồng nhau như <ul>·<li> cũng có thể được sắp xếp vào cùng các ô lưới
  • Nó giải quyết sự mất cân đối giữa các phần tử anh em phát sinh do chênh lệch độ dài nội dung, đồng thời hỗ trợ tạo bố cục mà mỗi thẻ hoặc mỗi section có thể phản hồi động
  • Tuy vậy vẫn có những điểm cần lưu ý như vấn đề đặt trước hàng, đánh số lại line, và không tương thích với fluid grid dựa trên auto-fill
  • Tính năng này đã được hỗ trợ trên các trình duyệt lớn và có thể áp dụng dần dần, hứa hẹn nâng cao đáng kể độ linh hoạt trong thiết kế UI trong tương lai

Khái niệm cơ bản về Subgrid

  • CSS Grid ban đầu chỉ cho phép các phần tử con trực tiếp tham gia vào bố cục
    • Ví dụ, trong UI portfolio, các ảnh trong <li> bên trong <ul> về cơ bản sẽ bị gói vào cùng một ô
  • Khi dùng grid-template-rows: subgrid, grid-template-columns: subgrid, ta có thể kế thừa định nghĩa hàng và cột từ grid cha
    • Nhờ đó, mỗi <li> có thể được đặt trực tiếp vào các ô của grid cha, vừa giữ được cấu trúc HTML mang tính ngữ nghĩa, vừa duy trì căn chỉnh trực quan
  • Có thể đạt kết quả tương tự bằng Flexbox và Grid lồng nhau, nhưng subgrid mang lại cách tiếp cận gọn gàng hơn nhờ chia sẻ một cấu trúc grid duy nhất

Những khả năng bố cục mới

  • Trong ví dụ thẻ portfolio, mỗi <article> có một grid 2 cột để bố trí hình ảnh và văn bản
    • Đơn vị fr linh hoạt, nhưng vì mỗi thẻ tự tính toán độc lập nên dễ phát sinh mất cân đối về độ rộng cột
  • Khi áp dụng grid-template-columns: subgrid, mọi thẻ sẽ chia sẻ cùng một tỷ lệ cột của grid cha
    • Khi nội dung thay đổi, chẳng hạn độ dài tiêu đề, toàn bộ grid sẽ tự động được điều chỉnh lại
  • Với cách này có thể hiện thực bố cục có nhận thức lẫn nhau giữa các phần tử anh em
    • Ví dụ: nếu rút ngắn tiêu đề “Infinite Supercomputer”, tỷ lệ ảnh và văn bản của toàn bộ các thẻ sẽ được điều chỉnh ngay lập tức

Những điểm cần chú ý khi dùng Subgrid (Gotchas)

Đặt trước không gian hàng

  • Việc chia sẻ cột khá trực quan, nhưng khi chia sẻ hàng thì cần đặt trước số hàng một cách tường minh
    • Ví dụ: trong thẻ bảng giá, nếu muốn các mục của từng <ul> thẳng hàng trên cùng một hàng thì cần chỉ định số lượng hàng bằng grid-row: span N
  • Theo mặc định, subgrid chỉ chiếm một ô duy nhất, nên nếu muốn dùng nhiều hàng thì trước hết cần mở rộng vùng grid của phần tử cha

Đánh số trong grid lồng nhau

  • Subgrid kế thừa template hàng và cột của phần tử cha, nhưng số line sẽ được đánh lại
    • Ví dụ: dù kế thừa line 2 đến 5 của phần tử cha, bên trong nó vẫn sẽ được đánh số lại thành 1 đến 4
    • Mỗi grid có chỉ mục riêng, nên số line hoạt động như chỉ mục tương đối chứ không phải ID duy nhất

Không tương thích với fluid grid

  • Fluid grid có dạng repeat(auto-fill, minmax()) không thể dùng cùng subgrid
    • Subgrid cần số lượng cột đã được xác định, nên không hỗ trợ auto-fill·auto-fit
    • Tác giả cũng nói rõ rằng họ chưa tìm ra cách giải quyết cho tổ hợp này

Hỗ trợ trên trình duyệt cũ

  • Từ sau năm 2023, tính năng này đã được hỗ trợ trên các trình duyệt lớn, nhưng tỷ lệ hỗ trợ vẫn dưới 90%
  • Có thể cung cấp bố cục thay thế bằng điều kiện @supports not (grid-template-columns: subgrid)
    • Ví dụ: đề xuất một cấu trúc fallback xếp ảnh và văn bản theo chiều dọc

Ví dụ thực tế và kết luận

  • Trang dành cho nhà phát triển của Stripe (stripe.dev) tổ chức toàn bộ trang dưới dạng một grid lớn duy nhất, và hiện thực cách bố trí chi tiết thông qua nhiều tầng subgrid
  • Subgrid không chỉ hữu ích cho các bố cục quy mô lớn mà còn phù hợp với những tinh chỉnh UI nhỏ
  • Có thể triển khai dần dần mà không cần tái cấu trúc toàn bộ dự án
  • Đây là một công cụ mới giúp mở rộng độ linh hoạt của bố cục CSS, rất đáng để thử nghiệm trong thực tế

1 bình luận

 
GN⁺ 2025-11-27
Ý kiến trên Hacker News
  • Tính năng subgrid thực sự rất tuyệt, nhưng ở ví dụ đơn giản đầu tiên, cũng có thể dùng ul { display: contents } để các phần tử con tham gia vào bố cục grid
    Nếu không nhất thiết phải dùng subgrid thì cách này hiệu quả hơn

    • Đúng với ví dụ đó, nhưng nhìn chung display: contents sẽ loại bỏ hoàn toàn phần tử UL khỏi layout
      Vì vậy không thể áp dụng style hoặc nhận sự kiện UI trên phần tử đó
      Nếu muốn dùng UL làm vùng highlight hoặc một section có thể cuộn, thì subgrid hữu ích hơn nhiều
    • Ở ví dụ thứ hai, để giữ chiều rộng ảnh ổn định thì nên dùng đơn vị khác thay cho fr, và dùng fr cho phần văn bản để nó lấp đầy không gian còn lại
  • Trước đây khi làm UI so sánh giá, tôi đã rất khổ sở vì không có subgrid
    Việc đặt hai bảng cạnh nhau rồi căn các hàng cho khớp là bất khả thi
    Có thể xử lý bằng chiều cao cố định hoặc tính toán bằng JS, nhưng trong cấu trúc component React thì quá kém hiệu quả

  • Tôi từng nghĩ container queries có phải là lời giải tốt hơn không
    Nhưng để giữ tính nhất quán của toàn bộ grid thì subgrid có thể phù hợp hơn
    Nhân tiện, xem ví dụ CodePen sẽ dễ hiểu hơn

    • Container queries không giải quyết được vấn đề phản ứng theo kích thước của phần tử anh em
      Hơn nữa, dùng container sẽ tạo ra stacking context mới nên khá bất tiện
      Thật tiếc là không thể dùng subgrid cùng với container. Nếu phần tử con có thể tham chiếu kích thước của subgrid thì sẽ cực kỳ mạnh mẽ
  • Tôi có cảm giác như “rốt cuộc lại quay về layout bằng <table> à?”

    • Vừa đúng mà cũng vừa không. <table> ngày xưa là một kiểu hack để giải quyết vấn đề, nhưng có nhiều giới hạn về khả năng truy cập và kỹ thuật
      Hệ thống Grid là công cụ cho việc sắp xếp trực quan, khác với bảng dùng để biểu diễn cấu trúc dữ liệu
      Giờ grid đã trở thành tiêu chuẩn, nên tôi mong mọi người đừng tiếp tục so sánh nó với table nữa
    • 25 năm trước, người ta tự động render table từ phía server để làm layout, và khi đó nó thực sự dễ hoạt động
      Nhưng hoàn toàn không tính đến responsive hay accessibility. Rốt cuộc chúng ta như đang phát minh lại table vậy
    • Vấn đề của <table> là nó là một cấu trúc dùng để mô tả nội dung. Bản thân grid thì không có vấn đề gì
    • Tôi cũng đã nghe câu “table là để hiển thị dữ liệu dạng bảng” hơn 20 năm rồi
      Rốt cuộc CSS chỉ là tái hiện lại chức năng đó dưới một hình thức được cải tiến hơn
  • Một trong những lỗi grid tôi từng gặp là khi đặt kích thước phần tử <img> bằng đơn vị phần trăm, kích thước ô bị méo theo kích thước ảnh gốc
    Nó xảy ra trên cả Firefox và Chromium, và bug liên quan nằm ở Mozilla Bug 1857365

    • Tôi tự hỏi không biết nếu gán thuộc tính width/height cố định cho ảnh thì vấn đề này có biến mất không
  • Thật đáng tiếc khi CSS đôi lúc buộc phải thêm thông tin về cấu trúc tài liệu chỉ để phục vụ layout
    Ví dụ như phải khai báo rõ số lượng hàng

    • Lý tưởng nhất là có cách căn chỉnh các phần tử ngay cả khi chúng có parent khác nhau
      Hoặc sẽ rất hay nếu một flex container có thể mô phỏng cách phân bố của container khác
      Nhưng làm vậy có thể khiến DX trở nên phức tạp hơn nhiều
  • Tôi thắc mắc vì sao trong ví dụ code lại có style nằm ở cả file HTML lẫn CSS
    Chỉ nhìn CSS của ví dụ subgrid đầu tiên, tôi đã mất khá lâu để tìm xem UL đang được áp dụng style gì

  • Tôi lại có cảm giác như “rốt cuộc lại quay về grid à?”
    Thời HTML trước đây chúng ta cũng từng làm những thứ tương tự

    • Nhưng grid hiện nay giúp việc làm thiết kế responsive dễ hơn rất nhiều
    • Tất nhiên, giờ đây tác dụng phụ là lỗi khi styling cũng nhiều hơn 😅
  • Bài viết trên blog của Josh lúc nào cũng đáng ngưỡng mộ
    Độ rõ ràng trong cách viết, cảm quan thiết kế, và cả website có tính tương tác đều rất xuất sắc

    • Tôi cũng đăng ký mailing list của anh ấy. Mỗi lần có bài mới đều rất mong chờ
  • Cá nhân tôi vẫn thấy grid khó dùng
    Cú pháp khá gượng gạo và cảm giác về layout cũng không hợp lắm. Flexbox trực quan và linh hoạt hơn nhiều

    • Hai công nghệ này tiếp cận vấn đề theo cách khác nhau
      Flexbox kiểm soát kích thước theo hướng nội dung, còn Grid theo hướng container
    • Tôi cũng thỉnh thoảng thử quay lại với grid, nhưng vẫn thấy thiếu những tính năng mình muốn
      Nội dung không tự động khớp theo nhiều trục, và mọi thứ đều phải đặt bằng tay
      Có lẽ là tôi chưa hiểu đúng bản chất của grid, hoặc kiểu công việc của tôi không phù hợp với nó
    • Khi làm thiết kế responsive, tôi cũng thấy flexbox đơn giản hơn grid rất nhiều