grid-template-areas cho dashboard admin | Named Grid layout thực chiến

(Cập nhật: 19 tháng 7, 2026 ) CSS Grid grid-template-areas dashboard admin layout named areas responsive
Kết luận

Shell admin/SaaS dùng grid-template-areas — đặt tên vùng rồi gán grid-area, không nhảy số cột. Desktop: sidebar cố định + header/main/footer. Mobile: viết lại cùng tên areas (một cột), ẩn hoặc drawer sidebar. Lưới widget bên trong main dùng repeat(12, 1fr) + span — đừng nhét widget vào một ASCII map khổng lồ. Prototype cột/gap trên CSS Grid generator (chạy trình duyệt), rồi viết tay named areas.

Team frontend Việt Nam làm admin CRM, portal nội bộ, SaaS dashboard thường gặp cùng một PR: sidebar 240px, header sticky, main scroll, footer mỏng — rồi breakpoint tablet phá hết vì mọi thứ gắn grid-column: 1 / 3. grid-template-areas giải bài đó bằng sơ đồ đọc được: đổi layout = đổi chuỗi tên, không đụng markup.

Bài này đi sâu named areas cho shell trang. Nếu bạn đang chọn Flex vs Grid tổng quát, đọc thêm CSS Grid vs Flexbox.

Ai nên bookmark

  • Dev dựng layout admin (sidebar + content) lần đầu hoặc đang refactor Flex lồng
  • Freelancer / outsourcing nhận Figma “dashboard 3 vùng” và cần CSS ổn định qua breakpoint
  • Reviewer muốn PR layout đọc được trong 30 giây (ASCII areas thay vì số magic)

Named areas là gì?

grid-template-areas khai báo bản đồ chữ nhật bằng chuỗi tên. Mỗi hàng trong template là một chuỗi; mỗi token là một ô. Phần tử con nhận grid-area: tên.

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

.admin__side { grid-area: side; }
.admin__head { grid-area: head; }
.admin__main { grid-area: main; }
.admin__foot { grid-area: foot; }

Đọc template như wireframe: cột trái toàn side, cột phải head / main / foot. Designer đổi “sidebar rộng hơn” → sửa 240px; đổi “header full width trên sidebar” → viết lại areas — không đổi HTML.

Quy tắc cứng (sai là template vỡ)

  1. Mỗi hàng cùng số token"side head""side main foot" không khớp → invalid.
  2. Vùng chữ nhật — tên main phải tạo hình chữ nhật liên tục; chữ L / lỗ thủng không hợp lệ.
  3. Tên khớp grid-area — typo sidebar vs side = phần tử rơi khỏi vùng.
  4. . = ô trống — không gán vùng; hữu ích khi chừa khoảng có chủ đích.
Khi nào areas, khi nào số track
Tình huống Ưu tiên Lý do
Shell trang (side/header/main/footer) Named areas Breakpoint = viết lại chuỗi; PR dễ review
Lưới 12 cột widget / KPI span cột Widget thêm/bớt liên tục; areas map sẽ phình
Gallery đều cột auto-fit + minmax Không cần đặt tên từng card
Navbar một hàng Flexbox Một trục; xem bài so sánh Flex/Grid
Form label thẳng cột Grid cột số / subgrid Areas ít mang lại giá trị hơn track cố định

Pattern shell admin chuẩn

Desktop: sidebar xuyên suốt

Pattern phổ biến nhất cho CRM / back-office:

.admin {
  display: grid;
  grid-template-columns: 16rem 1fr;
  grid-template-rows: 3.5rem 1fr 2.5rem;
  grid-template-areas:
    "nav top"
    "nav body"
    "nav foot";
  gap: 0; /* border nội bộ thay gap nếu cần hairline */
  min-height: 100dvh;
}

.admin__nav  { grid-area: nav; overflow: auto; }
.admin__top  { grid-area: top; }
.admin__body { grid-area: body; overflow: auto; }
.admin__foot { grid-area: foot; }

Vì sao không Flex column + Flex row? Vì bạn đang căn hai chiều cùng lúc (sidebar cao bằng cả ba hàng). Flex thuần dễ sinh wrapper flex-col > flex-row > flex-col — đúng tạm, review sau 6 tháng khó đọc hơn ASCII areas.

Header full-bleed (sidebar dưới header)

Một số design: logo + search trên toàn rộng, nav chỉ dưới:

.admin--topnav {
  grid-template-columns: 16rem 1fr;
  grid-template-rows: 3.5rem 1fr;
  grid-template-areas:
    "top top"
    "nav body";
}

Cùng bốn class HTML; chỉ đổi template. Đây là lý do named areas thắng grid-column: 1 / -1 rải rác khắp stylesheet.

Tablet / mobile: viết lại areas

@media (max-width: 900px) {
  .admin {
    grid-template-columns: 1fr;
    grid-template-rows: auto auto 1fr auto;
    grid-template-areas:
      "top"
      "nav"
      "body"
      "foot";
  }
}

@media (max-width: 640px) {
  .admin {
    grid-template-areas:
      "top"
      "body"
      "foot";
  }
  .admin__nav {
    /* drawer: position fixed + transform — vẫn giữ grid-area khi mở */
    position: fixed;
    inset: 0 auto 0 0;
    width: min(16rem, 85vw);
    z-index: 40;
    transform: translateX(-100%);
  }
  .admin.is-nav-open .admin__nav {
    transform: translateX(0);
  }
}

