CSS Grid vs Flexbox: khi nào dùng Flex, khi nào dùng Grid (nav & dashboard)

(Cập nhật: 19 tháng 7, 2026 ) CSS Grid Flexbox layout dashboard navbar responsive
Kết luận

Đừng hỏi “cái nào tốt hơn” — hỏi bạn đang thiết kế mấy chiều. Một trục (nav, chip, nhóm nút, căn icon+label) → Flexbox. Hai chiều (shell trang, dashboard widget, gallery căn hàng, form label/input thẳng cột) → Grid. Pattern thắng: Grid làm khung vùng, Flex làm ruột component. Prototype vùng khó trên CSS Grid generator rồi mới dán vào stylesheet.

Trên nhóm Discord / Slack của freelancer và team outsourcing Việt Nam, câu hỏi lặp lại mỗi sprint: “Navbar dùng Grid được không?”, “Dashboard toàn Flex bị vỡ cột — sao?”. Tài liệu hay dừng ở định nghĩa “1D vs 2D”. Bài này đi tiếp: quyết định theo màn hình thật (nav, card, dashboard), bảng litmus, code copy được, và lỗi DevTools hay gặp.

Ai nên đọc

  • Frontend đang chọn layout cho landing, admin, SaaS dashboard
  • Dev từng nhét cả trang vào display: flex rồi sinh wrapper lồng nhau
  • Ai cần giải thích nhanh cho designer / reviewer: vì sao vùng này là Grid

Litmus test (30 giây)

  1. Nếu một item cao hơn, các hàng/cột khác chiều có phải căn lại như một hệ không?
    • Có → nghiêng Grid
    • Không → nghiêng Flex
  2. Bạn có đang vẽ trên giấy cả đường ngang và dọc để căn không?
    • Có → Grid
    • Chỉ một hàng hoặc một cột → Flex
Bảng quyết định nhanh
Bài toán Ưu tiên Vì sao
Header / main / sidebar / footer Grid Named areas giữ sanity khi đổi breakpoint
Navbar: logo + link + CTA Flex Một trục ngang, space-between / gap
Gallery card cao đều theo hàng Grid auto-fit + minmax; track chung
Chip / tag wrap xuống dòng Flex flex-wrap; không cần căn cột giữa hàng
Form label + input thẳng cột Grid Cột dùng chung; Flex từng hàng dễ lệch khi copy dài ngắn khác
Footer nút trong card Flex justify-content + align-items trên một hàng
Dashboard 12 cột widget Grid span cột; vùng độc lập với nội dung widget
Căn giữa icon + chữ trong nút Flex align-items: center là đủ

.nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap; /* menu dài trên mobile */
}
.nav__links {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  align-items: center;
}

Tại sao không Grid? Vì bạn không căn cột giữa các hàng nav — chỉ phân bố trên một hàng. Ép Grid vào đây thường thêm grid-template-columns thừa và khó đọc hơn Flex.

Ngoại lệ: header hai tầng (hàng 1: logo + search; hàng 2: tab) mà cột logo phải thẳng hàng với sidebar — khi đó shell ngoài là Grid, hàng menu bên trong vẫn Flex.


Dashboard / shell trang: Grid

Đây là chỗ Flex thuần hay “thắng tạm rồi thua bảo trì”: bạn bọc flex column → flex row → lại column cho đến khi vô tình tái tạo grid.

.page {
  min-height: 100dvh;
  display: grid;
  grid-template-columns: 240px 1fr;
  grid-template-rows: auto 1fr auto;
  grid-template-areas:
    "side header"
    "side main"
    "side footer";
}

.side { grid-area: side; }
.header { grid-area: header; }
.main { grid-area: main; }
.footer { grid-area: footer; }

@media (max-width: 800px) {
  .page {
    grid-template-columns: 1fr;
    grid-template-areas:
      "header"
      "main"
      "footer";
  }
  .side { display: none; } /* hoặc drawer */
}

