Menu
ESC

Nhập từ khóa để tìm kiếm

↑↓ Di chuyển
Enter Mở
ESC Đóng

Đang tải...

Bài 50 — Tables & Data Display

Web Design Basics Bài 50/60

Mở đầu — vì sao bài này quan trọng

Nếu bạn từng mở một trang quản trị (admin dashboard) và thấy hàng nghìn dòng đơn hàng dồn vào một cái bảng chật chội, chữ san sát nhau, không biết cột nào quan trọng, không biết click vào đâu để sắp xếp — thì bạn đã trải nghiệm một cái table được thiết kế tệ. Và ngược lại, khi bạn dùng bảng trong Notion, Airtable hay trang đơn hàng của Shopee Seller Center, mọi thứ rõ ràng đến mức bạn lướt mắt là biết ngay đơn nào chưa giao, doanh thu ngày nào cao — đó là sức mạnh của một table được thiết kế đúng.

Table (bảng dữ liệu) là một trong những component bị xem nhẹ nhất nhưng lại xuất hiện nhiều nhất trong các sản phẩm thực tế. Mọi phần mềm doanh nghiệp — từ hệ thống quản lý kho, CRM, dashboard tài chính, đến trang quản lý người dùng — đều sống nhờ table. Một designer giỏi card, button, hero section nhưng "đuối" khi gặp table thì sẽ rất chật vật khi làm sản phẩm B2B hoặc internal tool, vốn là mảng có nhiều việc và lương tốt tại Việt Nam.

Bài này tập trung riêng vào trình bày dữ liệu dạng bảng: khi nào nên dùng table, cấu trúc giải phẫu của một bảng, cách căn chỉnh số liệu, sắp xếp (sort), lọc (filter), xử lý bảng trên mobile, và những lỗi khiến bảng trở nên không đọc nổi. Đây là kỹ năng "cơm áo gạo tiền" mà rất nhiều khóa học design bỏ qua.

Khái niệm cốt lõi

Khi nào dùng table — và khi nào KHÔNG

Table tồn tại để giải quyết một nhu cầu rất cụ thể: so sánh nhiều giá trị có cùng cấu trúc trên nhiều bản ghi. Bạn nên dùng table khi:

  • Người dùng cần so sánh giá trị giữa các dòng với nhau (so doanh thu tháng này với tháng trước, so giá sản phẩm A với B).
  • Dữ liệu có cấu trúc đồng nhất — mỗi bản ghi có cùng các thuộc tính (đơn hàng nào cũng có mã, khách, ngày, tổng tiền, trạng thái).
  • Người dùng cần quét nhanh (scan) một khối lượng lớn dữ liệu để tìm bất thường hoặc một dòng cụ thể.
  • Cần các thao tác sort, filter, phân trang trên dữ liệu.
Ngược lại, đừng dùng table khi: mỗi bản ghi có nội dung phong phú, dài, không đồng đều (lúc này dùng list hoặc card hợp hơn — ví dụ danh sách bài viết blog có ảnh, tiêu đề dài, mô tả); hoặc khi bạn chỉ có vài món thông tin của một đối tượng duy nhất (lúc đó dùng description list / key-value layout, không cần bảng). Lỗi kinh điển là nhồi nội dung tự do vào table chỉ vì "trông cho gọn", rồi cột nào cũng wrap chữ lung tung.

Giải phẫu một table (anatomy)

Một bảng dữ liệu chuẩn gồm các thành phần sau, và bạn nên nhớ tên chúng vì sẽ dùng cả khi thiết kế lẫn khi code:

  • Header (thead): hàng tiêu đề cột. Đây là "bản đồ" của bảng — nói cho người dùng biết mỗi cột chứa gì. Header thường được nhấn mạnh bằng font đậm hơn hoặc nền khác, và rất hay là nơi đặt nút sort.
  • Body (tbody): phần thân chứa các hàng dữ liệu (rows). Mỗi hàng là một bản ghi (một đơn hàng, một người dùng).
  • Cell: ô giao giữa hàng và cột, chứa một giá trị.
  • Row: hàng ngang, đại diện một bản ghi.
  • Column: cột dọc, đại diện một thuộc tính.
  • Footer (tfoot) (tùy chọn): hàng tổng kết — tổng tiền, trung bình, số dòng.
  • Toolbar/Controls: thanh phía trên hoặc dưới bảng chứa ô tìm kiếm, bộ lọc, nút export, và phân trang (pagination — sẽ học sâu ở Bài 51).
  • Caption: mô tả ngắn của bảng, quan trọng cho khả năng tiếp cận (accessibility).

Căn lề dữ liệu (alignment) — quy tắc vàng

