Menu
ESC

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

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

Đang tải...

Bài 45 — Empty States — Khi không có dữ liệu

Web Design Basics Bài 45/60

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

Hãy hình dung bạn vừa tải một ứng dụng quản lý chi tiêu mới. Bạn mở app lần đầu, và màn hình hiện ra... một khoảng trắng mênh mông. Không có gì cả. Không một dòng chữ, không một nút bấm, không một gợi ý. Bạn ngồi đó, bối rối, tự hỏi: "App này bị lỗi à? Mình phải làm gì tiếp theo đây?"

Đó chính là cảm giác mà một empty state (trạng thái rỗng) tồi tệ mang lại. Và đáng buồn là rất nhiều designer Việt Nam — kể cả những người làm việc nhiều năm — vẫn bỏ quên hoàn toàn phần này khi thiết kế. Họ dồn tâm huyết vào màn hình "lý tưởng" khi mọi thứ đầy ắp dữ liệu, đẹp đẽ và hoàn hảo. Nhưng trong thực tế, người dùng gặp empty state rất nhiều lần trong vòng đời sử dụng sản phẩm.

Empty state không phải là một lỗi cần che giấu. Nó là một cơ hội thiết kế vàng. Đây là khoảnh khắc bạn có thể dẫn dắt người dùng, dạy họ cách dùng sản phẩm, trấn an họ khi tìm kiếm không ra kết quả, hoặc thậm chí biến một tình huống "không có gì" thành một trải nghiệm thú vị. Một empty state tốt giảm tỉ lệ bỏ cuộc (drop-off), tăng tỉ lệ kích hoạt (activation), và để lại ấn tượng rằng sản phẩm này được làm bởi những người thực sự quan tâm đến người dùng.

Trong bài này, chúng ta sẽ đi sâu vào bốn loại empty state phổ biến, cách thiết kế component cho từng loại, và những lỗi mà tôi thấy hầu hết các bạn mới đều mắc phải. Đây là kỹ năng phân biệt giữa một giao diện "tạm được" và một giao diện thực sự chuyên nghiệp.

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

Empty state là trạng thái của một màn hình hoặc một khu vực giao diện khi không có dữ liệu để hiển thị. Nghe có vẻ đơn giản, nhưng "không có dữ liệu" thực ra đến từ nhiều nguyên nhân khác nhau — và mỗi nguyên nhân đòi hỏi một cách thiết kế hoàn toàn khác. Hiểu sai loại empty state sẽ dẫn đến thông điệp sai và làm người dùng hoang mang.

Bốn loại empty state bạn phải phân biệt

1. First-time use — Lần đầu sử dụng (chưa có data)

Đây là khi người dùng mới hoàn toàn, chưa tạo ra bất kỳ dữ liệu nào. Ví dụ: danh sách công việc trống vì họ chưa thêm task nào, giỏ hàng trống vì chưa mua gì, hộp thư trống vì chưa có tin nhắn.

Đây là loại tích cực nhất và quan trọng nhất. Nó không phải là vấn đề — nó là điểm khởi đầu. Mục tiêu của bạn ở đây là dẫn dắt và động viên. Hãy giải thích khu vực này dùng để làm gì, và đưa ra một hành động rõ ràng để người dùng bắt đầu. Đây là cơ hội onboarding ngầm tuyệt vời.

2. No search results — Tìm kiếm không ra kết quả

Người dùng gõ một từ khóa, nhấn Enter, và... không có gì khớp. Đây là tình huống có thể gây bực bội nếu xử lý kém. Mục tiêu của bạn là trấn an và đề xuất lối thoát: gợi ý người dùng kiểm tra lại chính tả, thử từ khóa khác, hoặc xóa bộ lọc. Tuyệt đối đừng để người dùng cảm thấy như họ vừa làm sai điều gì.

3. No results after filtering — Bộ lọc loại bỏ hết items

Khác với tìm kiếm, ở đây người dùng đã chủ động áp dụng các bộ lọc (filter) — ví dụ "sản phẩm dưới 100k, màu đỏ, còn hàng" — và kết quả là rỗng. Điểm mấu chốt: dữ liệu vẫn tồn tại, chỉ là bộ lọc đang quá khắt khe. Vì vậy giải pháp luôn phải có nút "Xóa bộ lọc" (Clear filters) để đưa người dùng quay lại trạng thái đầy đủ dữ liệu.

4. Error / offline — Lỗi hoặc mất kết nối

