Menu
ESC

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

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

Đang tải...

Bài 18 — Icon System: Library, Sizing, Stroke

UI Design and Design Handoff Bài 18/60

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

Nếu bạn từng mở một sản phẩm và cảm thấy "cái này nhìn chuyên nghiệp thật", thì rất có thể một phần lớn cảm giác đó đến từ hệ thống icon. Icon là thứ nhỏ bé nhưng xuất hiện dày đặc: trên thanh navigation, trong nút bấm, cạnh label form, trong empty state, trong toast thông báo. Chỉ cần vài icon lệch cỡ, lệch độ dày nét (stroke), hay lẫn lộn hai phong cách khác nhau là toàn bộ giao diện lập tức mất đi sự tinh tế — dù màu sắc và typography của bạn có chuẩn đến đâu.

Vấn đề là ở giai đoạn junior, hầu hết designer xử lý icon theo kiểu "gặp đâu lấy đó": cần icon giỏ hàng thì lên Flaticon tải một cái, cần icon tìm kiếm thì copy từ một bộ khác, cần icon thông báo thì tự vẽ. Kết quả là một sản phẩm có 40 icon đến từ 6 nguồn khác nhau, mỗi cái một cỡ, một độ dày nét, một tỉ lệ bo góc. Người dùng không gọi tên được vấn đề, nhưng họ cảm nhận được sự "rẻ tiền".

Bài này dạy bạn xây dựng một icon system đúng nghĩa — tức là một tập icon có quy tắc rõ ràng về library (nguồn và cách tổ chức), sizing (kích thước chuẩn theo ngữ cảnh), và stroke (độ dày nét đồng nhất). Đây là phần "foundation" của design system, ngang hàng với typography scale và spacing system mà bạn đã học ở các bài trước. Làm đúng phần này, giao diện của bạn sẽ có một sự nhất quán mà mắt thường khó chỉ ra nhưng luôn cảm nhận được.

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

Icon system là gì và gồm những gì

Một icon system không phải là "một thư mục chứa file SVG". Nó là một tập quy ước gồm ba trụ cột:

  • Library — bạn dùng bộ icon nào, tổ chức nó trong Figma ra sao, đặt tên thế nào để cả team tìm được.
  • Sizing — các kích thước chuẩn (16, 20, 24, 32...) và quy tắc dùng cỡ nào trong ngữ cảnh nào.
  • Stroke — độ dày nét của icon, cách nó giữ nguyên (hoặc thay đổi) khi scale, và cách phối hợp với độ đậm của chữ.
Ba trụ cột này phải khớp nhau. Ví dụ, một icon vẽ trên khung 24px với nét 2px sẽ trông cân đối, nhưng nếu bạn ép nó xuống 16px mà nét vẫn 2px thì icon sẽ trông "nặng nề, béo phì" so với chữ xung quanh. Đó là lý do phần lớn công việc của icon system là giữ cho tỉ lệ giữa kích thước và độ dày nét luôn hài hòa.

Grid và optical size — nền tảng của mọi icon đẹp

Mọi bộ icon chuyên nghiệp đều được vẽ trên một grid cố định, phổ biến nhất là grid 24×24px. Bên trong grid đó có một vùng an toàn (live area, thường 20×20px) và padding xung quanh (thường 2px mỗi cạnh). Padding này cực kỳ quan trọng: nó đảm bảo mọi icon — dù là hình tròn, hình vuông hay hình chữ nhật — đều chiếm một "khối lượng thị giác" tương đương nhau khi đặt cạnh nhau.

Đây là điểm mà rất nhiều junior bỏ qua. Một icon hình tròn (như avatar) và một icon hình vuông (như calendar) nếu vẽ tràn hết khung 24px thì icon vuông sẽ trông to hơn hẳn, dù cùng cỡ. Nhà thiết kế icon giỏi sẽ cân bằng quang học (optical balancing): cho hình tròn nhô ra ngoài live area một chút, cho hình vuông thu vào một chút, để mắt người cảm nhận chúng bằng nhau.