Đây là kiến thức phân biệt người làm bảng nghiệp dư với chuyên nghiệp:

  • Text (văn bản) căn trái. Tên người, mô tả, địa chỉ — căn trái để mắt bắt đầu đọc từ một điểm cố định.
  • Số (number) căn phải. Giá tiền, số lượng, phần trăm — căn phải để các chữ số hàng đơn vị, hàng chục, hàng trăm thẳng cột nhau. Nhờ vậy người dùng so sánh độ lớn chỉ bằng cách nhìn chiều dài: "1.500.000" dài hơn "150.000" rõ ràng khi căn phải. Nên dùng tabular figures (chữ số đều bề rộng) để các chữ số thẳng hàng tuyệt đối.
  • Header căn theo cột của nó. Header của cột số cũng nên căn phải để khớp với dữ liệu.
  • Trạng thái, badge, action căn giữa hoặc trái tùy bố cục, nhưng nhất quán.

Mật độ (density) và khoảng thở

Table là cuộc đấu giữa mật độ thông tin (xem được nhiều dòng) và khả năng đọc (đủ khoảng thở). Có ba mức density phổ biến: compact (gọn, cho người dùng pro xem nhiều dữ liệu), default, và comfortable (thoáng). Một mẹo hay là cho phép người dùng tự chọn density — Gmail và nhiều admin tool làm điều này. Đường kẻ ngang nhạt (row divider) hoặc nền xen kẽ (zebra striping) giúp mắt bám đúng dòng khi bảng rộng.

Sort, filter và các tương tác

  • Sort (sắp xếp): cho click vào header để sắp xếp tăng/giảm. Phải có chỉ báo thị giác rõ — mũi tên lên/xuống — cho biết đang sort theo cột nào, chiều nào. Chỉ một cột được sort tại một thời điểm (trừ khi bạn làm multi-sort nâng cao).
  • Filter (lọc): thu hẹp dữ liệu theo điều kiện (chỉ đơn "Đang giao", chỉ tháng 6). Đặt ở toolbar phía trên.
  • Row actions: các thao tác trên từng dòng (sửa, xóa, xem). Đặt ở cột cuối, hoặc hiện khi hover, hoặc gom vào menu "ba chấm".
  • Selection: checkbox đầu dòng để chọn nhiều dòng làm hành động hàng loạt (bulk action) như xóa, xuất file.

Tình huống thực tế

Ví dụ 1 — Tiki Seller Center và trang "Quản lý đơn hàng"

Hãy tưởng tượng một nhà bán hàng trên Tiki có 2.000 đơn mỗi tháng, mở trang quản lý đơn. Phiên bản đầu của trang dùng một table với 11 cột: mã đơn, ngày, tên khách, số điện thoại, địa chỉ đầy đủ, sản phẩm, số lượng, đơn giá, tổng, trạng thái, ghi chú. Hậu quả: cột địa chỉ và sản phẩm wrap thành 3-4 dòng, mỗi hàng cao ngất, người bán phải cuộn ngang (horizontal scroll) liên tục, và cột "tổng tiền" căn trái nên không ai so sánh được đơn nào giá trị lớn.

Đội thiết kế xử lý lại theo nguyên tắc bài này: giảm còn 6 cột cốt lõi hiển thị trực tiếp (mã đơn, khách, ngày, tổng tiền, trạng thái, hành động); đẩy địa chỉ + sản phẩm chi tiết vào panel mở rộng khi click vào dòng. Cột tổng tiền căn phải, dùng tabular figures, định dạng "1.250.000 đ". Trạng thái thành badge màu: xanh "Đã giao", vàng "Đang xử lý", đỏ "Đã hủy". Thêm bộ lọc theo trạng thái và ô tìm theo mã đơn ở toolbar.

Bài học: đừng cố nhồi mọi cột vào tầm nhìn. Xác định 5-7 cột mà người dùng thực sự cần để quét và quyết định; mọi thứ chi tiết đẩy vào lớp thứ hai (row expand hoặc trang chi tiết). Một bảng ít cột nhưng đọc được luôn thắng một bảng "đầy đủ" nhưng phải cuộn ngang.

Ví dụ 2 — Dashboard tài chính của một startup fintech (giả định: công ty MoMoPay nội bộ)

Một analyst cần bảng so sánh doanh thu theo ngày trong 30 ngày, với các cột: ngày, số giao dịch, tổng giá trị (VND), phí thu được, tỷ lệ thành công (%). Bản đầu căn trái hết mọi cột số, không có footer. Analyst phải dùng máy tính cầm tay để cộng tổng tháng, và mất 10-15 giây mỗi lần để tìm ngày có giá trị cao nhất vì các con số không thẳng hàng.