Nguyên tắc: tên vùng ổn định; chỉ chuỗi areas và track đổi theo breakpoint. HTML grid-area không đụng.


Main bên trong: widget ≠ shell areas

Sau khi shell ổn, vùng body thường là lưới KPI:

.dashboard {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  gap: 1rem;
  padding: 1rem;
}

.w-8 { grid-column: span 8; }
.w-4 { grid-column: span 4; }
.w-6 { grid-column: span 6; }
.w-12 { grid-column: span 12; }

@media (max-width: 900px) {
  .w-8, .w-4, .w-6 { grid-column: span 6; }
}
@media (max-width: 640px) {
  .w-8, .w-4, .w-6, .w-12 { grid-column: span 12; }
}

Ép toàn bộ widget vào một grid-template-areas kiểu:

"kpi kpi chart chart chart"
"table table table table table"

…sẽ vỡ ngay khi PO thêm widget thứ sáu giữa sprint. Areas cho khung trang; span cho nội dung động.

Ruột từng card (tiêu đề + badge + nút) → Flex. Pattern thắng: Grid shell → Grid 12 cột → Flex chrome.


Lỗi hay gặp (và cách đọc DevTools)

Lỗi named areas thường gặp
Triệu chứng Nguyên nhân Cách xử
Layout nhảy / vùng trống lạ Số token mỗi hàng không đều Đếm token; format ASCII thẳng cột trong editor
Phần tử nằm góc trái grid-area typo hoặc chưa gán So khớp tên trong template và class
Invalid property value Vùng không chữ nhật (chữ L) Vẽ lại; tách thành hai vùng hoặc dùng span
Sidebar không cao full Thiếu min-height / rows 1fr min-height: 100dvh + row giữa 1fr
Content tràn ngang 1fr + min-content con không co minmax(0, 1fr) trên cột; overflow trên body
Mobile còn khoảng side trống Đổi columns nhưng quên viết lại areas Media query phải đổi cả hai

Trong Chrome/Firefox: bật Grid overlay trên .admin — tên areas hiện trên track. Nếu overlay không khớp wireframe, sửa template trước khi đổ lỗi React/Vue.

minmax(0, 1fr): cột 1fr mặc định minmax(auto, 1fr) — bảng rộng trong main có thể kéo nở track. Admin hay “vỡ ngang” vì thiếu minmax(0, 1fr) hoặc overflow: auto trên vùng body.


Case study

1) Portal nội bộ outsourcing (React + CSS modules)

Yêu cầu: sidebar menu 8 mục, topbar user, main iframe báo cáo, footer version.

Team đầu dùng Flex: aside + div cột phải chứa header/main/footer. Khi design đổi “topbar full width”, phải tách DOM. Chuyển sang named areas — một PR CSS, HTML giữ bốn vùng. Tablet xếp nav thành hàng ngang dưới topbar bằng cách viết lại areas, không đụng component React.

2) SaaS analytics cho client Việt

Shell areas + dashboard 12 cột. Sprint 1: 4 KPI span 3. Sprint 3: thêm chart span 8 + list span 4. Areas shell không đổi một dòng; chỉ class span trên widget. Reviewer mới vào repo đọc grid-template-areas hiểu khung trang trong một phút.

3) Fail nhanh: areas map cả trang gồm 20 widget

Một freelancer copy “holy grail” rồi mở rộng ASCII cho mọi card. Thêm filter bar giữa header và KPI → phải sửa 4 media query. Refactor: tách .shell (areas) và .dashboard (12 cột) — thời gian debug layout giảm rõ ở các PR sau.


Quy trình prototype trên Kawa

Công cụ CSS Grid không sinh named areas — nó xuất repeat, gap, kích thước track. Dùng đúng việc:

  1. Chốt số cột shell (2) và gap (0 hoặc 1px hairline)
  2. Thử 1fr / auto / minmax(0,1fr) cho track main
  3. Copy đoạn display: grid; … gap… làm xương
  4. Viết tay grid-template-areas theo wireframe
  5. Kiểm tra overlay DevTools trên viewport thật (390 / 768 / 1280)

Không cần đăng ký; chạy trên trình duyệt — phù hợp khi đang xem Figma nội bộ và không muốn upload layout lên service lạ.

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

  

Checklist trước merge:

  • Mỗi hàng template cùng số token
  • Mọi grid-area khớp tên trong areas
  • Mobile đã viết lại areas (không chỉ đổi grid-template-columns)
  • Cột nội dung dùng minmax(0, 1fr) nếu có bảng/pre rộng
  • Widget động không nằm trong ASCII areas của shell
  • Đã xem Grid overlay ở breakpoint chính

Tóm tắt quyết định

Câu hỏiTrả lời ngắn
Shell admin 2D?grid-template-areas
Đổi breakpoint?Viết lại cùng tên areas
Widget thêm/bớt?12 cột + span trong main
Nav một hàng / nhóm nút?Flex (không areas)
Chốt số cột/gap nhanh?/vi/tools/css-grid/ rồi viết areas tay

Named areas không “thay” Flex hay 12-cột — nó là ngôn ngữ đặt tên cho khung trang. Dashboard dễ bảo trì khi khung đọc như wireframe và nội dung động không bị nhét vào cùng một bản đồ ASCII.

Liên kết liên quan