Khái niệm liên quan là optical size: cùng một icon nhưng ở cỡ 16px và cỡ 32px không nên chỉ đơn giản là phóng to/thu nhỏ. Ở cỡ nhỏ, chi tiết cần được đơn giản hóa, nét cần dày tương đối hơn để không "biến mất". Các bộ icon hiện đại như Material Symbols của Google hỗ trợ optical size như một axis (trục) riêng chính vì lý do này.

Sizing scale — bốn cỡ nền tảng

Đây là phần trọng tâm. Một icon system tốt chỉ cần một tập nhỏ các kích thước chuẩn, và tất cả đều là bội số của 4 (khớp với spacing system 8-point mà bạn đã học):

  • 16px — dùng inline với body text cỡ 14–16px. Đây là icon đi kèm chữ: icon bên trái một menu item nhỏ, icon trong một chip/tag, icon cảnh báo cạnh dòng lỗi trong form, icon mũi tên nhỏ trong breadcrumb. Nguyên tắc: chiều cao icon nên xấp xỉ chiều cao chữ hoa (cap height) của dòng chữ nó đứng cạnh, để hai thứ trông "ngang vai".
  • 20px — dùng cho secondary actions và các control có mật độ vừa phải. Ví dụ điển hình: icon trong một toolbar dày đặc, icon action phụ trong một table row (sửa, xóa), icon trong một input field cỡ trung. 20px là "cỡ trung gian" hữu ích khi 16px trông quá nhỏ để bấm nhưng 24px lại quá lấn.
  • 24px — cỡ "mặc định" và quan trọng nhất. Dùng cho primary actions và navigation: icon trên bottom navigation của app mobile, icon trong nút chính, icon trên app bar, icon menu hamburger. Khi phân vân không biết dùng cỡ nào, 24px thường là lựa chọn an toàn. Đây cũng là cỡ mà hầu hết các bộ icon được vẽ gốc trên đó (native grid 24px), nên chất lượng hiển thị tốt nhất.
  • 32px — dùng cho các điểm nhấn thị giác lớn hơn: icon trong empty state, icon minh họa cho một feature card, icon trong onboarding, icon trạng thái cỡ lớn (như dấu tích thành công sau khi thanh toán). 32px không dùng cho thao tác dày đặc mà dùng khi icon đóng vai trò "gần như minh họa" — thu hút ánh nhìn và truyền cảm xúc, không chỉ chỉ dẫn hành động.
Một số hệ thống mở rộng thêm 40px và 48px cho illustration hoặc feature icons cỡ lớn, nhưng bốn cỡ trên đã đủ cho 95% giao diện product.

Stroke — linh hồn của phong cách icon

Stroke (độ dày nét) là yếu tố quyết định "tính cách" của bộ icon. Có hai trường phái lớn:

  • Outline / line icons — icon vẽ bằng đường viền, phổ biến nhất hiện nay (Lucide, Feather, Heroicons outline). Nhẹ nhàng, hiện đại, hợp giao diện SaaS và app tài chính.
  • Filled / solid icons — icon vẽ đặc, khối lượng thị giác nặng hơn, thường dùng cho trạng thái active (ví dụ tab đang được chọn dùng filled, tab còn lại dùng outline).
Với line icons, độ dày nét chuẩn là 1.5px hoặc 2px trên grid 24px. Quy tắc vàng: giữ độ dày nét tuyệt đối cố định trên toàn hệ thống. Nghĩa là icon 24px và icon 16px nên có nét gần bằng nhau về mặt pixel (ví dụ 1.5px), chứ không phải nét scale theo tỉ lệ icon. Nếu bạn scale cả icon (kéo giãn), nét sẽ mỏng dần theo kích thước và làm icon nhỏ trông "yếu ớt", còn icon lớn trông "quá mảnh". Cách làm đúng là dùng icon được thiết kế riêng cho từng cỡ, hoặc dùng bộ icon có nét không đổi khi resize.