Sau khi thiết kế lại: tất cả cột số căn phải với tabular figures; thêm tfoot hiển thị tổng số giao dịch, tổng giá trị và phí trung bình; cho phép sort theo "tổng giá trị" giảm dần để ngày đỉnh điểm nhảy lên đầu; tô nhẹ nền cho hàng có tỷ lệ thành công dưới 95% (cảnh báo trực quan). Thời gian phân tích một báo cáo giảm rõ rệt vì mắt không còn phải "dò" số.

Bài học: với dữ liệu định lượng, căn phải + tabular figures + footer tổng kết không phải tiểu tiết thẩm mỹ — chúng trực tiếp rút ngắn thời gian ra quyết định. Sort theo cột quan trọng là cách rẻ nhất để biến một bảng tĩnh thành công cụ phân tích.

Ví dụ 3 — App giao hàng xem trên điện thoại

Một công ty logistics ở TP.HCM làm app cho tài xế xem danh sách đơn cần giao. Trên desktop, bảng 6 cột rất ổn. Nhưng tài xế dùng điện thoại, và bảng 6 cột bị bóp lại đến mức không đọc nổi, hoặc phải cuộn ngang nguy hiểm khi đang chạy xe.

Giải pháp: trên mobile, bỏ layout table truyền thống, chuyển mỗi hàng thành một card. Mỗi card hiển thị mã đơn (lớn, đậm) ở trên, địa chỉ giao ở giữa, và một dòng dưới gồm khoảng cách + trạng thái + nút "Bắt đầu giao". Cấu trúc cột bị "gập" lại thành các cặp nhãn-giá trị xếp dọc. Trên màn lớn vẫn là table; dưới breakpoint mobile thì biến hình thành danh sách card.

Bài học: table không "responsive" tự nhiên. Bạn phải chọn chiến lược: (1) horizontal scroll có chủ đích cho phần cột phụ trong khi ghim cột đầu, (2) ẩn bớt cột ưu tiên thấp, hoặc (3) chuyển sang card layout trên mobile — cách thường tốt nhất cho người dùng cuối, không phải dân chuyên xem dữ liệu dày.

Hướng dẫn từng bước

Đây là quy trình thiết kế một table từ con số không:

  • Xác định "job" của bảng. Người dùng đến bảng này để làm gì? Tìm một dòng cụ thể? So sánh để xếp hạng? Quét tìm bất thường? Câu trả lời quyết định cột nào quan trọng, cần sort/filter gì.
  • Liệt kê và xếp ưu tiên cột. Viết ra tất cả thuộc tính, rồi chấm điểm. Giữ 5-7 cột ưu tiên cao hiển thị trực tiếp. Cột ưu tiên thấp: đẩy vào row expand, tooltip, hoặc trang chi tiết.
  • Quyết định kiểu dữ liệu mỗi cột và căn lề tương ứng. Text → căn trái. Number/tiền/phần trăm → căn phải, tabular figures. Ngày → căn trái hoặc phải tùy bối cảnh, nhưng định dạng nhất quán (ví dụ "27/06/2026").
  • Thiết kế header. Tiêu đề ngắn gọn, đậm nhẹ. Đánh dấu cột nào sort được. Header căn theo dữ liệu cột.
  • Chọn density và row divider. Quyết định compact hay comfortable theo đối tượng. Dùng divider nhạt hoặc zebra striping để mắt bám dòng. Đảm bảo hover state làm sáng cả dòng đang trỏ.
  • Thiết kế trạng thái đặc biệt của cell. Trạng thái → badge có màu + chữ (không chỉ màu, để người mù màu vẫn đọc được). Số âm có thể tô đỏ. Giá trị rỗng dùng "—" thay vì để trống trơn gây nhầm "thiếu dữ liệu hiển thị".
  • Thêm toolbar. Ô tìm kiếm, bộ lọc, nút export, nút chọn density. Đặt phía trên bảng, sát lề trái/phải.
  • Thiết kế các trạng thái của cả bảng. Loading (dùng skeleton — Bài 44), Empty (chưa có dữ liệu — Bài 45), Error. Một bảng thật luôn có lúc rỗng hoặc đang tải; đừng quên ba trạng thái này.
  • Lên kế hoạch responsive. Chọn chiến lược mobile: ghim cột đầu + scroll ngang, ẩn cột, hoặc chuyển card. Định nghĩa rõ ở breakpoint nào thì đổi.
  • Kiểm tra accessibility. Dùng đúng thẻ ngữ nghĩa <table>, <th scope="col">, có <caption>. Header phải đọc được bằng screen reader để người khiếm thị hiểu cell thuộc cột nào.

Lỗi thường gặp & mẹo

Lỗi 1 — Căn trái cột số. Lỗi phổ biến nhất. Số căn trái khiến không thể so sánh độ lớn bằng mắt. Luôn căn phải số và dùng tabular figures.

