Contents

Refactoring UI: Những Nguyên Tắc Thiết Kế Giao Diện Mà Mọi Developer Nên Biết

Contents

“Design không phải là làm cho thứ gì đó trông đẹp. Design là làm cho thứ gì đó hoạt động đúng cách.”

Nguồn tham khảo / Reference
Bài viết này được tổng hợp và biên dịch dựa trên cuốn sách Refactoring UI của Adam Wathan & Steve Schoger. Nội dung gốc tham khảo từ bài viết của tuananhhedspibk.

Là một developer, tôi từng nghĩ thiết kế UI là lãnh địa riêng của designers. Nhưng thực tế là: mọi người viết code đều phải đưa ra quyết định thiết kế hàng ngày — từ việc đặt khoảng cách cho một button, chọn màu cho một badge, cho đến bố cục của một form đăng ký. Refactoring UI là cuốn sách giúp developers tư duy đúng về những quyết định đó.


1. STARTING FROM SCRATCH

Bắt đầu từ Feature, không phải Layout

Khi bắt tay vào thiết kế một ứng dụng, hầu hết chúng ta đều nghĩ ngay đến:

  • Ứng dụng trông sẽ như thế nào?
  • Bố cục sẽ ra sao?
  • Có cần top nav không?

Nhưng thực ra chúng ta đang chỉ nghĩ về phần vỏ bên ngoài. Một ứng dụng thực chất chỉ là tập hợp các features. Trước khi thiết kế một feature mà chưa có bất cứ thông tin gì về cách thức vận hành của nó, đây là công thức cho sự… mất phương hướng.

Thay vì bắt đầu ở phần vỏ, hãy bắt đầu với những thành phần thực sự của một feature.

Ví dụ: Với service booking flight, bắt đầu với feature “tìm kiếm chuyến bay”. Giao diện cần:

  • Fields cho điểm đi, điểm đến
  • Fields cho ngày đi, ngày trở về
  • Button thực thi chức năng search

Và chỉ vậy thôi. Không cần quan tâm đến navigation, sidebar, hay footer ở giai đoạn này.

Chi tiết đến sau

Một tip hay: Design trên giấy bằng bút Sharpie.

/images/posts/refactoring-ui/61635785-48236e00-accf-11e9-9f91-2493f2c4fdac.webp

Việc vẽ chi tiết bằng bút Sharpie là điều không thể — nên đây là cách hay để bỏ thói quen đi quá sâu vào chi tiết ngay từ đầu thiết kế.

Giữ màu Grayscale lúc đầu

Ban đầu nên thiết kế với 2 màu đen, trắng (grayscale) — điều này buộc bạn phải chú trọng vào khoảng cách, tương phản, kích thước. Kết quả là bạn sẽ có được giao diện với tính phân cấp tốt trước, rồi mới thêm màu sắc vào sau.

Đừng đầu tư quá sớm

Build nhanh nhất có thể. Mục đích của bản thiết kế ban đầu là thể hiện ý tưởng — không phải là sản phẩm cuối. Khi đã có quyết định cuối cùng, hãy bỏ bản thô ban đầu và làm lại đúng cách.

Đừng thiết kế quá nhiều
Không cần thiết kế toàn bộ feature trước khi triển khai. Việc tưởng tượng ra tất cả các trường hợp biên (edge cases) chỉ dựa trên trí tưởng tượng và design tool khiến công việc thiết kế trở nên nhàm chán và khó khăn một cách vô lý. Hãy bắt đầu từ version đơn giản nhất và mở rộng dần khi có dữ liệu thực.

Chọn tính cách (Personality) cho giao diện

Mỗi site nên có đặc điểm nhận dạng riêng. Những site liên quan đến ngân hàng hướng đến bảo mật, tin cậy, chuyên nghiệp, trong khi startup có thể mang lại hình ảnh vui nhộn, tươi mới.

Tính cách được quyết định bởi:

Font choice:

  • Serif (có chân): sang trọng, cổ điển
  • Rounded sans-serif (tròn): vui nhộn, trẻ trung
  • Neutral sans-serif (không chân trung tính): đơn giản, hiện đại

Màu sắc:

  • Xanh nước biển: an toàn, thân thiện
  • Vàng kim: đắt đỏ, tinh vi
  • Hồng: vui nhộn, không căng thẳng

Border radius:

/images/posts/refactoring-ui/62029311-36851d80-b21d-11e9-885f-3c75d34f4c0d.webp

/images/posts/refactoring-ui/62029366-5c122700-b21d-11e9-9939-cb35f110d841.webp