Đây thực ra là một trường hợp đặc biệt: màn hình rỗng không phải vì không có data, mà vì hệ thống không lấy được data. Có thể do mất mạng, server lỗi, hoặc request thất bại. Điều quan trọng là phải phân biệt rõ với ba loại trên — vì thông điệp ở đây phải là "có gì đó trục trặc" kèm nút Thử lại (Retry), chứ không phải "bạn chưa có dữ liệu".

Cấu trúc của một empty state component

Một empty state được thiết kế tốt thường gồm các thành phần sau, sắp xếp theo trục dọc và căn giữa:

  • Hình minh họa hoặc icon (illustration/icon): Một hình ảnh nhẹ nhàng giúp lấp đầy khoảng trống về mặt thị giác và truyền tải cảm xúc. Không bắt buộc, nhưng rất hiệu quả.
  • Tiêu đề (headline): Một dòng ngắn gọn, rõ ràng, nêu bản chất tình huống. Ví dụ: "Bạn chưa có đơn hàng nào".
  • Mô tả phụ (supporting text): Một đến hai câu giải thích thêm và định hướng. Đây là nơi bạn xóa tan bối rối.
  • Hành động chính (primary action / CTA): Một nút bấm dẫn người dùng đến bước tiếp theo. Đây là phần quan trọng nhất mà nhiều người quên.
Không phải mọi empty state đều cần đủ bốn thành phần. Một empty state của filter có thể chỉ cần text + nút "Xóa bộ lọc". Nhưng nguyên tắc bất biến là: luôn phải có một lối ra rõ ràng.

Tình huống thực tế

Ví dụ 1 — Shopee và bài học "đừng để giỏ hàng trống lặng câm"

Hãy nhìn vào màn hình giỏ hàng trống của các sàn thương mại điện tử lớn như Shopee hay Lazada tại Việt Nam. Khi bạn mở giỏ hàng mà chưa thêm sản phẩm nào, bạn không bao giờ thấy một màn hình trắng trơn. Thay vào đó, bạn thấy một hình minh họa giỏ hàng dễ thương, dòng chữ "Giỏ hàng của bạn còn trống", và quan trọng nhất — một nút lớn màu cam "Mua sắm ngay" dẫn thẳng về trang chủ hoặc trang flash sale.

Đây là first-time use empty state được làm đúng bài. Hãy phân tích logic phía sau: với một sàn TMĐT, mỗi giây người dùng nhìn vào giỏ hàng trống mà không biết làm gì là một giây có nguy cơ thoát app. Nếu chỉ hiển thị "Giỏ hàng trống" rồi để đó, bạn đã đẩy gánh nặng "phải tự tìm đường" sang người dùng. Nút "Mua sắm ngay" biến một ngõ cụt thành một con đường — và con đường đó dẫn thẳng tới doanh thu.

Bài học rút ra: Empty state của những khu vực có giá trị thương mại (giỏ hàng, danh sách yêu thích, lịch sử mua) phải luôn có một CTA dẫn người dùng quay lại "vòng" tạo giá trị. Đừng bao giờ để một empty state trở thành ngõ cụt.

Ví dụ 2 — Tiki và empty state khi lọc sản phẩm quá chặt

Giả sử bạn đang lướt Tiki tìm tai nghe. Bạn áp dụng bộ lọc: thương hiệu Sony, giá dưới 200.000đ, đánh giá từ 5 sao. Kết quả: không có sản phẩm nào khớp (vì tai nghe Sony hiếm khi dưới 200k). Một sàn thiết kế tốt sẽ không hiển thị màn hình trắng, mà sẽ nói: "Không tìm thấy sản phẩm phù hợp với bộ lọc của bạn" kèm nút "Xóa tất cả bộ lọc" và có thể gợi ý "Thử nới lỏng mức giá".

Điểm tinh tế ở đây: hệ thống biết rằng dữ liệu tai nghe Sony vẫn tồn tại — chỉ là khoảng giá đang chặn hết. Vì vậy giải pháp đúng không phải bảo người dùng "thử từ khóa khác" (đó là cách xử lý của no-search-result), mà là cho họ một cú nhấn để gỡ bỏ rào cản mà chính họ vừa dựng lên. Nếu thiếu nút "Xóa bộ lọc", người dùng sẽ phải mở lại từng bộ lọc và bỏ chọn thủ công — một trải nghiệm cực kỳ ức chế trên màn hình điện thoại nhỏ.

Bài học rút ra: Empty state của filter phải luôn cung cấp đường tắt để hoàn tác bộ lọc. Phân biệt rạch ròi giữa "không có kết quả tìm kiếm" và "bộ lọc quá chặt" — vì hành động đề xuất là khác nhau.

Ví dụ 3 — Ứng dụng ngân hàng và empty state khi mất mạng