Lỗi 2 — Quá nhiều cột, bắt cuộn ngang. Cuộn ngang là dấu hiệu bảng cần được cắt gọt. Ưu tiên cột, đẩy phần thừa xuống lớp hai.

Lỗi 3 — Trạng thái chỉ phân biệt bằng màu. "Xanh = ok, đỏ = lỗi" vô dụng với 8% nam giới mù màu. Luôn kèm chữ hoặc icon trong badge.

Lỗi 4 — Wrap chữ tùy tiện. Để cell wrap 3-4 dòng làm bảng cao thấp lộn xộn, khó quét. Với cột text dài, dùng truncate (cắt bằng "…") kèm tooltip xem đầy đủ, hoặc giới hạn 1-2 dòng.

Lỗi 5 — Quên trạng thái loading/empty. Bảng trống trơn khi đang tải khiến người dùng tưởng app hỏng. Dùng skeleton rows lúc loading và một empty state có hướng dẫn lúc chưa có dữ liệu.

Lỗi 6 — Row action ẩn hoàn toàn vào hover. Trên mobile không có hover, và người dùng mới không đoán được phải hover. Trên cảm ứng, để action luôn hiện hoặc gom vào menu rõ ràng.

Mẹo hữu ích:

  • Ghim (sticky) hàng header khi cuộn dọc để luôn biết cột nào là cột nào.
  • Ghim cột định danh đầu tiên (mã/tên) khi cuộn ngang.
  • Đặt ô tìm kiếm ngay khi bảng có trên ~20 dòng.
  • Cho người dùng tùy chọn density nếu họ làm việc với bảng hằng ngày.
  • Giữ chiều cao dòng nhất quán để quét nhanh và để ảo giác "bảng ngay ngắn".
  • Định dạng số có dấu phân cách hàng nghìn theo chuẩn Việt Nam ("1.250.000 đ") để dễ đọc.

Bài tập thực hành

  • Audit một bảng có thật. Mở Shopee/Tiki Seller Center, Google Analytics, hoặc một admin tool bạn dùng. Chụp màn hình một table và đánh dấu: cột số có căn phải không? Trạng thái có dùng chỉ mỗi màu không? Có cuộn ngang không? Header có sort được không? Viết 5 điểm cần cải thiện.
  • Thiết kế lại bảng đơn hàng. Dựng (trên Figma hoặc giấy) một bảng "Quản lý đơn hàng" cho seller Việt Nam với các cột: mã đơn, khách hàng, ngày đặt, tổng tiền, trạng thái, hành động. Áp dụng đúng quy tắc căn lề, badge trạng thái có màu + chữ, footer tổng doanh thu, và toolbar có tìm kiếm + lọc theo trạng thái.
  • Làm phiên bản responsive. Lấy bảng ở bài 2, thiết kế phiên bản mobile bằng cách chuyển mỗi dòng thành một card. Quyết định thông tin nào nổi bật nhất (mã đơn? tổng tiền?) và đặt action ở đâu cho dễ chạm.
  • Ba trạng thái. Vẽ thêm trạng thái loading (skeleton rows), empty ("Chưa có đơn hàng nào" + nút hướng dẫn), và error cho bảng của bạn.
  • Thử thách số liệu. Tạo một bảng 30 dòng số liệu doanh thu theo ngày. So sánh hai phiên bản — căn trái không tabular figures vs. căn phải có tabular figures + footer tổng. Tự bấm giờ xem bạn tìm ngày doanh thu cao nhất nhanh hơn bao nhiêu ở phiên bản thứ hai.

Tóm tắt

Table là component "xương sống" của mọi sản phẩm có nhiều dữ liệu, và làm tốt nó là kỹ năng rất giá trị, nhất là với mảng phần mềm doanh nghiệp và internal tool tại Việt Nam. Hãy nhớ những điểm cốt lõi: chỉ dùng table khi cần so sánh dữ liệu có cấu trúc đồng nhất; nắm vững giải phẫu (header, body, cell, row, column, footer, toolbar, caption); tuân thủ quy tắc căn lề vàng — text căn trái, số căn phải với tabular figures và footer tổng kết. Đừng nhồi quá nhiều cột; ưu tiên 5-7 cột và đẩy phần còn lại xuống lớp hai. Trạng thái phải có màu kèm chữ, không bao giờ chỉ màu. Luôn thiết kế loading, empty, error. Và đặc biệt: table không tự responsive — bạn phải chủ động chọn chiến lược cuộn ngang có ghim cột, ẩn cột, hay chuyển card trên mobile. Một bảng đọc được, quét nhanh, ra quyết định nhanh luôn thắng một bảng "trông đầy đủ" nhưng rối mắt.