Stroke cũng cần đồng bộ với độ đậm của typography. Nếu font UI của bạn dùng weight Regular (400), một bộ icon nét 2px có thể trông hơi đậm; nét 1.5px sẽ hài hòa hơn. Ngược lại, nếu giao diện dùng nhiều chữ đậm (Semibold/Bold), icon nét 2px sẽ "đứng vững" cạnh chữ tốt hơn.

Tình huống thực tế

Ví dụ 1 — Momo và bài học "một nguồn icon duy nhất"

Hãy tưởng tượng một ví điện tử lớn tại Việt Nam kiểu như MoMo, với hàng chục dịch vụ trên màn hình chính: nạp tiền, chuyển khoản, hóa đơn điện, vé xem phim, mua sắm... Ở giai đoạn đầu, mỗi team feature tự thêm icon cho dịch vụ của mình. Team A lấy icon từ một bộ line 2px, team B tự vẽ theo phong cách filled bo góc mềm, team C tải từ một marketplace với nét 1px rất mảnh.

Kết quả: màn hình chính có 24 icon dịch vụ nhưng nhìn như "chợ trời" — cái đậm cái nhạt, cái vuông cái tròn, cái có màu nền cái không. Người dùng khó quét mắt, và về mặt thương hiệu, sản phẩm trông thiếu chỉn chu so với đối thủ.

Cách xử lý đúng: chọn một phong cách nền tảng (ví dụ line 2px trên grid 24px, bo góc 2px), rồi vẽ lại toàn bộ 24 icon theo đúng chuẩn đó, đặt trong một container icon cỡ cố định (ví dụ khung 44×44px với icon 24px căn giữa). Với các icon dịch vụ có màu thương hiệu (như logo đối tác ngân hàng), tách riêng thành nhóm "brand icons" và cho phép chúng phá luật màu, nhưng vẫn giữ cùng grid và cùng vùng an toàn.

Bài học: một icon system bắt đầu bằng một quyết định kỷ luật — chọn một nguồn/một phong cách và bắt mọi feature tuân theo. Sự nhất quán quan trọng hơn việc mỗi icon "đẹp riêng lẻ".

Ví dụ 2 — Startup SaaS 8 người và bộ Lucide

Một startup SaaS B2B tại TP.HCM có 8 người, chỉ 1 designer, làm dashboard quản lý kho hàng. Họ không có thời gian tự vẽ 150 icon. Designer quyết định dùng nguyên bộ Lucide (mã nguồn mở, nét 2px, grid 24px, đồng nhất tuyệt đối) làm library chính, import vào Figma dưới dạng components với auto layout để dễ đổi màu.

Điểm hay là Lucide có phiên bản React (lucide-react) mà dev có thể dùng trực tiếp trong code. Nghĩa là designer và dev nói cùng một "ngôn ngữ icon": khi designer chọn icon truck trong Figma, dev chỉ cần viết <Truck /> — không cần export SVG, không cần hỏi qua lại. Handoff gần như bằng không.

Họ thiết lập quy tắc sizing: 16px cho icon cạnh chữ trong bảng dữ liệu dày đặc, 20px cho action buttons trong toolbar, 24px cho sidebar navigation. Toàn bộ dùng nét 2px gốc của Lucide, không scale nét. Trong 6 tháng, dashboard mở rộng lên hơn 40 màn hình mà vẫn giữ được cảm giác "một sản phẩm liền mạch", nhờ đúng một quyết định về library từ đầu.

Bài học: với team nhỏ, chọn một bộ icon mã nguồn mở chất lượng cao và có sẵn thư viện code là chiến lược thông minh nhất — vừa nhất quán, vừa tiết kiệm hàng trăm giờ handoff. Đừng tự vẽ khi không cần.