Một ngân hàng số tại Việt Nam, gọi tạm là "VBank", có màn hình lịch sử giao dịch. Trong điều kiện bình thường, màn hình này đầy ắp các dòng giao dịch. Nhưng giả sử người dùng đang ở khu vực sóng yếu, app không tải được dữ liệu. Nếu đội thiết kế lười, màn hình sẽ trắng trơn — và người dùng lập tức hoảng: "Tiền của mình đâu rồi? Giao dịch biến mất hết à?"

Đây là lý do error/offline state phải được thiết kế khác hẳn empty state thông thường. VBank xử lý đúng bằng cách hiển thị icon "mất kết nối", dòng chữ "Không thể tải dữ liệu. Vui lòng kiểm tra kết nối mạng", và nút "Thử lại". Thông điệp này nói rõ: vấn đề nằm ở kết nối, không phải dữ liệu của bạn đã mất. Sự khác biệt nhỏ này có thể là khác biệt giữa một người dùng bình tĩnh nhấn "Thử lại" và một người dùng hoảng loạn gọi tổng đài.

Bài học rút ra: Với các sản phẩm liên quan đến tiền bạc, sức khỏe hay dữ liệu nhạy cảm, error state phải trấn an tuyệt đối và không bao giờ được nhầm lẫn với "bạn không có dữ liệu". Một nút Retry là bắt buộc.

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

Đây là quy trình tôi khuyên bạn áp dụng mỗi khi thiết kế một màn hình mới.

Bước 1 — Liệt kê mọi trạng thái rỗng có thể xảy ra. Với mỗi màn hình hiển thị danh sách hay dữ liệu, hãy tự hỏi: "Khi nào khu vực này sẽ trống?" Vẽ ra cả bốn khả năng: lần đầu dùng, tìm kiếm không ra, lọc không ra, và lỗi/offline. Không phải màn hình nào cũng có đủ bốn, nhưng bạn phải chủ động kiểm tra.

Bước 2 — Xác định thông điệp cốt lõi cho từng trạng thái. Trả lời ba câu hỏi: (a) Người dùng đang thấy gì? (b) Tại sao lại trống? (c) Họ nên làm gì tiếp theo? Câu trả lời cho (c) chính là CTA của bạn.

Bước 3 — Viết nội dung (copy) trước, thiết kế hình sau. Đây là mẹo của dân chuyên nghiệp. Hãy viết tiêu đề và mô tả bằng ngôn ngữ con người, ngắn gọn, ấm áp. Ví dụ thay vì "No data available", hãy viết "Bạn chưa lưu công thức nào. Hãy bắt đầu khám phá!". Nội dung quyết định cảm xúc nhiều hơn hình ảnh.

Bước 4 — Chọn cấp độ hình ảnh phù hợp. Empty state quan trọng (như onboarding, giỏ hàng) xứng đáng có illustration riêng. Empty state nhỏ trong một widget có thể chỉ cần một icon đơn giản. Đừng dùng illustration to đùng cho một ô tìm kiếm nhỏ — nó sẽ trông nặng nề và lạc lõng.

Bước 5 — Thiết kế CTA rõ ràng và đúng hành động. Với first-time use, CTA là hành động tạo dữ liệu ("Thêm task đầu tiên"). Với filter, CTA là "Xóa bộ lọc". Với error, CTA là "Thử lại". Đảm bảo nút này nổi bật và là điểm dừng tự nhiên của mắt.

Bước 6 — Căn giữa và cho khoảng thở. Empty state thường được căn giữa cả chiều ngang lẫn dọc trong vùng chứa, với khoảng cách (spacing) thoáng đãng giữa các thành phần. Điều này tạo cảm giác cố ý, có chủ đích — chứ không phải "màn hình bị lỗi nên trống".

Bước 7 — Kiểm tra trên thiết bị thật. Đảm bảo empty state không bị che bởi bàn phím ảo, hiển thị tốt trên màn hình nhỏ, và CTA luôn nằm trong tầm với của ngón tay cái.

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

Lỗi 1 — Quên thiết kế empty state hoàn toàn. Đây là lỗi phổ biến nhất. Designer chỉ giao file Figma với màn hình "đầy data". Khi dev code xong, người dùng mới mở app lần đầu thấy màn hình trắng. Mẹo: coi empty state là một phần bắt buộc của mọi màn hình danh sách, ghi nó vào checklist bàn giao.

