Menu
ESC

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

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

Đang tải...

Bài 47 — Modals, Dialogs & Drawers

Web Design Basics Bài 47/60

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

Hãy tưởng tượng bạn đang dùng app ngân hàng trên điện thoại để chuyển 5 triệu đồng. Bạn nhập số tài khoản, số tiền, rồi bấm "Chuyển khoản". Ngay lúc đó, một ô vuông nổi lên giữa màn hình, nền phía sau tối lại, hiện dòng chữ: "Bạn có chắc chắn chuyển 5.000.000đ đến Nguyễn Văn A?" với hai nút Hủy và Xác nhận. Cái ô vuông đó chính là một modal. Nó dừng mọi thứ lại, buộc bạn phải đưa ra một quyết định trước khi đi tiếp.

Modal, dialog và drawer là ba thành phần giao diện cực kỳ phổ biến nhưng cũng là ba thứ bị lạm dụng nhiều nhất trong thiết kế web. Một designer mới thường có xu hướng "cái gì cũng nhét vào modal" — báo lỗi cũng modal, quảng cáo cũng modal, đăng ký newsletter cũng modal. Kết quả là người dùng bực bội, đóng vội, và đôi khi rời bỏ luôn website.

Trong bài này, tôi sẽ giúp bạn hiểu rõ bản chất của ba thành phần này: chúng khác nhau ở đâu, khi nào nên dùng, khi nào tuyệt đối KHÔNG nên dùng, và cách thiết kế chúng cho đúng chuẩn — từ kích thước, vị trí, hành vi đóng/mở cho đến những chi tiết nhỏ mà người dùng cảm nhận được dù không gọi tên ra. Đây là kiến thức nền tảng mà bất kỳ ai làm UI/UX cũng phải nắm vững.

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

Modal là gì và tại sao nó "chặn"

Modal (đôi khi gọi là modal dialog) là một lớp nội dung nổi lên trên giao diện chính, và quan trọng nhất: nó chặn tương tác với phần còn lại của trang cho đến khi người dùng xử lý xong. Đặc trưng kỹ thuật của modal:

  • Overlay (lớp phủ mờ): một lớp nền tối, thường đen với độ trong suốt khoảng 40–60%, phủ lên toàn bộ trang phía sau. Lớp này vừa làm nổi bật modal, vừa báo hiệu trực quan rằng "phần dưới đang bị khóa".
  • Focus trap (bẫy focus): khi modal mở, bàn phím và con trỏ chỉ di chuyển được bên trong modal. Người dùng nhấn Tab không thể nhảy ra các thành phần phía sau.
  • Tính độc chiếm (modal nghĩa là "modal" — bắt buộc một chế độ): bạn không thể bỏ qua nó để làm việc khác. Phải xử lý xong mới đi tiếp.
Chính vì tính chặn này, modal là công cụ "nặng đô". Nó cắt ngang dòng suy nghĩ của người dùng, nên chỉ dùng khi thật sự cần sự chú ý tuyệt đối.

Dialog là gì — và sự khác biệt tinh tế với modal

Trong thực tế công việc, nhiều người dùng từ "modal" và "dialog" thay thế cho nhau, nhưng có một phân biệt hữu ích:

  • Dialog là khái niệm rộng hơn, chỉ một hộp hội thoại giữa hệ thống và người dùng. Dialog có thể là modal dialog (chặn) hoặc non-modal dialog / modeless (không chặn — người dùng vẫn thao tác được với phần còn lại).
  • Một ví dụ về non-modal dialog là hộp "Find and Replace" trong trình soạn thảo: nó nổi lên nhưng bạn vẫn gõ và cuộn tài liệu được.
Trong thiết kế web hiện đại, phần tử HTML <dialog> đã được chuẩn hóa, hỗ trợ cả hai chế độ: gọi .showModal() để mở dạng chặn, hoặc .show() để mở dạng không chặn. Hiểu phân biệt này giúp bạn chọn đúng hành vi thay vì mặc định cái gì cũng chặn.