/images/posts/refactoring-ui/62049065-69450b00-b249-11e9-93a5-eeaf4a1743b0.webp

Điểm mấu chốt: chỉ sử dụng một loại nút duy nhất để tạo sự thống nhất.

Giới hạn lựa chọn của bạn

Khi có quá nhiều lựa chọn (opacity 10% hay 15%? margin 18px hay 20px?), quyết định trở nên cực kỳ khó khăn dù không có lựa chọn nào thực sự tồi.

Giải pháp: Xây dựng Design System từ trước.

Đừng tìm màu mới mỗi khi thiết kế UI mới — hãy định nghĩa sẵn 8-10 màu chuẩn:

/images/posts/refactoring-ui/62095587-d8f3de00-b2bb-11e9-9cd6-f45626cac2fb.webp

Đừng chỉnh từng pixel cho đến khi font chữ “hoàn hảo” — hãy tự thiết kế một hệ thống font size ngay từ đầu:

/images/posts/refactoring-ui/62095614-e9a45400-b2bb-11e9-8780-a4cdd54215b0.webp

Việc này mất thời gian lúc đầu, nhưng mỗi khi thêm UI mới, bạn sẽ không cần phải ra quyết định lại từ đầu.


2. HIERARCHY IS EVERYTHING

Không phải mọi element đều bình đẳng

Visual Hierarchy là khái niệm chỉ sự phân cấp giữa các thành phần trong UI. Nếu không có sự phân cấp, mọi thứ cạnh tranh với nhau, tạo ra một bức tường thông tin rối rắm.

Đây là giao diện không có sự phân cấp:

/images/posts/refactoring-ui/62106177-862c1d80-b2df-11e9-9ee3-62b3d5fc0875.webp

Và đây là giao diện đã có sự phân cấp thông tin — dù font chữ và tông màu không thay đổi gì:

/images/posts/refactoring-ui/62106272-cf7c6d00-b2df-11e9-9794-da144d8edb41.webp

Kích thước không phải tất cả

Sai lầm phổ biến: primary content phải có font size lớn, secondary content có font size nhỏ. Nếu có 4-5 cấp phân cấp thì phải dùng 4-5 font size — nhưng trong một site chỉ nên dùng tối đa 3 font sizes.

Thay vào đó, kết hợp nhiều yếu tố:

/images/posts/refactoring-ui/62119405-7110b800-b2fa-11e9-8314-baa62ee86753.webp

Trong một site chỉ cần:

  • 2-3 màu: Dark cho primary (tiêu đề), Grey cho secondary (ngày tháng), Lighter grey cho cấp 3 (copyright)
  • 2 font weights: 400-500 cho text thường, 600-700 cho nội dung muốn nhấn mạnh

Đừng dùng grey text trên background màu

Light grey text trên background trắng hoạt động hoàn hảo. Nhưng điều này không đúng với background màu:

/images/posts/refactoring-ui/62131911-13d72f80-b317-11e9-9626-2927a427fc2d.webp

Cách đúng: dùng màu text gần với màu background (cùng tông):

/images/posts/refactoring-ui/62132108-63b5f680-b317-11e9-96d5-4b66e1db4282.webp

Chọn màu dựa theo background color rồi chỉnh độ sáng:

/images/posts/refactoring-ui/62134048-d1175680-b31a-11e9-8612-363eb6336da4.webp

Nhấn mạnh bằng cách làm mờ xung quanh

Đôi lúc muốn nhấn mạnh một item nhưng không thể làm nó nổi hơn được nữa:

/images/posts/refactoring-ui/62177971-f7bca800-b381-11e9-97c0-e6fc82fe5d0b.webp

Thay vì cố làm active item nổi bật hơn, hãy làm mờ (de-emphasize) các item xung quanh:

/images/posts/refactoring-ui/62178091-7f0a1b80-b382-11e9-9268-e1262a3d2499.webp

Có thể áp dụng cho những phần UI lớn hơn — ví dụ bỏ background của sidebar để nội dung chính nổi bật:

/images/posts/refactoring-ui/62178956-c34aeb00-b385-11e9-820a-5fde97997f5e.webp

Label: Dùng khi thực sự cần

Hầu hết chúng ta mắc bẫy hiển thị dữ liệu theo format label: value. Điều này khiến người đọc khó nắm bắt thông tin vì không có bất cứ hệ thống phân cấp nào.

Đôi khi không cần label: abc@mail.com → ai cũng biết đó là email. Ngữ cảnh đã nói lên tất cả:

/images/posts/refactoring-ui/62182042-3bb6a980-b390-11e9-8a38-758bc7ce5848.webp