Ví dụ 3 — App du lịch và cái bẫy "scale nét"

Một app đặt phòng du lịch Đông Nam Á gặp phàn nàn rằng icon ở màn hình empty state (khi chưa có booking) nhìn "mảnh và mờ", trong khi icon trên bottom nav lại "thô". Điều tra ra: designer vẽ tất cả icon ở 24px với nét 2px, rồi khi cần 32px cho empty state thì kéo giãn cả icon lên — làm nét dày thành ~2.7px; còn khi cần 16px trong chip thì thu nhỏ xuống — làm nét mỏng còn ~1.3px.

Hậu quả là mỗi cỡ có một độ dày nét khác nhau, phá vỡ sự đồng nhất. Cách sửa: dùng bộ icon có nét cố định khi resize (hoặc tạo ba biến thể tối ưu cho 16/24/32), và trong Figma đặt constraint đúng để nét không bị scale theo. Sau khi sửa, toàn bộ icon có nét ~2px nhất quán ở mọi cỡ, empty state trở nên sắc nét và bottom nav thanh thoát hơn.

Bài học: đừng bao giờ scale icon bằng cách kéo giãn tự do. Stroke phải được kiểm soát độc lập với kích thước — đây là lỗi kỹ thuật phổ biến nhất phá hỏng một icon system.

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

Đây là quy trình xây dựng icon system từ đầu trong Figma:

  • Chọn library nền tảng. Ưu tiên một bộ mã nguồn mở đồng nhất: Lucide, Heroicons, Phosphor, hoặc Material Symbols. Tiêu chí chọn: cùng grid (24px), cùng nét, đủ số lượng icon bạn cần, và tốt nhất là có sẵn package code cho dev.
  • Định nghĩa grid và vùng an toàn. Tạo một frame 24×24px làm khung chuẩn, với live area 20×20px và padding 2px. Mọi icon mới vẽ hoặc chỉnh sửa đều đặt trong khung này.
  • Thiết lập sizing scale. Quy ước rõ 4 cỡ: 16 / 20 / 24 / 32px, kèm mô tả ngữ cảnh dùng (inline text / secondary action / primary & nav / empty state & feature). Ghi thành một trang trong file design system để cả team tham chiếu.
  • Cố định độ dày nét. Chọn 1.5px hoặc 2px và ghi rõ đây là nét chuẩn. Kiểm tra nét này có hài hòa với font-weight của body text không bằng cách đặt icon 16px cạnh một dòng chữ 16px Regular.
  • Tạo components trong Figma. Mỗi icon là một component, đặt trong một frame vuông đúng cỡ (icon 24px trong frame 24px). Dùng "resize to fit" cẩn thận và khóa tỉ lệ để tránh biến dạng. Với icon nhiều màu (như status), cân nhắc dùng component properties để đổi màu.
  • Đặt tên theo hệ thống. Dùng cấu trúc phân cấp rõ ràng: icon/navigation/home, icon/action/edit, icon/status/success. Tên nhất quán giúp cả designer lẫn dev tìm nhanh (bạn sẽ học sâu hơn về naming ở Bài 34).
  • Đóng gói thành library. Publish thành một Figma library để các file khác dùng chung. Khi bạn cập nhật một icon, mọi nơi dùng nó đều được cập nhật theo — đây chính là sức mạnh của việc làm system thay vì copy-paste.
  • Đồng bộ với code. Nếu dùng bộ có sẵn package (Lucide, Heroicons), thống nhất với dev rằng tên icon trong Figma trùng tên trong code. Nếu icon custom, thiết lập quy trình export SVG chuẩn (bạn sẽ học kỹ ở Bài 48 về asset export).

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

Lỗi 1 — Trộn nhiều phong cách. Dùng line icon chỗ này, filled icon chỗ kia một cách ngẫu nhiên. Mẹo: chọn một phong cách chính; chỉ dùng filled một cách có chủ đích, ví dụ để phân biệt trạng thái active/inactive trong navigation.