Drawer là gì

Drawer (ngăn kéo) là một panel trượt ra từ một cạnh màn hình — thường là trái, phải, hoặc dưới. Khác với modal xuất hiện ở giữa, drawer "neo" vào một cạnh và trượt vào như một ngăn kéo bàn.

Drawer phù hợp với:

  • Menu điều hướng trên mobile (trượt từ trái) — đây là ứng dụng kinh điển nhất.
  • Bộ lọc sản phẩm trên trang thương mại điện tử (trượt từ phải).
  • Giỏ hàng mini (mini-cart) trượt từ phải khi bấm "Thêm vào giỏ".
  • Form phụ hoặc panel chi tiết không cần chiếm toàn màn hình.
Drawer có thể là modal (kèm overlay, chặn nền) hoặc non-modal. Trên desktop, drawer bộ lọc thường non-modal để người dùng vừa chỉnh lọc vừa thấy kết quả thay đổi; trên mobile thì thường modal vì không gian hẹp.

Khi nào dùng modal?

Modal chỉ nên xuất hiện trong ba nhóm tình huống:

  • Xác nhận hành động quan trọng, khó hoàn tác: xóa tài khoản, xóa dữ liệu, thanh toán, hủy đơn hàng. Đây là lúc bạn cần người dùng dừng lại và xác nhận có chủ đích.
  • Tác vụ tập trung ngắn: đăng nhập, đăng ký nhanh, một form nhỏ vài trường mà không đáng để chuyển sang trang mới. Modal giữ ngữ cảnh — người dùng làm xong quay lại đúng chỗ cũ.
  • Thông tin bắt buộc phải đọc/đồng ý: chấp nhận điều khoản dịch vụ, xác nhận tuổi, cảnh báo pháp lý. Những thứ mà việc người dùng "lỡ bỏ qua" sẽ gây hậu quả.

Khi nào KHÔNG dùng modal?

Đây là phần quan trọng nhất mà ghi chú gốc bỏ lửng — tôi sẽ làm rõ. KHÔNG dùng modal khi:

  • Thông tin không khẩn cấp: thông báo "đã lưu thành công" nên dùng toast (thông báo tự biến mất), không phải modal buộc người dùng bấm đóng.
  • Nội dung dài, cần cuộn nhiều: nếu nội dung dài như một trang riêng, hãy cho nó một trang riêng. Modal cuộn dài là trải nghiệm tệ.
  • Quảng cáo / mời đăng ký newsletter ngay khi vừa vào trang: đây là kiểu lạm dụng bị ghét nhất, và Google còn phạt SEO với "intrusive interstitial" trên mobile.
  • Modal mở modal mở modal: chồng nhiều lớp khiến người dùng lạc lối, không biết bấm gì để thoát.
  • Form nhiều bước, phức tạp: nên dùng trang riêng hoặc wizard nhiều trang.
Nguyên tắc vàng: modal làm gián đoạn — chỉ gián đoạn khi sự gián đoạn đó đáng giá hơn dòng chảy hiện tại của người dùng.

Tình huống thực tế

Ví dụ 1 — Tiki và modal xác nhận hủy đơn

Trên Tiki, khi người dùng vào mục đơn hàng và bấm "Hủy đơn", hệ thống không hủy ngay. Một modal nổi lên: nền tối lại, hiện thông tin đơn hàng, lý do hủy (dropdown chọn), và hai nút "Không, giữ đơn" với "Xác nhận hủy". Nút hủy được tô màu cảnh báo, nút giữ đơn là nút phụ.