Kết hợp label và value: Thay vì “In stock: 12”, hãy viết “12 in stock” — làm nổi bật value:

/images/posts/refactoring-ui/62185372-24ca8400-b39d-11e9-8eb0-27a7c7c0652f.webp

Label là secondary: Khi cần label (như dashboard), hãy coi label như supporting content — de-emphasize chúng, làm nổi bật dữ liệu:

/images/posts/refactoring-ui/62186062-c9e65c00-b39f-11e9-810d-1116b52b8329.webp

Phân cấp thị giác ≠ Phân cấp tài liệu

Chúng ta được dạy rằng <h1>, <h2> phải có kích cỡ lớn. Nhưng trong nhiều trường hợp, title chỉ đóng vai trò như label — nội dung mới là thứ người ta cần đọc:

/images/posts/refactoring-ui/62189802-e76cf300-b3aa-11e9-84eb-837a008fbe06.webp

Đừng để element đang sử dụng làm ảnh hưởng đến việc style cho thiết kế.

Dùng Contrast để bù cho Weight

Khi kết hợp texticon, icon thường nổi bật hơn text (đặc biệt solid icons). Cách xử lý: dùng màu nhạt hơn cho icon thay vì thay đổi weight:

/images/posts/refactoring-ui/62194093-19368780-b3b4-11e9-8088-17dcc7a779d8.webp

Tương tự, có thể tăng weight của border để bù cho contrast thấp. Border mỏng màu nhạt trông không có nghĩa, nhưng làm tối màu sẽ khiến người dùng tập trung vào border thay vì nội dung:

/images/posts/refactoring-ui/62197592-13907000-b3bb-11e9-8e53-94865dbd9936.webp

/images/posts/refactoring-ui/62197749-64a06400-b3bb-11e9-8c83-810b9064501a.webp

Semantics là thứ yếu

Chúng ta hay mắc bẫy thiết kế actions theo semantics mà quên đi tính kế thừa. Trong trang web thường có 1 main action, 2 secondary actions, và một vài tertiary actions.

Nếu thiết kế theo semantics:

/images/posts/refactoring-ui/62200702-ee9efb80-b3c0-11e9-982a-5c92cc9bb22f.webp

Thiết kế đúng theo phân cấp:

/images/posts/refactoring-ui/62268151-d33bfb00-b469-11e9-98b8-c50a072b17d6.webp

  • Primary actions: Background tương phản cao, solid
  • Secondary actions: Outline style hoặc màu tương phản thấp
  • Tertiary actions: Style như một link
Destructive Actions

Actions liên quan đến xóa không có nghĩa là mặc nhiên primary action. Nếu không phải primary action, nút xóa nên là secondary hoặc tertiary — không phải lúc nào cũng cần background đỏ to tướng.

/images/posts/refactoring-ui/62268618-590c7600-b46b-11e9-8353-1c69337a666b.webp

Chỉ khi nút xóa đi kèm với bước xác nhận thì nó mới nên là primary action.


3. LAYOUT AND SPACING

Bắt đầu với quá nhiều White Space

Một trong những cách đơn giản nhất để clean up thiết kế: thêm nhiều không gian thở hơn cho các elements.

/images/posts/refactoring-ui/62293414-84ab5280-b4a3-11e9-9c50-49d8208bc9b2.webp

White space nên bị xóa, không phải được thêm

Khi thiết kế trông chật chội, chúng ta thường thêm margin/padding — nhưng không gian được thêm thường quá ít nên không cải thiện gì mấy.

Cách tiếp cận tốt hơn: bắt đầu với thiết kế có nhiều khoảng trắng, sau đó thu hẹp dần cho đến khi cảm thấy ổn:

/images/posts/refactoring-ui/62293812-5b3ef680-b4a4-11e9-9796-f5e8ef36149e.webp

Dense UIs cũng có chỗ đứng

Giao diện dashboard (Dense UI) mang lại cảm giác bận rộn nhất định — và đó không nhất thiết là xấu. Với những giao diện loại này, không cần quá nhiều khoảng trắng:

/images/posts/refactoring-ui/62294271-8544e880-b4a5-11e9-8d12-79e0e06220a9.webp

Xây dựng hệ thống Spacing

Thay vì căn chỉnh từng pixel một, hãy xây dựng hệ thống spacing từ trước.

Tại sao linear scale không hoạt động? Với elements nhỏ, thay đổi 2px cũng tạo ra sự khác biệt ~25%. Nhưng với elements lớn như card, thay đổi 20px chỉ tạo khác biệt ~2%.