Prototype số cột / gap / areas trên công cụ CSS Grid (chạy trên trình duyệt, copy CSS) trước khi gắn vào Astro/React — đặc biệt hữu ích khi designer đổi “sidebar 240 → 280” giữa sprint.

🏁 Tạo CSS Grid ngay tại đây

  

Lưới widget 12 cột

.dashboard {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: 1rem;
}
.widget--wide { grid-column: span 8; }
.widget--narrow { grid-column: span 4; }

.widget {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}
.widget__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  justify-content: flex-end;
  align-items: center;
}

Grid đặt widget; Flex làm chrome bên trong. Reviewer nhìn một file CSS cũng hiểu ranh giới trách nhiệm.


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

Card cao khác nhau vẫn căn theo track hàng — việc mà Flex + flex-wrap làm kém tự nhiên hơn (mỗi hàng là flex line riêng, không chia cột chung với hàng dưới).


Case study ngắn

1) Landing freelancer: hero + pricing

  • Hero CTA nhóm nút → Flex (gap, wrap trên mobile)
  • Ba cột pricing → Grid repeat(3, 1fr) desktop; một cột mobile
  • Footer link → Flex wrap

Team từng dùng Flex cho cả ba cột pricing: khi một card thêm bullet dài, hai card kia không cùng baseline tiêu đề — chuyển sang Grid hết lệch trong một PR.

2) Admin CRM outsourcing

  • Shell: Grid areas (sidebar cố định)
  • Bảng filter chips phía trên: Flex wrap
  • Grid KPI 4 ô: repeat(4, 1fr)repeat(2, 1fr) tablet → 1 cột phone
  • Mỗi KPI card: Flex column (số lớn + label + sparkline)

Myth & debug DevTools

Myth thường gặp
Nghe đồn Thực tế
Grid thay Flex Không — lồng tự do là bình thường
Cả trang luôn dùng Flex Shell 2D sẽ sinh wrapper lồng; chuyển Grid từng vùng
gap trên Flex không tin được Hỗ trợ rộng; ưu tiên gap hơn margin hack
stretch là bug chiều cao Flex mặc định align-items: stretch — kiểm tra overlay trước khi đổ lỗi content

Trong Chrome/Firefox DevTools: Grid overlay hiện track; Flex overlay hiện main/cross axis. Khi migrate Flex shell → Grid, đổi từng vùng để bisect regression (sidebar trước, rồi main).

Container queries: khi component tự phản ứng theo bề rộng parent, lựa chọn Grid/Flex ngày càng local — giảm media query toàn cục. Vẫn áp dụng cùng litmus: component đó căn 1 trục hay 2 chiều?

Subgrid: hữu ích khi lưới con phải khớp cột cha; feature-detect và progressive enhance. Đa số dashboard ổn với Grid lồng + Flex mà chưa cần subgrid.


Checklist trước khi merge layout

  1. Vẽ (hoặc comment) trục căn chỉnh trong PR
  2. Nav / actions / chips → Flex đã thử chưa?
  3. Shell / gallery / form cột → Grid đã thử chưa?
  4. Có lồng đúng hướng (Grid ngoài, Flex trong) không?
  5. Mobile: flex-wrap hoặc đổi grid-template-areas — đã mở DevTools chưa?
  6. Prototype Grid phức tạp trên /vi/tools/css-grid/ rồi mới hard-code số magic

Kết

Câu hỏi đúng không phải “Flex hay Grid tốt hơn?” mà “màn hình này đang thiết kế mấy chiều?”. Nav và ruột component → Flex. Dashboard, gallery, form căn cột → Grid. Lồng hai cái là dấu hiệu team đã hiểu layout — không phải “code bẩn”. Khi vùng trang rối, mở CSS Grid tool, chỉnh hàng/cột/gap, copy CSS, rồi mới tối ưu tay.