Diễn giải: đây là ví dụ chuẩn mực. Hủy đơn là hành động khó hoàn tác (đơn đã xử lý có thể không khôi phục được), nên modal chặn là hợp lý. Tiki còn thêm bước hỏi lý do — vừa giữ người dùng lại một nhịp để cân nhắc, vừa thu thập dữ liệu kinh doanh. Quan trọng: nút mặc định an toàn ("giữ đơn") được đặt nổi bật hơn để tránh người dùng vô tình xác nhận hủy.

Bài học rút ra: với hành động phá hủy, modal nên đặt nút an toàn làm lựa chọn dễ bấm nhất, và mô tả rõ hậu quả ("đơn đã hủy không thể khôi phục").

Ví dụ 2 — Shopee và drawer bộ lọc trên mobile

Trên app/web mobile của Shopee, khi bạn xem danh sách sản phẩm và bấm "Bộ lọc", một drawer trượt từ phải (hoặc từ dưới lên, tùy phiên bản) chứa tất cả tùy chọn: khoảng giá, đánh giá, địa điểm, dịch vụ. Bạn chọn xong bấm "Áp dụng" ở cuối drawer, nó đóng lại và danh sách cập nhật.

Diễn giải: Shopee không dùng modal giữa màn hình cho bộ lọc, vì bộ lọc có nhiều tùy chọn cần không gian dọc dài. Drawer cho phép tận dụng toàn bộ chiều cao màn hình, lại có cảm giác "panel phụ" nhẹ nhàng hơn modal. Nút "Áp dụng" cố định ở đáy (sticky) để người dùng cuộn bao xa vẫn bấm được.

Bài học rút ra: với panel nhiều nội dung và mang tính "công cụ phụ" (filter, menu, giỏ hàng), drawer là lựa chọn tốt hơn modal giữa màn hình. Luôn cố định nút hành động chính ở đáy drawer khi nội dung dài.

Ví dụ 3 — Một startup fintech Việt và bài học lạm dụng modal

Một startup ví điện tử (giả định, gọi là PayViet) từng tung chiến dịch khuyến mãi và cài modal toàn màn hình bật lên ngay khi người dùng mở app, quảng cáo voucher. Tệ hơn, nút đóng (dấu X) cố tình để nhỏ và mờ ở góc trên. Sau hai tuần, đội ngũ phát hiện tỷ lệ thoát app trong 5 giây đầu tăng 18%, và lượng đánh giá 1 sao trên CH Play tăng vọt với từ khóa "quảng cáo phiền".

Họ thay đổi: bỏ modal chặn, chuyển khuyến mãi thành một banner có thể vuốt bỏ ở đầu trang chủ. Tỷ lệ thoát giảm về mức cũ, và tỷ lệ click vào voucher thực tế còn tăng nhẹ vì người dùng không còn cảm giác bị ép.

Diễn giải: modal chặn dùng cho mục đích marketing không khẩn cấp gần như luôn phản tác dụng. Người dùng cảm nhận sự ép buộc và phản ứng tiêu cực.

Bài học rút ra: đừng dùng modal để "cướp" sự chú ý cho nội dung mà người dùng không yêu cầu. Nội dung marketing nên dùng banner, toast, hoặc inline — những thứ người dùng có thể phớt lờ.

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

Đây là quy trình thiết kế một modal/drawer đúng chuẩn:

Bước 1 — Xác định có thật sự cần chặn không. Tự hỏi: nếu người dùng bỏ qua thành phần này và đi tiếp, có hậu quả nghiêm trọng không? Nếu KHÔNG, dùng toast/banner/inline thay vì modal. Nếu CÓ, tiếp tục.

Bước 2 — Chọn dạng phù hợp. Quyết định quan trọng cần xác nhận tập trung → modal giữa màn hình. Panel công cụ phụ, menu, filter, nội dung dài kiểu danh sách → drawer. Nội dung cực ngắn (xác nhận yes/no) → dialog nhỏ gọn.

