Menu
ESC

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

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

Đang tải...

Bài 19 — Elevation, Shadows & Depth

UI Design and Design Handoff Bài 19/60

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

Hãy thử một bài kiểm tra nhanh. Bạn mở một màn hình app bất kỳ trên điện thoại, nheo mắt lại cho hình ảnh hơi mờ đi. Bạn sẽ nhận ra ngay: một số phần tử như "nổi lên" phía trên, một số phần tử "chìm" xuống nền. Nút bấm nổi bật, thẻ card nhô lên, menu thả xuống che phủ nội dung bên dưới. Cái cảm giác "tầng lớp" đó không phải ngẫu nhiên — nó được thiết kế có chủ đích, và công cụ chính tạo ra nó chính là elevation (độ cao) và shadow (bóng đổ).

Elevation là một trong những khái niệm bị hiểu sai nhiều nhất bởi designer mới vào nghề. Rất nhiều bạn nghĩ bóng đổ chỉ là "trang trí cho đẹp", nên đổ bóng tùy hứng: chỗ này blur 4px, chỗ kia blur 20px, màu bóng khi thì đen đặc khi thì xám nhạt, chẳng theo quy luật nào. Kết quả là giao diện trông rối, thiếu chuyên nghiệp, và tệ hơn — nó gửi tín hiệu sai cho người dùng về việc phần tử nào quan trọng, phần tử nào bấm được.

Trong bài này, chúng ta sẽ hiểu elevation như một hệ thống truyền đạt thông tin, không phải hiệu ứng trang trí. Bạn sẽ học cách Material Design mô hình hóa không gian ba chiều trên màn hình phẳng, cách xây một thang elevation nhất quán, cách một bóng đổ "thật" được tạo nên từ hai lớp bóng, và cách áp dụng tất cả vào Figma để bàn giao cho developer. Đây là kiến thức nền tảng cho gần như mọi component bạn sẽ dựng sau này — button, card, modal, dropdown đều dựa vào nó.

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

Elevation là gì và tại sao nó tồn tại

Màn hình của chúng ta phẳng — chỉ có trục X (ngang) và trục Y (dọc). Nhưng bộ não con người quen với thế giới ba chiều, nơi mọi vật đều có độ sâu. Elevation là cách chúng ta "mượn" trục Z (chiều sâu) để đưa vào giao diện phẳng: mỗi phần tử được gán một độ cao ảo tính bằng đơn vị dp (density-independent pixels) — ví dụ nền là 0dp, card là 1dp, nút nổi là 6dp, modal là 24dp.

Material Design của Google là hệ thống đầu tiên chuẩn hóa ý tưởng này thành một mô hình chặt chẽ. Hình dung tất cả các phần tử UI nằm trên những tấm giấy xếp chồng, được chiếu sáng bởi một nguồn sáng ảo đặt phía trên. Tấm giấy nào cao hơn sẽ đổ bóng xuống tấm bên dưới — và tấm ở càng cao thì bóng càng lớn, càng mờ, càng lan rộng. Đó chính là lý do một modal (rất cao) có bóng đổ to và mềm, còn một card (thấp hơn) chỉ có bóng nhỏ, sát viền.

Elevation truyền đạt hai thứ: thứ bậc và khả năng tương tác

Đây là ý quan trọng nhất của cả bài. Elevation không chỉ làm đẹp — nó giao tiếp. Cụ thể nó nói với người dùng hai điều:

  • Thứ bậc (hierarchy): Phần tử càng cao càng quan trọng, càng đòi hỏi sự chú ý. Một dialog xác nhận xóa tài khoản nổi cao vọt lên trên toàn bộ màn hình, kèm lớp phủ tối phía sau — nó đang hét lên "hãy tập trung vào tôi trước đã".
  • Khả năng tương tác (interactivity): Những phần tử "nổi" thường ngầm báo rằng chúng có thể chạm vào, kéo, thả. Nút Floating Action Button (FAB) nổi cao vì nó là hành động chính. Khi bạn nhấn giữ và kéo một item trong danh sách, nó thường "nhấc lên" cao hơn để báo trạng thái đang được cầm.
Vì elevation mang thông tin, việc dùng nó tùy tiện sẽ gây nhiễu. Nếu mọi thứ trên màn hình đều có bóng đổ giống nhau, thì không có gì nổi bật, và hệ thống thứ bậc sụp đổ.

Bóng đổ "thật" được tạo bởi ít nhất hai lớp

Đây là bí mật mà nhiều designer không biết. Trong thế giới thực, một vật thể tạo ra hai loại bóng cùng lúc:

  • Key shadow (bóng chính): bóng đậm, sắc nét hơn, nằm ngay dưới vật thể — do nguồn sáng chính trực tiếp tạo ra.
  • Ambient shadow (bóng môi trường): bóng nhạt, mờ và lan rộng hơn — do ánh sáng phản xạ, khuếch tán từ môi trường xung quanh.
