Agent Skills - Phần 7: UX Best Practices
Tài liệu tổng hợp UX Best Practices dùng làm nguồn tham chiếu cho Agent Skills (ví dụ trong Cursor), bao gồm các chủ đề: Navigation, Animation, Layout, Touch interactions, Accessibility, Performance, Forms, Responsive design, Typography, Feedback, Content strategy, Onboarding, Search, Data Entry, AI Interaction, Spatial UI và Sustainability. Mỗi guideline được đánh giá mức độ quan trọng và có ví dụ cụ thể. Nội dung dựa trên ux-guidelines.csv từ ui-ux-pro-max-skill, giúp designers và developers tạo trải nghiệm người dùng tốt và tuân thủ UX best practices.
Tài liệu này tổng hợp UX Best Practices dùng làm nguồn tham chiếu cho Agent Skills (ví dụ trong Cursor).
Nội dung dựa trên bộ guideline từ ui-ux-pro-max-skill — file ux-guidelines.csv.
Cập nhật: 08/02/2026.
Mức độ: 🔴 Cao · 🟡 Trung bình · 🟢 Thấp
Ví dụ code: + nên · - tránh
1. Navigation
1.1 🔴 Smooth scroll for anchor links (Web)
Scroll “nhảy” tức thời khi click anchor gây khó chịu và mất ngữ cảnh.
- Nên: Dùng
scroll-behavior: smoothcho HTML.
+ html { scroll-behavior: smooth; }
- Không nên: Để anchor nhảy thẳng tới section mà không có smooth scroll.
- <a href="#section">Section</a> <!-- không có CSS smooth scroll -->
1.2 🟡 Sticky navigation không che nội dung (Web)
Nav cố định phải chừa chỗ cho content bên dưới.
- Nên: Thêm
padding-topcho body (hoặc section đầu) bằng chiều cao nav.
+ <main class="pt-20">...</main> <!-- nav cao h-20 -->
- Không nên: Để nav overlap phần đầu content.
- <main>...</main> <!-- không bù padding -->
1.3 🟡 Active state rõ ràng (All)
User cần biết đang ở trang/section nào.
- Nên: Highlight nav item hiện tại bằng màu/underline/border.
+ <a class="text-primary border-b-2 border-primary">Home</a>
- Không nên: Tất cả link nhìn giống nhau, không có trạng thái active.
- <a class="text-gray-600">Home</a>
1.4 🔴 Back button predictable (Mobile/Web)
Back (trình duyệt/app) phải hoạt động đúng expectation của user.
- Nên: Bảo tồn history đúng thứ tự.
+ history.pushState(...)
- Không nên: Dùng
location.replace()hoặc phá history khiến back không quay lại trang trước.
- location.replace('/dashboard')
1.5 🟡 Deep linking phản ánh state (All)
URL nên phản ánh state hiện tại để share/bookmark được.
- Nên: Cập nhật URL (query/hash) khi view/state thay đổi.
+ /products?category=shoes&page=2
- Không nên: Tất cả state động nhưng URL cố định.
- /products <!-- một URL cho mọi bộ lọc -->
1.6 🟢 Dùng breadcrumbs cho cấu trúc sâu (Web)
Site nhiều tầng cần breadcrumbs để user biết mình đang ở đâu.
- Nên: Hiển th ị đường dẫn hierarchy.
+ Home > Category > Product
- Không nên: Thêm breadcrumbs cho site phẳng 1–2 cấp (chỉ gây nhiễu).
- Home > Blog
2. Animation & Motion
2.1 🔴 Tránh excessive motion
Quá nhiều animation gây phân tâm và mệt/motion sickness.
- Nên: Chỉ animate 1–2 phần tử quan trọng mỗi view.
+ Single hero animation
- Không nên: Animate hàng loạt icon, text, background cùng lúc.
- animate-bounce on 5+ elements
2.2 🟡 Duration hợp lý cho micro-interactions
Animation UI nên nhanh nhưng không “giật”.
- Nên: 150–300ms cho hover/click/focus.
+ transition-all duration-200
- Không nên: > 500ms cho thao tác thường ngày.
- transition-all duration-1000
2.3 🔴 Tôn trọng prefers-reduced-motion (All)
User nhạy cảm motion cần có option giảm/bỏ animation.
- Nên: Dùng media query
prefers-reduced-motion.
+ @media (prefers-reduced-motion: reduce) {
+ * { animation: none !important; scroll-behavior: auto; }
+ }
- Không nên: Bỏ qua hoàn toàn setting này.
- No motion query check
2.4 🔴 Loading states có feedback rõ (All)
Async > 300ms nên có skeleton/spinner, không để UI “chết đứng”.
- Nên: Dùng skeleton hoặc spinner.
+ <div class="animate-pulse bg-gray-200 h-6 w-full" />
- Không nên: Màn hình trắng im lặng trong khi chờ.
- Blank screen while loading
2.5 🔴 Hover vs tap (All)
Hover không tồn tại trên mobile – đừng rely hoàn toàn vào hover để tương tác chính.
- Nên: Dùng click/tap cho primary action.
+ onClick={handleClick}
- Không nên: Chỉ xử lý bằng hover.
- onMouseEnter={handleOpen}
2.6 🟡 Continuous animation chỉ cho loading
Animation infinite gây phân tâm nếu dùng cho trang trí.
- Nên: Dùng
animate-spin/pulse cho loader.
+ <Spinner class="animate-spin" />
- Không nên: Icon/badge trang trí chạy bounce/spin mãi.
- <Icon class="animate-bounce" />
2.7 🟡 Animate bằng transform & opacity (Web)
Animate layout properties (top/left/width/height) rất tốn kém.
- Nên: Dùng
transform+opacity.
+ transform: translateY(10px);
- Không nên: Animate
top,left,width,height.
- top: 10px; /* trong animation */
2.8 🟢 Dùng easing phù hợp
Linear khiến chuyển động “robotic”.
- Nên:
ease-outkhi enter,ease-inkhi exit.
+ transition-timing-function: ease-out;
- Không nên: Dùng
linearcho mọi thứ.
- transition-timing-function: linear;
3. Layout
3.1 🔴 Quản lý z-index theo scale (Web)
Scale z-index rõ ràng tránh “chiến tranh 9999”.
- Nên: Định nghĩa scale 10/20/30/50... dùng nhất quán.
+ z-10 z-20 z-50
- Không nên: Dùng
z-[9999]tuỳ tiện.
- z-[9999]
3.2 🟡 Cẩn thận với overflow-hidden (Web)
overflow-hidden có thể cắt mất component quan trọng.
- Nên: Dùng
overflow-autohoặc test kỹ khi cần hidden.
+ overflow-auto với scroll
- Không nên: Gắn
overflow-hiddendefault để “chữa cháy”.
- overflow-hidden truncating content
3.3 🟡 Fixed elements không chồng chéo (Web)
Nhiều element fixed (nav, bottom bar...) cần tính toán khoảng trống/safe area.
- Nên: Tính khoảng cách giữa fixed top & bottom.
+ Fixed nav + fixed bottom with gap
- Không nên: Chồng nhiều fixed elements che content.
- Multiple overlapping fixed elements
3.4 🟡 Hiểu stacking context (Web)
New stacking context có thể làm z-index “không ăn”.
- Nên: Biết element nào tạo stacking context (position + z-index, transform...).
+ Parent with z-index isolates children
- Không nên: Cứ tăng
z-indexmà không hiểu vì sao không áp dụng.
- z-index: 9999 not working
3.5 🔴 Tránh content jumping (CLS) (Web)
Layout shift khi hình/async content load rất khó chịu.
- Nên: Reserve space (aspect-ratio hoặc fixed height).
+ aspect-ratio: 16 / 9;
- Không nên: Không set dimension cho ảnh/content dynamic.
- No dimensions on images
3.6 🟡 Cẩn thận 100vh trên mobile (Web)
100vh bị ảnh hưởng bởi browser chrome trên mobile.
- Nên: Dùng
min-h-dvh(dynamic viewport) hoặcmin-h-screen.
+ min-h-dvh
- Không nên: Dùng
h-screen/100vhcho full-screen mobile mà không test.
- h-screen trên mobile
3.7 🟡 Giới hạn độ rộng content text (Web)
Line dài quá khó đọc – nên khoảng 65–75 ký tự.
- Nên: Dùng
max-w-prose/max-w-3xl.
+ <article class="max-w-prose mx-auto">...</article>
- Không nên: Paragraph full-width 1440px.
- <p class="w-full">...</p>
4. Touch
4.1 🔴 Touch target ≥ 44x44 (Mobile/Web)
Button quá nhỏ dễ bấm nhầm.
- Nên: Đảm bảo tối thiểu ~44x44px.
+ class="min-h-[44px] min-w-[44px]"
- Không nên: Button
w-6 h-6trên mobile.
- class="w-6 h-6"
4.2 🟡 Touch spacing tối thiểu 8px (Mobile)
Targets sát nhau tăng nguy cơ bấm nhầm.
- Nên: Giữ khoảng cách tối thiểu 8px.
+ class="gap-2"
- Không nên:
gap-0hoặcgap-1giữa buttons.
- class="gap-0"
4.3 🟡 Tránh gesture xung đột (Mobile)
Gesture custom có thể xung đột với hệ thống (back, swipe…).
- Nên: Dùng vertical scroll cho nội dung chính, horizontal swipe chỉ cho carousel rõ ràng.
+ Vertical scroll primary
- Không nên: Swipe ngang trên toàn màn hình chính.
- Horizontal swipe on main content
4.4 🟡 Giảm tap delay (Mobile Web)
Tap delay ~300ms gây cảm giác lag.
- Nên: Dùng
touch-action: manipulation;hoặc kỹ thuật tương đương.
+ button { touch-action: manipulation; }
- Không nên: Giữ default tap handling.
- No touch optimization
5. Interaction & Feedback
5.1 🔴 Focus states rõ ràng (All)
Keyboard user phải thấy được element đang focus.
- Nên: Dùng focus ring rõ ràng.
+ class="focus:ring-2 focus:ring-blue-500"
- Không nên: Xoá outline mà không thay thế.
- class="outline-none"
5.2 🟡 Hover states cho element clickable (Web)
Element click được nên có hover feedback.
- Nên: Cursor pointer + subtle hover.
+ class="cursor-pointer hover:bg-gray-100"
- Không nên: Button/link mà hover như text thường.
- class="text-gray-700"
5.3 🟡 Active/pressed state (All)
Feedback ngay khi nhấn giúp user yên tâm.
- Nên: Thêm
active:*(scale, shadow...).
+ class="active:scale-95"
- Không nên: Không có pressed state nào.
- No active state
5.4 🟡 Disabled state dễ nhận biết (All)
Element disabled phải trông khác hẳn enabled.
- Nên: Giảm opacity +
cursor-not-allowed.
+ class="opacity-50 cursor-not-allowed"
- Không nên: Disabled nhưng nhìn không khác gì bình thường.
- Same style as enabled
5.5 🔴 Loading button chặn double submit (All)
Trong async submit, button phải disabled và hiển thị loading.
- Nên: Disable khi loading + spinner.
+ <button disabled={loading}>
+ {loading ? 'Saving...' : 'Save'}
+ </button>
- Không nên: Cho click nhiều lần trong khi đang xử lý.
- <button onClick={submit}>Save</button>
5.6 🔴 Error feedback rõ ràng (All)
Khi lỗi, user phải hiểu chuyện gì xảy ra và ở đâu.
- Nên: Hiển thị thông báo lỗi gần chỗ xảy ra + màu/error icon.
+ <p class="text-sm text-red-600">Email không hợp lệ</p>
- Không nên: Lỗi im lặng, chỉ log console.
- console.error(error)
5.7 🔴 Confirmation trước hành động destructive (All)
Xoá/sửa không hoàn tác cần confirm.
- Nên: Dialog “Bạn có chắc không?” trước khi delete.
+ <ConfirmDialog onConfirm={handleDelete} />
- Không nên: Xoá ngay khi click mà không cảnh báo.
- onClick={deleteImmediately}