Lỗi 2 — Scale nét theo kích thước. Đã phân tích ở ví dụ 3. Mẹo: luôn kiểm tra độ dày nét (px) của icon ở mọi cỡ; chúng phải gần bằng nhau.

Lỗi 3 — Icon lệch cỡ so với chữ. Đặt icon 24px cạnh chữ 14px làm icon "át" chữ. Mẹo: nguyên tắc icon-cạnh-chữ dùng 16px, và canh chiều cao icon xấp xỉ cap height của chữ, không phải x-height.

Lỗi 4 — Bỏ qua cân bằng quang học. Icon tròn trông nhỏ hơn icon vuông dù cùng cỡ. Mẹo: cho phép hình tròn nhô nhẹ ra ngoài live area để cân bằng thị giác.

Lỗi 5 — Vùng bấm quá nhỏ. Icon 16px hay 24px về mặt hiển thị, nhưng vùng chạm (touch target) trên mobile phải tối thiểu 44×44px (theo Apple) hoặc 48×48px (theo Material). Mẹo: bọc icon trong một container có padding đủ lớn; kích thước hiển thị và kích thước bấm là hai thứ khác nhau.

Mẹo bonus — pixel snapping: để icon sắc nét trên màn hình 1x, đặt icon ở tọa độ số nguyên (không phải 12.5px) và ưu tiên cỡ chẵn. Nét cũng nên nằm đúng ranh giới pixel để không bị mờ (anti-aliasing).

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

  • Audit hiện trạng: Lấy một app bạn đang dùng hằng ngày (một ví điện tử, một app đặt đồ ăn). Chụp màn hình 3 màn hình và đánh dấu toàn bộ icon. Ghi chú: chúng có cùng phong cách không? Có bao nhiêu cỡ khác nhau? Nét có đồng nhất không?
  • Xây mini icon system: Trong Figma, import 12 icon từ Lucide (hoặc Heroicons). Tạo component cho từng cái trong frame 24px, đặt tên theo cấu trúc icon/{nhóm}/{tên}. Tạo 4 phiên bản kích thước 16/20/24/32 và kiểm tra nét có giữ nguyên độ dày không.
  • Kiểm tra hài hòa với chữ: Đặt icon 16px cạnh một dòng body text 16px Regular và một dòng 16px Semibold. Quan sát: nét icon 1.5px hay 2px trông cân đối hơn với từng weight? Ghi lại kết luận cho hệ thống của bạn.
  • Bài tập touch target: Thiết kế một bottom navigation 5 mục với icon hiển thị 24px nhưng vùng chạm 48px. Bật layout grid để chứng minh mỗi vùng chạm đủ chuẩn.

Tóm tắt

Icon system là một trong những "foundation layer" âm thầm nhưng quyết định độ chỉn chu của giao diện. Ba trụ cột cần nắm: Library — chọn một nguồn/một phong cách và giữ kỷ luật, ưu tiên bộ mã nguồn mở song hành với code để handoff mượt; Sizing — bốn cỡ nền tảng 16 (inline text), 20 (secondary action), 24 (primary & navigation), 32 (empty state & feature), tất cả là bội số của 4; Stroke — cố định độ dày nét (1.5–2px trên grid 24px), tuyệt đối không scale nét theo kích thước, và cân chỉnh với độ đậm của typography.

Nhớ ba điều quan trọng nhất: vẽ trên grid 24px với vùng an toàn, cân bằng quang học giữa các hình dạng, và tách bạch kích thước hiển thị với vùng chạm. Làm đúng những điều này, bạn sẽ có một hệ thống icon mà người dùng không bao giờ để ý — vì mọi thứ trông vừa vặn đến mức tự nhiên. Và đó chính là dấu hiệu của thiết kế trưởng thành.