Nếu bạn chỉ đổ một lớp bóng duy nhất, giao diện sẽ trông "rẻ tiền" và phẳng. Bóng đổ đẹp trong các design system chuyên nghiệp (Material, iOS, Ant Design) hầu như luôn là chồng của 2–3 lớp box-shadow với độ mờ, độ lan và độ đậm khác nhau. Ví dụ một card elevation trung bình có thể là:

box-shadow:
  0 1px 2px rgba(0,0,0,0.12),   / key shadow: sắc, sát /
  0 4px 12px rgba(0,0,0,0.08);  / ambient shadow: mềm, lan /

Bốn thông số của một box-shadow

Mỗi lớp bóng được điều khiển bởi bốn giá trị bạn phải nắm chắc:

  • Offset X / Offset Y: bóng dịch bao xa theo chiều ngang/dọc. Vì nguồn sáng ảo đặt thẳng phía trên, offset X thường bằng 0, còn offset Y dương (bóng đổ xuống dưới).
  • Blur: độ mờ của mép bóng. Càng cao thì bóng càng "tán" ra mềm mại. Elevation cao đi kèm blur lớn.
  • Spread: bóng nở to hơn hay co nhỏ hơn kích thước phần tử. Trong UI thường để 0 hoặc âm nhẹ.
  • Color / Opacity: màu và độ trong suốt. Nguyên tắc vàng: không dùng đen đặc (#000000 opacity 100%). Bóng thật luôn bán trong suốt (opacity 8–20%), để nền phía sau vẫn "thấm" qua.

Tình huống thực tế

Ví dụ 1 — Card sản phẩm trên sàn thương mại điện tử

Hãy tưởng tượng đội thiết kế của một sàn TMĐT lớn tại Việt Nam như Tiki đang làm lại trang danh mục sản phẩm. Ban đầu, mỗi thẻ sản phẩm được đổ bóng khá đậm: 0 8px 16px rgba(0,0,0,0.3). Trên một màn hình chỉ có một card thì trông ổn, nhưng khi xếp lưới 4 cột x 5 hàng — tức 20 card cùng lúc — màn hình trở nên nặng nề, tối tăm, và mắt người dùng không biết nhìn vào đâu. Mọi thứ đều "hét" như nhau.

Đội thiết kế quyết định hạ elevation của card ở trạng thái nghỉ xuống rất thấp: chỉ một lớp bóng cực nhẹ 0 1px 3px rgba(0,0,0,0.1), gần như chỉ đủ tách card khỏi nền. Nhưng họ thêm một tương tác: khi người dùng rê chuột (hover) vào một card, nó nâng elevation lên với bóng 0 6px 20px rgba(0,0,0,0.12) cùng chuyển động mượt trong 150ms. Kết quả: trang thoáng hẳn, và card mà người dùng đang quan tâm tự động nổi lên đúng lúc.

Bài học rút ra: Ở trạng thái nghỉ, hãy giữ elevation thấp và đồng đều để giao diện thở được. Dùng việc thay đổi elevation như một tín hiệu phản hồi tương tác, chứ không đổ bóng nặng ngay từ đầu.

Ví dụ 2 — Dialog xác nhận trong app ngân hàng số

Một team làm app ngân hàng số (giả định là "VBank Digital") gặp khiếu nại: người dùng chuyển tiền nhầm vì không nhận ra hộp thoại xác nhận đã bật lên. Điều tra ra thì hộp thoại xác nhận có elevation gần như bằng với các card thông tin phía sau — bóng đổ mờ nhạt, lại không có lớp phủ (scrim) tối phía sau. Về mặt thị giác, dialog "chìm" vào nền, người dùng lướt mắt qua và bấm nhầm nút phía dưới.

Giải pháp: nâng dialog lên nấc elevation cao nhất trong hệ thống (24dp) với bóng đổ hai lớp lớn và mềm, đồng thời thêm lớp scrim đen rgba(0,0,0,0.5) phủ toàn màn hình bên dưới. Bây giờ dialog thực sự "nhấc bổng" khỏi mọi thứ khác, tách bạch rõ ràng. Tỷ lệ chuyển tiền nhầm giảm rõ rệt trong đợt đo A/B tiếp theo.

Bài học rút ra: Elevation cao nhất phải dành cho những phần tử đòi hỏi hành động dứt khoát và không thể bị bỏ qua. Với modal/dialog, elevation cao đi cùng scrim là bộ đôi bắt buộc — bóng đổ tách phần tử, scrim làm mờ ngữ cảnh phía sau.

Ví dụ 3 — Dropdown menu bị "dán phẳng" vào ô input

Một bạn junior trong một startup ở TP.HCM dựng component select dropdown. Khi bấm vào ô, danh sách lựa chọn bung ra — nhưng nó không có bóng đổ nào cả, chỉ có viền 1px cùng màu với ô input. Hệ quả: menu trông như bị "hàn dính" vào ô, người dùng khó phân biệt đâu là ô, đâu là danh sách đang mở, đặc biệt trên nền trắng.

Mentor hướng dẫn bạn ấy gán cho menu bung ra một elevation trung bình (8dp) với bóng 0 4px 12px rgba(0,0,0,0.15). Chỉ một thay đổi nhỏ, menu lập tức "nổi" lên trên ô input, người dùng hiểu ngay đây là một lớp tạm thời đang che nội dung bên dưới và sẽ đóng lại sau khi chọn.

Bài học rút ra: Mọi phần tử tạm thời bung ra che nội dung khác — dropdown, popover, menu ngữ cảnh — đều cần elevation đủ để tách khỏi lớp nền. Không có bóng, người dùng mất cảm giác về "lớp".

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

Dưới đây là quy trình xây dựng một hệ thống elevation gọn gàng cho dự án của bạn.

Bước 1 — Xác định số nấc elevation cần dùng. Đừng tạo 20 nấc. Hầu hết sản phẩm chỉ cần 5–6 nấc là đủ. Một bộ chuẩn để bắt đầu:

  • Level 0: nền phẳng, không bóng (background, phần tử chìm).
  • Level 1: card, panel ở trạng thái nghỉ — bóng rất nhẹ.
  • Level 2: phần tử được hover hoặc chọn nhẹ.
  • Level 3: dropdown, popover, menu ngữ cảnh.
  • Level 4: navigation bar cố định, header nổi khi cuộn.
  • Level 5: modal, dialog, sheet — cao nhất.
Bước 2 — Định nghĩa công thức bóng cho từng nấc. Với mỗi nấc, xác định hai lớp (key + ambient). Nguyên tắc: elevation càng cao thì offset Y càng lớn, blur càng lớn, nhưng opacity thường giảm đi một chút (bóng cao thì lan rộng nên phải nhạt hơn để không quá đậm). Ví dụ một thang tham khảo:

  • Level 1: 0 1px 2px rgba(0,0,0,0.12), 0 1px 3px rgba(0,0,0,0.08)
  • Level 3: 0 2px 6px rgba(0,0,0,0.12), 0 6px 16px rgba(0,0,0,0.08)
  • Level 5: 0 4px 12px rgba(0,0,0,0.12), 0 16px 32px rgba(0,0,0,0.10)
Bước 3 — Đặt tên có ý nghĩa, lưu thành style. Trong Figma, tạo các Effect Style đặt tên theo ngữ nghĩa: elevation/1, elevation/2, elevation/dropdown, elevation/modal... Tên nói lên "vai trò" chứ không phải giá trị thô. Sau này khi muốn chỉnh bóng của mọi dropdown trong app, bạn chỉ sửa một style — mọi component dùng nó cập nhật theo.

Bước 4 — Gán style, tuyệt đối không đổ bóng thủ công. Khi dựng một card, đừng nhập tay các số vào panel Effects. Hãy áp Effect Style đã lưu. Đây là điều tách biệt một designer làm việc có hệ thống với một người "vẽ" từng màn hình rời rạc.

Bước 5 — Kiểm tra trên nền tối và dark mode. Bóng đổ đen hoạt động tốt trên nền sáng, nhưng trên dark mode thì bóng gần như vô hình. Trong dark mode, elevation thường được thể hiện bằng cách làm sáng bề mặt (surface tint) thay vì đổ bóng — phần tử càng cao thì nền của nó càng sáng hơn nền chung một chút. Hãy chuẩn bị cả hai chế độ.

Bước 6 — Lập bảng bàn giao cho developer. Ghi rõ mỗi nấc elevation tương ứng với giá trị box-shadow CSS đầy đủ, tên token (--elevation-1), và component nào dùng nấc nào. Điều này giúp bài toán handoff về sau nhẹ đi rất nhiều.

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

Lỗi 1 — Dùng màu đen thuần cho bóng. Bóng rgba(0,0,0,1) cho ra vệt xám đục, trông rất giả. Bóng thật luôn bán trong suốt. Mẹo nâng cao: thử pha một chút màu chủ đạo của thương hiệu vào bóng (ví dụ bóng ánh xanh nhẹ thay vì đen tuyệt đối) để giao diện có cảm giác gắn kết hơn — nhưng dùng tiết chế.

Lỗi 2 — Loạn elevation, mỗi component một kiểu. Khi bạn thấy trong file Figma có 15 giá trị bóng khác nhau, đó là dấu hiệu hệ thống đang vỡ. Quy về một bộ 5–6 nấc chuẩn và ép mọi thứ dùng lại.

Lỗi 3 — Chỉ dùng một lớp bóng. Bóng một lớp trông phẳng. Tối thiểu hãy dùng hai lớp (key + ambient) cho mọi elevation từ trung bình trở lên.

Lỗi 4 — Đổ bóng để "sửa" độ tương phản kém. Nhiều bạn thêm bóng để tách một phần tử trắng khỏi nền trắng. Thực ra vấn đề gốc là thiếu tương phản; đôi khi một đường viền 1px mảnh hoặc đổi nhẹ màu nền là giải pháp sạch hơn, nhẹ hơn cả về thị giác lẫn hiệu năng.

Lỗi 5 — Bỏ quên hiệu năng. Trên web, quá nhiều box-shadow blur lớn (đặc biệt trên hàng trăm phần tử cuộn liên tục) có thể gây giật. Với danh sách dài, hãy cân nhắc bóng nhẹ hoặc dùng viền.

Mẹo — Nguồn sáng nhất quán. Trong toàn bộ sản phẩm, hãy giả định nguồn sáng luôn ở cùng một vị trí (thường là trên đầu, hơi chếch). Nghĩa là mọi bóng đều đổ cùng một hướng — offset X = 0, offset Y dương. Bóng đổ lung tung mỗi hướng là dấu hiệu thiếu chuyên nghiệp dễ nhận ra nhất.

Mẹo — Elevation là tương đối, không tuyệt đối. Điều quan trọng không phải con số dp chính xác, mà là quan hệ cao–thấp giữa các phần tử. Một modal chỉ cần cao hơn mọi thứ xung quanh nó là đủ, không cần nhớ nó đúng "24dp".

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

  • Xây thang elevation của riêng bạn. Trong Figma, tạo 6 hình chữ nhật trắng đặt trên nền xám nhạt. Định nghĩa 6 Effect Style từ elevation/0 đến elevation/5, mỗi nấc gồm hai lớp bóng (key + ambient). Đặt cạnh nhau và nheo mắt kiểm tra: bạn có cảm nhận được rõ ràng nấc nào cao hơn nấc nào không? Nếu hai nấc liền kề trông giống hệt nhau, hãy tăng khác biệt.
  • Dựng một card có ba trạng thái. Tạo một card sản phẩm với ba trạng thái: nghỉ (Level 1), hover (Level 2), và đang được kéo/nhấc (Level 4). Áp đúng Effect Style cho từng trạng thái. Ghi lại giá trị box-shadow CSS tương ứng cho mỗi trạng thái để bàn giao.
  • Audit một app thật. Chọn một app bạn hay dùng (MoMo, Grab, Shopee...). Chụp màn hình một vài giao diện có card, dropdown, và modal. Với mỗi phần tử, đoán xem nó ở nấc elevation nào và ghi lý do. Việc "đọc ngược" thiết kế của người khác giúp bạn hiểu logic elevation nhanh hơn nhiều so với chỉ đọc lý thuyết.
  • Chuyển sang dark mode. Lấy thang elevation ở bài 1, tạo một biến thể cho dark mode: thay vì đổ bóng đen, hãy thể hiện độ cao bằng cách làm sáng dần bề mặt. So sánh cảm giác chiều sâu giữa hai chế độ.

Tóm tắt

Elevation là cách chúng ta đưa chiều sâu (trục Z) vào một màn hình phẳng, và shadow là công cụ thị giác chính để thể hiện nó. Ba điều cốt lõi cần khắc ghi:

  • Elevation là để giao tiếp, không phải trang trí. Nó truyền đạt thứ bậc (phần tử nào quan trọng) và khả năng tương tác (phần tử nào chạm được). Đổ bóng tùy hứng là phá vỡ tín hiệu này.
  • Bóng đổ đẹp được tạo bởi nhiều lớp, bán trong suốt, đổ cùng một hướng, với opacity thấp — không bao giờ dùng đen thuần một lớp.
  • Hệ thống hóa mọi thứ: chỉ dùng 5–6 nấc, lưu thành Effect Style có tên ngữ nghĩa, áp lại thay vì nhập tay, và chuẩn bị cả biến thể dark mode.
Khi bạn nhìn một giao diện và thấy được rõ ràng "tầng nào nằm trên tầng nào", đó là lúc bạn đã dùng elevation đúng cách. Ở các bài tiếp theo về border radius, motion tokens và các component cụ thể, bạn sẽ thấy elevation quay lại như một mảnh ghép nền tảng liên tục — vậy nên hãy dựng cho mình một thang elevation vững chắc ngay từ bây giờ.