/images/posts/refactoring-ui/62372149-b12da000-b571-11e9-8eca-3d55d0f6bbea.webp

Xây dựng hệ thống: Dùng base 16px (default font size của trình duyệt) làm cơ sở. Các kích cỡ lớn hơn là bội số của 16px:

/images/posts/refactoring-ui/62372718-2c438600-b573-11e9-90b0-8c313e4e358d.webp

Khi có hệ thống spacing, thiết kế sẽ nhất quán và trôi chảy hơn bao giờ hết:

/images/posts/refactoring-ui/62373927-cad0e680-b575-11e9-8566-04910f85ea38.webp

Đừng cố lấp đầy toàn bộ màn hình

Hiện nay chúng ta thường dùng công cụ thiết kế có canvas rộng 1200-1400px. Nhưng có nhiều không gian không có nghĩa phải dùng hết:

/images/posts/refactoring-ui/62588703-acfedb00-b901-11e9-9eee-87ebf001ca42.webp

Nếu element chỉ cần 600px thì hãy chỉ dùng 600px:

/images/posts/refactoring-ui/62588823-1a127080-b902-11e9-8c29-109449f00760.webp

Navigation full-width không có nghĩa là mọi element khác cũng phải vậy:

/images/posts/refactoring-ui/62588924-7a091700-b902-11e9-9c68-d69192bc0feb.webp

Thu nhỏ canvas: Nếu thiết kế web responsive, hãy bắt đầu từ mobile (400px). Khi hài lòng với mobile, tăng kích cỡ canvas và chỉnh sửa nhỏ:

/images/posts/refactoring-ui/62589508-7080ae80-b904-11e9-9b11-c4dea84d7c46.webp

/images/posts/refactoring-ui/62590319-e259f780-b906-11e9-812c-501b76ec81c8.webp

Thinking in columns: Khi thiết kế phù hợp màn hình nhỏ nhưng mất cân bằng trên màn hình rộng, hãy chia thành nhiều cột thay vì chỉ kéo rộng ra:

/images/posts/refactoring-ui/62591094-6f05b500-b909-11e9-9ab7-055a6aede993.webp

/images/posts/refactoring-ui/62591107-80e75800-b909-11e9-8ea2-d33bd9ccb91b.webp

Grid bị đánh giá quá cao

12-column grid rất phổ biến nhưng không phải lúc nào cũng phù hợp.

Vấn đề với percentage-based grid: Sidebar 25% + MainContent 75%. Khi resize màn hình, sidebar cũng resize theo — có thể rộng hơn cần thiết hoặc nhỏ đến mức text bị vỡ:

/images/posts/refactoring-ui/62592516-5f3c9f80-b90e-11e9-97b3-c531a55f78f9.webp

Giải pháp tốt hơn: Sidebar dùng fixed width, MainContent flexible với internal grid:

/images/posts/refactoring-ui/62593199-d7a46000-b910-11e9-93cf-9735a098e432.webp

Don’t force shrink: Với login card, thay vì phụ thuộc vào grid (6/12 columns), hãy định nghĩa max-width và chỉ force shrink khi màn hình nhỏ hơn max-width:

/images/posts/refactoring-ui/62682025-13fdbc00-b9f6-11e9-9106-ed516b7e01fb.webp

/images/posts/refactoring-ui/62682052-2677f580-b9f6-11e9-8f88-ee393bdd970f.webp

Relative sizing không scale được

Giả sử: body font size 18px, title font size 45px → tỉ lệ 2.5. Liệu điều này có phù hợp khi màn hình nhỏ đi?

Với màn hình nhỏ (body 14px), nếu giữ nguyên tỉ lệ → title 35px:

/images/posts/refactoring-ui/62684281-4e1d8c80-b9fb-11e9-9c24-be924914df0c.webp

Nếu chỉnh title xuống 24px:

/images/posts/refactoring-ui/62684433-a94f7f00-b9fb-11e9-8197-f75f1abc03c6.webp

Quy tắc tổng quát
Các phần tử có kích cỡ lớn trên màn hình lớn sẽ bị thu nhỏ nhanh hơn là các phần tử có kích cỡ nhỏ khi kích cỡ màn hình bị thu nhỏ. Không có sự khác biệt quá nhiều giữa phần tử lớn và nhỏ ở màn hình có kích cỡ nhỏ. Hãy scale mọi thứ độc lập với nhau.

Tương tự, với button: nếu giữ nguyên tỉ lệ padding/font-size khi scale:

/images/posts/refactoring-ui/62686010-ca659f00-b9fe-11e9-8da0-8f24856ce178.webp

Nếu thay đổi không theo tỉ lệ cứng:

/images/posts/refactoring-ui/62686530-e1f15780-b9ff-11e9-8966-44f4fe6915a7.webp

Tránh Spacing mơ hồ

Khi thiết kế, spacing và separators là công cụ để phân biệt các element groups với nhau.

Khi margin giữa label với input bằng nhau — không có sự liên kết giữa label và input cùng group:

/images/posts/refactoring-ui/62750787-5083f300-ba9c-11e9-9663-90f46b2bf698.webp

Khi thay đổi khoảng cách giữa input với label phía dưới, mọi thứ có sự liên kết rõ ràng hơn:

/images/posts/refactoring-ui/62750798-5bd71e80-ba9c-11e9-993c-1660df3e01ea.webp

Tương tự trong article: section heading cần khoảng cách phía trên đủ lớn:

/images/posts/refactoring-ui/62750960-df910b00-ba9c-11e9-9b57-30464b3cc6ae.webp

/images/posts/refactoring-ui/62750974-eddf2700-ba9c-11e9-8ea7-9975bcd4366d.webp

Điều tương tự cũng xảy ra với các phần tử nằm ngang:

/images/posts/refactoring-ui/62751024-2bdc4b00-ba9d-11e9-96c7-06e67e202770.webp

Khoảng cách xung quanh group elements luôn phải lớn hơn khoảng cách bên trong group.


4. DESIGNING TEXT

Thiết lập Type Scale

Không quá khó để tìm thấy một thiết kế có quá nhiều font-size:

/images/posts/refactoring-ui/62755913-c7c38200-bab0-11e9-85c3-ae72c85dd55d.webp

Chọn font-size mà thiếu đi tính hệ thống là ý tưởng tồi vì:

  1. Khiến giao diện thiếu tính thống nhất
  2. Làm giảm tiến độ công việc

Modular scales (tính toán theo tỉ lệ như 4:5, 2:3, 1:1.618) nghe hay nhưng không thực tế: thường cho ra số phân số và không đủ font-sizes cần thiết cho interface design.

Hand-crafted scales mới là cách đúng — tự tạo hệ thống để chủ động kiểm soát:

/images/posts/refactoring-ui/62756782-01e25300-bab4-11e9-87e2-74bc70b0e80b.webp

/images/posts/refactoring-ui/62756835-25a59900-bab4-11e9-9897-3edfd7dd70dc.webp


4. DESIGNING TEXT (tiếp theo)

Tránh đơn vị em

Không nên dùng đơn vị em vì nó là giá trị mang tính tương đối — em của nested elements phụ thuộc vào element cha. Điều này dẫn đến việc tạo ra các giá trị ngoài ý muốn:

/images/posts/refactoring-ui/66882296-d5433e00-f004-11e9-877e-ebfa5f6b8ca4.webp

Hãy sử dụng px hoặc rem để bảo toàn những gì đang xây dựng cho giao diện.

Chọn Font tốt

Một vài tricks để chọn fonts phù hợp:

  • Play it safe: Sans-serif luôn là lựa chọn an toàn. Nếu không tin vào cảm nhận của bản thân, hãy dùng system font stack: -apple-system, Segoe UI, Roboto, Noto Sans, Ubuntu, Cantarell, Helvetica Neue.
  • Ignore typefaces với ít hơn 5 weights: Fonts có nhiều weights thường được tạo ra cẩn thận hơn.
  • Optimize for legibility: Fonts cho headlines có khoảng cách giữa các chữ hẹp hơn fonts cho text nhỏ.

/images/posts/refactoring-ui/69127501-b0535680-0aed-11ea-9ca8-05bc75aa8f88.webp

  • Steal from people who care: Tìm một site bạn yêu thích, inspect để xem họ dùng font gì.

Giữ Line Length trong tầm kiểm soát

Line length lý tưởng: 45-75 ký tự mỗi dòng, tương đương chiều rộng 20-35em.

/images/posts/refactoring-ui/69203042-b2b5bf00-0b86-11ea-8298-284919f39ec9.webp

Khi kết hợp paragraph với ảnh hoặc components lớn, vẫn nên giữ chiều rộng của paragraph trong khoảng hợp lý dù layout rộng hơn:

/images/posts/refactoring-ui/69395990-38bb3c80-0d24-11ea-9c91-44a8a5c55003.webp

/images/posts/refactoring-ui/69396015-47095880-0d24-11ea-932a-980fdb40380a.webp

Căn lề theo Baseline, không phải Center

Khi kết hợp nhiều font sizes trong cùng một dòng, căn lề dọc theo center sẽ trông vụng về:

/images/posts/refactoring-ui/69507770-ff2e3f80-0f76-11ea-8e7d-fa17fa0817ee.webp

Thay vào đó, căn theo baseline (đường kẻ chân chữ):

/images/posts/refactoring-ui/69508196-6d273680-0f78-11ea-8372-90be8a761c6a.webp

Line-height tỉ lệ nghịch với Font Size

Line-height 1.5 là điểm khởi đầu tốt, nhưng cần điều chỉnh theo:

Chiều rộng dòng: Paragraph hẹp cần line-height: 1.5, paragraph rộng cần line-height: 2.

/images/posts/refactoring-ui/69515372-be8fef80-0f91-11ea-99ef-e9644450c262.webp

Font size: Font nhỏ cần line-height cao hơn, font lớn (headline) chỉ cần line-height: 1.

/images/posts/refactoring-ui/69520419-03bb1e00-0fa0-11ea-8717-c90c986fdd42.webp

Line-height và font size tỉ lệ nghịch với nhau.

Với giao diện chỉ toàn links, việc làm nổi bật bằng màu xanh truyền thống tạo ra sự gượng ép:

/images/posts/refactoring-ui/69525059-a4aed680-0faa-11ea-8f34-c51ac5153171.webp

Thay vào đó dùng font weight đậm hơn và màu tối hơn:

/images/posts/refactoring-ui/69525189-e9d30880-0faa-11ea-9b78-17add451e9f0.webp

Với những links không quan trọng, chỉ thêm underline hoặc màu khi hover.

Căn lề có chủ đích

  • Căn giữa (center): Tốt cho headlines hoặc text blocks ngắn độc lập.

/images/posts/refactoring-ui/69639107-529bad00-109f-11ea-9f44-c3b9b4b43948.webp

  • Đừng center long-form text: Nếu text dài hơn 2-3 dòng, hãy căn trái.

/images/posts/refactoring-ui/69639202-7828b680-109f-11ea-92f6-04272e53ea19.webp

  • Căn phải số liệu trong bảng: Giúp so sánh nhanh hơn.

/images/posts/refactoring-ui/69639864-b2468800-10a0-11ea-801f-e785110cd605.webp

Letter-spacing hiệu quả

  • Tightening headlines: Nếu dùng font có letter-spacing rộng cho headline, hãy thu hẹp lại.
  • Improving all-caps: Với text viết HOA toàn bộ, các chữ có cùng chiều cao nên tăng letter-spacing để dễ đọc hơn.

5. WORKING WITH COLOR

Dùng HSL thay vì Hex

Hex và RGB không trực quan khi đọc code. HSL biểu diễn màu qua 3 thuộc tính gần với thị giác con người:

  • Hue (0-360°): Vị trí trên bánh xe màu — 0° là đỏ, 120° là xanh lá
  • Saturation (0-100%): 0% là xám, 100% là sống động
  • Lightness (0-100%): 0% là đen thuần, 50% là màu hue nguyên chất, 100% là trắng

/images/posts/refactoring-ui/69786683-424e1400-11fe-11ea-8d6e-b184deeaebd8.webp

Bạn cần nhiều màu hơn bạn nghĩ

Cách phổ biến là chọn 1 màu chủ đạo + palette generator tạo ra 4 màu thêm. Thực tế không đủ dùng.

Bạn cần chia bảng màu thành 3 nhóm:

Grey (8-10 shades): Cho text, backgrounds, panels, form controls. Bắt đầu từ dark grey thay vì true black:

/images/posts/refactoring-ui/69809816-e00d0780-122d-11ea-9a9d-d6a8efa4816c.webp

Primary color (5-10 shades): Màu nhận diện thương hiệu. Ultra-light shades dùng cho alert backgrounds, darker shades dùng cho text:

/images/posts/refactoring-ui/69810564-8e657c80-122f-11ea-862f-7f9404ad26a1.webp

Accent colors: Màu thu hút sự chú ý, plus màu cho các states:

  • Đỏ cho destructive actions
  • Vàng cho warnings
  • Xanh cho positive trends

/images/posts/refactoring-ui/69935763-307bb200-1519-11ea-9482-7c6eaf8c764d.webp

Xây dựng Shades từ trước

Đừng dùng các tên màu như “darker” hay “lighter” — sẽ tạo ra mớ bùng nhùng. Hãy tạo một tập cố định các shades (thường là 9 shades từ 100 đến 900):

  1. Chọn base color phù hợp làm button background
  2. Tìm darkest shade (dùng cho text) và lightest shade (dùng cho background)
  3. Điền các shades ở giữa theo nguyên tắc tăng dần