Bước 3 — Thiết kế cấu trúc. Một modal chuẩn gồm: tiêu đề rõ ràng (nói rõ đang làm gì), nội dung/form ở giữa, vùng hành động ở đáy với các nút. Đặt nút hành động chính (primary) bên phải, nút hủy/phụ bên trái hoặc cạnh nó. Luôn có nút đóng (X) ở góc trên phải.

Bước 4 — Xử lý kích thước và responsive. Trên desktop, đặt chiều rộng tối đa (max-width khoảng 400–600px cho dialog xác nhận, lớn hơn cho form) và căn giữa. Trên mobile, modal nên gần như chiếm toàn chiều rộng (chừa lề nhỏ 16px), và drawer thường full-screen hoặc trượt từ dưới (bottom sheet) — phù hợp ngón tay cái hơn.

Bước 5 — Thiết kế hành vi đóng. Cho phép đóng bằng nhiều cách: bấm nút X, bấm nút Hủy, nhấn phím Esc, và bấm ra vùng overlay bên ngoài. NGOẠI LỆ: với hành động khó hoàn tác hoặc form đang nhập dở, cân nhắc tắt "bấm overlay để đóng" để tránh mất dữ liệu do bấm nhầm — thay vào đó hỏi "Bạn có chắc muốn thoát? Dữ liệu chưa lưu sẽ mất".

Bước 6 — Thêm overlay và hiệu ứng. Overlay tối khoảng 50%. Modal nên có animation xuất hiện nhẹ (mờ dần + phóng to nhẹ hoặc trượt lên), thời lượng 150–250ms. Drawer trượt từ cạnh tương ứng. Animation quá chậm (>400ms) khiến người dùng sốt ruột.

Bước 7 — Đảm bảo accessibility (a11y). Đây là phần hay bị bỏ quên. Khi modal mở: chuyển focus vào modal (thường vào nút đầu tiên hoặc nút an toàn), giữ focus trap bên trong, gắn thuộc tính role="dialog"aria-modal="true", liên kết tiêu đề bằng aria-labelledby. Khi đóng: trả focus về đúng nút đã mở nó. Khóa cuộn nền (body scroll lock) để nền không cuộn khi modal mở.

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

Lỗi 1 — Không khóa cuộn nền. Khi modal mở mà người dùng cuộn, trang nền cuộn theo phía sau overlay. Trông cực kỳ thiếu chuyên nghiệp. Mẹo: thêm overflow: hidden vào body khi modal mở, gỡ ra khi đóng.

Lỗi 2 — Quên xử lý phím Esc và focus. Người dùng bàn phím và người dùng trình đọc màn hình bị kẹt trong modal không thoát được. Luôn cho Esc đóng modal (trừ trường hợp bắt buộc xác nhận) và quản lý focus đúng.

Lỗi 3 — Nút hành động mơ hồ. Nút ghi "OK" / "Cancel" không nói rõ điều gì sẽ xảy ra. Mẹo: dùng nhãn nút theo động từ cụ thể — "Xóa vĩnh viễn", "Lưu thay đổi", "Thoát không lưu". Người dùng đọc nhãn nút là biết hậu quả mà không cần đọc lại cả đoạn.

Lỗi 4 — Modal quá nhiều nội dung. Khi modal phải cuộn dài lê thê, đó là dấu hiệu nội dung nên ở trang riêng. Mẹo: nếu nội dung vượt quá khoảng 80% chiều cao màn hình thường xuyên, cân nhắc chuyển sang trang đầy đủ.

Lỗi 5 — Chồng nhiều modal. Modal A mở modal B mở modal C. Người dùng mất phương hướng. Mẹo: tránh chồng lớp; nếu cần nhiều bước, dùng nội dung nhiều bước (multi-step) ngay trong một modal với nút "Tiếp/Quay lại".

Lỗi 6 — Nút đóng (X) khó tìm hoặc cố tình giấu. Như ví dụ PayViet, giấu nút đóng làm mất niềm tin. Mẹo: nút X luôn rõ ràng ở góc trên phải, vùng bấm đủ lớn (tối thiểu 44x44px cho cảm ứng).