Lỗi 2 — Dùng một empty state chung cho tất cả tình huống. Hiển thị "Không có dữ liệu" cho cả lần đầu dùng, lọc không ra, lẫn lỗi mạng. Mỗi tình huống cần thông điệp và CTA khác nhau. Gộp chung khiến người dùng bối rối — họ không biết là mình chưa có data, hay app bị lỗi.

Lỗi 3 — Copy quá kỹ thuật và lạnh lùng. "Error 404: Resource not found" hay "Query returned 0 rows" là ngôn ngữ của lập trình viên, không phải của người dùng. Hãy dịch sang tiếng người: "Chúng tôi không tìm thấy gì khớp với "..." — thử kiểm tra lại chính tả nhé?".

Lỗi 4 — Thiếu CTA, biến empty state thành ngõ cụt. Một empty state không có lối ra là một empty state thất bại. Luôn tự hỏi: "Sau khi đọc xong, người dùng nhấn vào đâu?"

Lỗi 5 — Đổ lỗi cho người dùng. Tránh giọng văn như "Bạn đã nhập sai" hoặc "Tìm kiếm của bạn không hợp lệ". Hãy luôn đứng về phía người dùng: "Hmm, không có kết quả nào. Thử từ khóa khác xem sao?"

Mẹo nâng cao — Tận dụng empty state để giáo dục. Notion làm rất hay: khi bạn mở một trang trống, họ không chỉ nói "trang trống" mà còn gợi ý các template, phím tắt gõ "/" để thêm block. Empty state trở thành một bài học sử dụng sản phẩm. Đây là tư duy "biến khoảng trống thành cơ hội".

Mẹo về tông giọng — Thêm chút cá tính khi phù hợp. Một dòng chữ hài hước nhẹ nhàng ("Trống trơn như ví cuối tháng! Thêm gì đó vào nhé") có thể tạo thiện cảm. Nhưng cẩn thận: tuyệt đối không đùa cợt trong error state nghiêm trọng (mất tiền, mất dữ liệu) — lúc đó người dùng đang lo lắng, sự hài hước sẽ phản tác dụng.

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

Bài 1 — Audit một app bạn dùng hàng ngày. Mở một ứng dụng bất kỳ (MoMo, Grab, Shopee...) và cố tình tạo ra các empty state: tìm kiếm một từ vô nghĩa, bật chế độ máy bay rồi tải lại trang, mở một mục bạn chưa từng dùng. Chụp màn hình lại và đánh giá: Họ thiết kế đủ bốn loại chưa? CTA có rõ không? Copy có thân thiện không?

Bài 2 — Thiết kế ba empty state cho một app to-do list. Vẽ trên giấy hoặc Figma ba màn hình: (a) Lần đầu dùng, chưa có task nào. (b) Đã lọc "task quá hạn" nhưng không có cái nào. (c) Mất mạng không tải được danh sách. Mỗi màn hình phải có đủ tiêu đề, mô tả, và CTA đúng với tình huống. So sánh ba bản — bạn sẽ thấy rõ chúng phải khác nhau thế nào.

Bài 3 — Viết lại copy. Lấy năm thông điệp empty state khô khan sau và viết lại cho thân thiện, đúng tiếng Việt tự nhiên: "No data", "0 results", "Empty", "Nothing here", "Failed to load". Với mỗi cái, ghi rõ nó thuộc loại empty state nào và CTA đi kèm là gì.

Tóm tắt

Empty state không phải là "phần thừa" của giao diện — nó là một phần thiết yếu mà người dùng gặp rất thường xuyên, đặc biệt trong những khoảnh khắc quan trọng như lần đầu mở app. Hãy nhớ bốn loại cốt lõi: first-time use (dẫn dắt và động viên), no search results (trấn an và gợi ý), no filter results (cung cấp nút xóa bộ lọc), và error/offline (giải thích sự cố kèm nút thử lại). Mỗi loại có thông điệp và hành động riêng, không được gộp chung.

Một empty state tốt luôn có cấu trúc rõ ràng — hình minh họa hoặc icon, tiêu đề, mô tả, và đặc biệt là một CTA dẫn lối — được căn giữa và cho khoảng thở thoáng đãng. Hãy viết copy bằng ngôn ngữ con người, ấm áp, đứng về phía người dùng, và không bao giờ biến màn hình trống thành ngõ cụt. Như các ví dụ từ Shopee, Tiki và app ngân hàng cho thấy, khác biệt giữa một empty state cẩu thả và một empty state chỉn chu chính là khác biệt giữa người dùng bỏ đi và người dùng ở lại. Từ giờ, mỗi khi thiết kế một màn hình danh sách, hãy luôn tự hỏi: "Khi không có gì ở đây, người dùng sẽ thấy gì?"