/images/posts/refactoring-ui/69939287-d8e24400-1522-11ea-9f44-83ad6b04b888.webp

Lightness làm mất Saturation

Trong HSL, khi lightness gần 0% hoặc 100%, ảnh hưởng của saturation giảm. Muốn shades lighter/darker trông rõ ràng, hãy tăng saturation khi lightness ra xa 50%.

Ngoài ra, có thể thay đổi độ sáng bằng cách xoay hue thay vì chỉ thay đổi lightness:

  • Muốn màu sáng hơn: xoay về phía 60°, 180°, 300° (các hues sáng)
  • Muốn màu tối hơn: xoay về phía 0°, 120°, 240° (các hues tối)

Đừng xoay hue quá 20-30° nếu không muốn có một màu hoàn toàn khác.

Grey không nhất thiết phải là Grey

Grey trong thực tế thường có saturation khá mạnh. Saturate grey với một chút màu tạo ra cảm giác ấm/mát:

  • Saturate với xanh: Grey mát hơn, nhẹ nhàng hơn
  • Saturate với vàng/cam: Grey ấm áp hơn

Accessibility: Tương phản không nhất thiết phải xấu

Normal text (dưới 18px) cần tỉ lệ tương phản ít nhất 4.5:1, text lớn cần 3:1.

Khi cần đảm bảo tương phản mà không muốn dùng text trắng trên background tối, hãy đảo ngược: dùng text màu đậm trên background màu nhạt hơn.

Ngoài ra, đừng chỉ dựa vào màu sắc để truyền thông tin — thêm icons hoặc labels để hỗ trợ người dùng có thị giác màu kém.


6. CREATING DEPTH

Mô phỏng nguồn sáng

Trong thực tế, ánh sáng đến từ phía trên. Hãy áp dụng nguyên tắc này vào thiết kế:

  • Raised elements (nổi lên): Cạnh trên sáng hơn cạnh dưới, có box-shadow ngắn phía dưới.

/images/posts/refactoring-ui/70967089-a3b82300-20d8-11ea-8314-b1796a6a60b3.webp

  • Inset elements (lõm xuống): Dùng inset box-shadow phía trên và border sáng phía dưới.

/images/posts/refactoring-ui/70967784-b2073e80-20da-11ea-85a5-900442b18f5b.webp

Dùng Shadow để diễn đạt độ cao (Elevation)

Shadow nhỏ → element chỉ cao hơn một chút. Shadow lớn → element gần người dùng hơn:

  • Small shadow: Card bình thường
  • Medium shadow: Dropdown, popover
  • Large shadow: Dialog/Modal

Xây dựng elevation system với 5 levels shadow, tương tự như font/color system:

/images/posts/refactoring-ui/71067774-7e9ae180-21b8-11ea-95d4-b6974a40fc04.webp

Shadow cũng có thể dùng để diễn đạt tương tác — item được kéo thả sẽ có shadow lớn hơn, button được nhấn sẽ có shadow nhỏ đi.

Shadow thường có 2 phần

Shadow chuyên nghiệp thường gồm:

  1. Phần lớn: blur lớn, mô phỏng shadow từ luồng sáng trực tiếp
  2. Phần nhỏ: blur nhỏ hơn nhưng tối hơn, mô phỏng shadow vùng ánh sáng không chạm tới

/images/posts/refactoring-ui/71139593-f0733980-2251-11ea-9c5d-321b2c5340c3.webp

Flat design cũng có chiều sâu

Ngay cả flat design cũng có thể tạo cảm giác chiều sâu:

  • Màu sáng hơn → cảm giác gần người dùng hơn
  • Solid shadow (không blur): tạo cảm giác nổi mà vẫn giữ tính phẳng

Overlap Elements để tạo layers

Di chuyển card để nằm ở vùng chuyển giao giữa 2 backgrounds khác nhau sẽ tạo cảm giác đa tầng:

/images/posts/refactoring-ui/71140399-7db78d80-2254-11ea-8b09-7b9668922a3d.webp


7. WORKING WITH IMAGES

Text cần Contrast nhất quán

Khi đặt text lên background là ảnh, vấn đề không nằm ở màu của text mà ở bức ảnh — ảnh có cả vùng sáng và vùng tối, text trắng sẽ bị chìm ở vùng sáng:

/images/posts/refactoring-ui/71790813-bb4e5000-3075-11ea-8551-754ddefbd7ab.webp