Mẹo cộng thêm — Z-index có chủ đích. Modal phải nằm trên mọi thứ. Đặt z-index cao và nhất quán trong hệ thống (ví dụ overlay 1000, modal 1010, toast 1020 để toast nổi cả trên modal). Quản lý z-index bằng biến CSS để tránh "cuộc chiến z-index".

Mẹo cộng thêm — Bottom sheet cho mobile. Trên điện thoại, drawer trượt từ dưới lên (bottom sheet) thường tốt hơn modal giữa màn hình vì gần ngón cái, dễ vuốt xuống để đóng — đây là pattern Google Material và nhiều app Việt như MoMo, ZaloPay áp dụng rộng rãi.

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

  • Phân loại tình huống: Cho 6 tình huống sau, quyết định nên dùng modal, drawer, toast, hay trang riêng — và giải thích lý do: (a) thông báo "đã thêm vào giỏ hàng", (b) xác nhận xóa ảnh đại diện, (c) menu điều hướng trên mobile, (d) form đăng ký tài khoản 8 trường + xác minh OTP, (e) chấp nhận điều khoản trước khi dùng dịch vụ lần đầu, (f) bộ lọc sản phẩm 12 tùy chọn trên web mobile.
  • Thiết kế lại một modal tệ: Tìm một website hoặc app Việt Nam có modal mà bạn thấy phiền (gợi ý: các modal khuyến mãi bật lên khi vừa vào trang). Chụp màn hình, chỉ ra 3 vấn đề (ví dụ: chặn không cần thiết, nút đóng khó tìm, nội dung không khẩn cấp), rồi đề xuất phương án thay thế đúng hơn.
  • Vẽ wireframe một drawer bộ lọc: Thiết kế drawer bộ lọc cho một trang bán giày online. Yêu cầu: trượt từ phải trên desktop, từ dưới lên trên mobile, nút "Áp dụng" và "Xóa lọc" cố định ở đáy, có hiển thị số lượng bộ lọc đang chọn. Vẽ tay hoặc dùng Figma cũng được.
  • Checklist accessibility: Viết một checklist gồm 6 mục bạn sẽ kiểm tra cho mọi modal trước khi bàn giao (gợi ý: focus trap, Esc đóng, trả focus, khóa cuộn nền, role/aria, nhãn nút rõ). Lưu lại để dùng cho các dự án sau.

Tóm tắt

Modal, dialog và drawer đều là cách đưa nội dung nổi lên trên giao diện chính, nhưng khác nhau về bản chất: modal chặn và đòi quyết định, drawer trượt từ cạnh cho panel phụ/menu/filter, còn dialog là khái niệm rộng có thể chặn hoặc không chặn.

Dùng modal khi: xác nhận hành động khó hoàn tác, tác vụ tập trung ngắn, hoặc thông tin bắt buộc phải đồng ý. KHÔNG dùng modal cho: thông báo không khẩn (dùng toast), nội dung dài (dùng trang riêng), và đặc biệt là quảng cáo bật lên (gây bực bội và bị phạt SEO).

Khi thiết kế, hãy nhớ: tiêu đề rõ, nhãn nút theo động từ cụ thể, nút an toàn nổi bật với hành động phá hủy, đóng được bằng X/Esc/overlay (trừ khi có lý do giữ lại), khóa cuộn nền, và làm đúng accessibility với focus trap. Trên mobile, ưu tiên bottom sheet và drawer full-width.

Nguyên tắc cuối cùng để bạn ghi nhớ: mỗi lần bạn định bật một modal, hãy tự hỏi — sự gián đoạn này có thật sự đáng giá với người dùng không? Nếu câu trả lời do dự, gần như chắc chắn bạn nên chọn một cách nhẹ nhàng hơn.