Giải pháp:

  • Semi-transparent overlay: Tráng lớp tối lên ảnh để giảm tương phản
  • Giảm contrast + tăng brightness: Làm giảm tính sáng tối vốn có
  • Colorize ảnh: Giảm contrast → desaturate → thêm solid fill với multiply blend mode
  • Text shadow: Blur radius lớn, không có offset

Icon không nên Scale up

Scale up SVG icon 3-4x so với intended size sẽ mất đi tính cân xứng. Thay vào đó, bao icon bởi một shape có background color phù hợp:

/images/posts/refactoring-ui/71959216-82f57000-3235-11ea-9b46-25a66339e630.webp

Screenshot không nên Scale down

Thu nhỏ screenshot 70% khiến font size thực tế xuống còn 4px — người dùng phải nheo mắt. Giải pháp:

  • Chụp ở layout nhỏ hơn (tablet)
  • Chỉ chụp khu vực trung tâm của feature
  • Tạo simplified version thay thế bằng cách thay text bằng lines đơn giản

Beware User-Uploaded Content

  • Dùng background-size: cover để kiểm soát tỉ lệ ảnh upload của người dùng
  • Dùng inner box-shadow nhẹ thay vì border để tránh “bleed” khi ảnh cùng màu với background

8. FINISHING TOUCHES

Supercharge the Defaults

Thay vì thêm chi tiết mới, hãy tận dụng tối đa những gì đang có:

  • Bullet list → dùng icons thay vì dấu chấm
  • Quote → tăng font size, thay đổi màu
  • Links → font weight đậm hơn, underline style độc đáo
  • Checkbox → dùng màu nhận diện thương hiệu thay vì màu mặc định browser

Thêm màu bằng Accent Borders

Một trick đơn giản: thêm accent border màu sắc vào UI:

  • border-top của Card
  • border-bottom của active navigation item
  • border-left của alert message
  • Accent ngắn phía dưới headline

/images/posts/refactoring-ui/72315627-cd179f00-36d6-11ea-8567-4e07340ee9ee.webp

Trang trí Background

Nếu thiết kế trông đơn điệu dù hierarchy, spacing và typography đều tốt:

  • Thay đổi background color cho một section
  • Gradient nhẹ: Dùng 2 hues không khác nhau quá 30 độ
  • Repeating pattern: Dùng HeroPattern
  • Thêm geometric shapes/illustrations

Giữ độ tương phản giữa pattern và background ở mức thấp để đảm bảo tính dễ đọc.

Đừng bỏ qua Empty States

Khi nội dung phụ thuộc vào dữ liệu từ người dùng, trang sẽ có lúc trống. Đừng để trống — dùng illustrations để thu hút và khuyến khích người dùng hành động:

Empty state là tương tác đầu tiên của người dùng với sản phẩm. Hãy coi đó là cơ hội để tạo ấn tượng.

Dùng ít Border hơn

Border làm người dùng tập trung vào nó thay vì nội dung. Thay thế bằng:

  • Box-shadow nhẹ: Phân cách tinh tế
  • Hai background colors khác nhau: Các phần tử cạnh nhau khác background color
  • Extra spacing: Tăng khoảng cách giữa các group

Think Outside the Box

Hãy phá vỡ “định kiến” về cách một component phải trông như thế nào:

  • Dropdown có thể multi-column với icons thay vì list đơn giản
  • Table có thể kết hợp columns liên quan, thêm ảnh/màu sắc
  • Radio buttons có thể là selectable cards thay vì vòng tròn nhàm chán

Lời Kết

Sau khi đọc hết Refactoring UI, tôi nhận ra design là một kỹ năng có thể học được — không phải tài năng bẩm sinh. Các quyết định thiết kế đều có thể tư duy hóa thành nguyên tắc rõ ràng:

  • Xây dựng hệ thống trước: Màu, font, spacing — định nghĩa một lần, dùng mãi mãi
  • Visual Hierarchy là nền tảng — không phải màu sắc hay animation
  • White space là tài sản, không phải không gian lãng phí
  • Scale độc lập — không có tỉ lệ nào là bất biến cho mọi màn hình
  • De-emphasize đôi khi hiệu quả hơn emphasize
  • Ánh sáng và shadow tạo ra chiều sâu — hãy mô phỏng vật lý thực tế
  • Đừng để màu sắc là thứ duy nhất truyền thông tin — accessibility quan trọng
  • Phá vỡ định kiến về cách components phải trông như thế nào

Đây là cuốn sách ngắn nhưng mỗi trang đều có thể áp dụng ngay vào dự án thực tế.


Bài viết được tổng hợp từ: Refactoring UI — Adam Wathan & Steve Schoger (2019). Nội dung gốc tham khảo từ bài viết của tuananhhedspibk.