Skip to main content

Agent Skills - Phần 3: HTML + Tailwind Best Practices

Tóm tắt

Tài liệu tổng hợp HTML + Tailwind CSS Best Practices dùng làm nguồn tham chiếu cho Agent Skills (ví dụ trong Cursor), bao gồm các chủ đề: Animation, Layout, Images, Typography, Colors, Spacing, Forms, Responsive, Buttons, Cards, Accessibility, Performance, Plugins, Interactivity và Customization. Mỗi guideline được đánh giá mức độ quan trọng và có ví dụ code cụ thể. Nội dung dựa trên bộ guideline từ ui-ux-pro-max-skill, giúp developers và AI Agents xây dựng UI với Tailwind CSS hiệu quả và tuân thủ best practices.

Tài liệu này tổng hợp HTML + Tailwind CSS 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 html-tailwind.csv.

Cập nhật: 08/02/2026.

Mức độ: 🔴 Cao · 🟡 Trung bình · 🟢 Thấp
Ví dụ code: + nên · - tránh


1. Animation

1.1 🟡 Use Tailwind animate utilities

Ưu tiên các utility animation built-in của Tailwind (tối ưu & tôn trọng prefers-reduced-motion).

  • Nên: Dùng animate-pulse, animate-spin, animate-ping cho hiệu ứng đơn giản.
+ <div class="animate-pulse">...</div>
  • Không nên: Tự khai báo @keyframes cho các hiệu ứng đơn giản Tailwind đã có sẵn.
- @keyframes pulse { ... }

📖 Animation – Tailwind


1.2 🔴 Limit bounce animations

Hiệu ứng bounce liên tục dễ gây mệt mỏi/motion sickness.

  • Nên: Chỉ dùng animate-bounce cho 1 CTA quan trọng.
+ <button class="animate-bounce">Get started</button>
  • Không nên: Đặt animate-bounce cho nhiều phần tử cùng lúc.
- 5+ elements with animate-bounce

1.3 🟡 Choose appropriate transition duration

Transition UI nên nhanh nhưng vẫn mượt, khoảng 150–300ms.

  • Nên: Dùng duration-150duration-300 cho feedback UI.
+ <button class="transition-all duration-200 hover:bg-blue-600">Save</button>
  • Không nên: Transition quá chậm cho thao tác thường ngày.
- <button class="transition-all duration-1000 hover:bg-blue-600">Save</button>

📖 Transition duration


1.4 🟢 Smooth hover transitions

Hover nên có transition thay vì “giật” màu đột ngột.

  • Nên: Thêm transition-* khi có hover:*.
+ <a class="hover:bg-gray-100 transition-colors">Link</a>
  • Không nên: Đổi màu hover mà không có transition.
- <a class="hover:bg-gray-100">Link</a>

2. Z-Index

2.1 🟡 Use Tailwind z-* scale

Giữ z-index theo scale chuẩn của Tailwind để dễ kiểm soát stacking.

  • Nên: Dùng z-0, z-10, z-20, z-30, z-40, z-50.
+ <div class="fixed z-50">Modal</div>
  • Không nên: Dùng giá trị tuỳ ý như z-[9999] cho mọi thứ.
- <div class="fixed z-[9999]">Modal</div>

📖 Z-Index


2.2 🔴 Fixed elements need explicit z-index

Navbar, modal, dropdown cố định phải set z-index rõ ràng.

  • Nên: Đặt z-50 cho nav, z-40 cho dropdown, v.v.
+ <header class="fixed top-0 inset-x-0 z-50">...</header>
  • Không nên: Dựa vào DOM order, không set z-index.
- <header class="fixed top-0 inset-x-0">...</header>

2.3 🟢 Use negative z-index for backgrounds

Background trang trí nên nằm phía sau content bằng negative z-index.

  • Nên: Dùng -z-10 / z-[-1] cho layer nền.
+ <div class="absolute inset-0 -z-10">Background</div>
  • Không nên: Dùng z-10 cho background rồi phải “đè” mọi thứ khác lên.
- <div class="absolute inset-0 z-10">Background</div>
``>

---

## 3. Layout

### 3.1 🟡 Container max-width for readability

Nội dung chính nên giới hạn chiều rộng để dễ đọc.

- **Nên:** Dùng `max-w-7xl mx-auto` (kèm `px` responsive) cho vùng content.

```diff
+ <main class="max-w-7xl mx-auto px-4">...</main>
  • Không nên: Để w-full full-width trên màn hình rất rộng.
- <main class="w-full">...</main>

📖 Container


3.2 🟡 Responsive padding

Padding nên thay đổi theo breakpoint để phù hợp từng màn hình.

  • Nên: Kết hợp px-4 sm:px-6 lg:px-8 (hoặc tương tự).
+ <div class="px-4 sm:px-6 lg:px-8">...</div>
  • Không nên: Dùng một padding cố định cho mọi kích thước.
- <div class="px-8">...</div>

3.3 🟡 Use grid/flex gaps, not margins

Khoảng cách trong grid/flex nên dùng gap-* thay vì margin từng item.

  • Nên: Dùng gap-4, gap-6, gap-8.
+ <div class="grid gap-6">...</div>
  • Không nên: Set mb-* trên từng phần tử để tạo khoảng cách.
- <div class="grid">
- <div class="mb-4">...</div>
- <div class="mb-4">...</div>
- </div>

📖 Gap


3.4 🟢 Flexbox for alignment

Canh hàng ngang/dọc nên dùng flex utility thay vì nhiều wrapper.

  • Nên: Dùng flex items-center justify-between.
+ <div class="flex items-center justify-between">...</div>
  • Không nên: Tạo nhiều <div> lồng nhau chỉ để căn giữa.
- <div>
- <div class="flex items-center">
- <div class="justify-between">...</div>
- </div>
- </div>

3.5 🟡 Container queries for component-based layout

Dùng container queries cho layout phụ thuộc container, không chỉ viewport.

  • Nên: Sử dụng @container + utility @lg: cho component phức tạp.
+ <section class="@container">
+ <div class="grid gap-6 @lg:grid-cols-2">...</div>
+ </section>
  • Không nên: Viết media query thủ công trong từng component.
- @media (min-width: 1024px) {
- .card-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
- }

📖 Container queries plugin


4. Images

4.1 🟡 Maintain aspect ratio

Giữ tỉ lệ ảnh nhất quán để layout ổn định.

  • Nên: Dùng aspect-video, aspect-square cho wrapper ảnh.
+ <div class="aspect-video rounded-lg overflow-hidden">
+ <img src="..." class="w-full h-full object-cover" />
+ </div>
  • Không nên: Bỏ trống aspect ratio dẫn đến layout nhảy.
- <img src="..." class="w-full" />

📖 Aspect ratio


4.2 🟡 Use object-fit correctly

Tránh ảnh bị méo bằng object-cover hoặc object-contain.

  • Nên: Cho ảnh full container mà không méo.
+ <img src="..." class="w-full h-full object-cover" />
  • Không nên: Đặt w-full h-full mà không có object-*.
- <img src="..." class="w-full h-full" />

📖 Object fit


4.3 🔴 Lazy load off-screen images

Ảnh ngoài viewport nên lazy load để tối ưu hiệu năng.

  • Nên: Thêm loading="lazy" cho ảnh không ở trên fold.
+ <img src="..." alt="..." loading="lazy" />
  • Không nên: Để toàn bộ ảnh eager load mặc định.
- <img src="..." alt="..." />

4.4 🔴 Use responsive images

Serve kích thước ảnh phù hợp từng thiết bị bằng srcset/sizes.

  • Nên: Cung cấp nhiều kích thước trong srcset.
+ <img
+ src="image-800.jpg"
+ srcset="image-400.jpg 400w, image-800.jpg 800w, image-1600.jpg 1600w"
+ sizes="(min-width: 1024px) 800px, 100vw"
+ loading="lazy"
+ />
  • Không nên: Dùng một ảnh 4000px cho mọi thiết bị.
- <img src="image-4000.jpg" />

4.5 🔴 SVG explicit dimensions

SVG nên có width/height rõ ràng để tránh layout shift khi CSS chưa load.

  • Nên: Đặt width/height song song với utility size-*.
+ <svg class="size-6" width="24" height="24">...</svg>
  • Không nên: Chỉ rely vào class mà không set attribute.
- <svg class="size-6">...</svg>

5. Typography

5.1 🟡 Use typography (prose) plugin for rich text

Nội dung dạng bài viết/markdown nên dùng plugin @tailwindcss/typography.

  • Nên: Dùng prose + prose-lg cho content.
+ <article class="prose prose-lg max-w-none">...</article>
  • Không nên: Tự style từng thẻ p, h1, ul thủ công.
- Custom text styling cho từng element

📖 Typography plugin


5.2 🟡 Use comfortable line-height

Line-height hợp lý (~1.6) giúp text dễ đọc.

  • Nên: Dùng leading-relaxed cho body text.
+ <p class="leading-relaxed">...</p>
  • Không nên: Dùng line-height quá sát như leading-none hoặc leading-tight.
- <p class="leading-none">...</p>

📖 Line height


5.3 🟢 Use Tailwind font size scale

Giữ consistent bằng scale text-sm, text-base, text-lg, text-xl, ...

  • Nên: Dùng lớp size chuẩn.
+ <p class="text-lg">...</p>
  • Không nên: Dùng arbitrary size như text-[17px] nếu không thật cần.
- <p class="text-[17px]">...</p>

📖 Font size


5.4 🟡 Handle long text with truncation

Text dài phải có cơ chế truncate/line-clamp để không phá layout.

  • Nên: Dùng truncate hoặc line-clamp-*.
+ <p class="line-clamp-2">Very long title...</p>
  • Không nên: Để text overflow và đẩy vỡ layout.
- <p>Very very very very very long title...</p>

📖 Text overflow


6. Colors

6.1 🟢 Use opacity utilities

Ưu tiên bg-black/50, text-white/80 thay vì class opacity riêng.

  • Nên: Dùng slash opacity trên màu.
+ <div class="bg-black/50 text-white/80">...</div>
  • Không nên: Dùng opacity-50 chung cho cả element.
- <div class="bg-black opacity-50">...</div>

📖 Background color


6.2 🟡 Support dark mode

Dark mode nên được hỗ trợ bằng prefix dark:.

  • Nên: Thêm các biến thể dark:* tương ứng.
+ <div class="bg-white text-gray-900 dark:bg-gray-900 dark:text-white">...</div>
  • Không nên: Chỉ làm theme sáng, bỏ qua dark mode.
- <div class="bg-white text-gray-900">...</div>

📖 Dark mode


6.3 🟡 Use semantic colors in config

Màu nên đặt tên theo semantics (primary, danger...) thay vì màu cụ thể.

  • Nên: Dùng bg-primary, text-success.
+ <button class="bg-primary text-white">...</button>
  • Không nên: Dùng bg-blue-500 hard-code ở mọi nơi.
- <button class="bg-blue-500 text-white">...</button>

6.4 🟡 Theme color variables in Tailwind theme

Khai báo màu trong theme.colors và dùng trực tiếp, tránh trộn với CSS var.

  • Nên: Dùng màu từ theme Tailwind.
+ <div class="bg-primary text-success">...</div>
  • Không nên: Dùng bg-[var(--color-primary)] khắp nơi nếu màu đã có trong theme.
- <div class="bg-[var(--color-primary)]">...</div>

📖 Customizing colors


6.5 🟡 Use bg-linear-to-* for gradients (Tailwind v4+)

Tailwind v4 đổi syntax gradient sang bg-linear-to-*.

  • Nên: Dùng syntax mới bg-linear-to-r, bg-linear-to-b, ...
+ <div class="bg-linear-to-r from-blue-500 to-purple-500">...</div>
  • Không nên: Dùng bg-gradient-to-* đã deprecated trong v4.
- <div class="bg-gradient-to-r from-blue-500 to-purple-500">...</div>

📖 Background image


7. Spacing

7.1 🟢 Use Tailwind spacing scale

Spacing nên dùng scale chuẩn (1, 1.5, 2, 2.5, 3, 4, ...).

  • Nên: Dùng p-4, m-6, gap-8.
+ <div class="p-4 m-6 gap-8">...</div>
  • Không nên: Dùng giá trị pixel arbitrary nếu không bắt buộc.
- <div class="p-[15px]">...</div>

📖 Spacing


7.2 🟡 Use negative margins sparingly

Negative margin chỉ nên dùng cho effect overlap có chủ đích.

  • Nên: Dùng -mt-4 cho card overlap nhẹ.
+ <div class="-mt-4">...</div>
  • Không nên: Dùng negative margin để “chữa cháy” layout hỏng.
- <div class="-m-2">...</div>

7.3 🟢 Use space-y-* for vertical lists

Danh sách dọc nên dùng space-y-* thay vì margin từng item.

  • Nên: Áp dụng space-y-4 cho container.
+ <ul class="space-y-4">
+ <li>Item 1</li>
+ <li>Item 2</li>
+ </ul>
  • Không nên: Thêm mb-* từng child.
- <ul>
- <li class="mb-4">Item 1</li>
- <li class="mb-4">Item 2</li>
- </ul>

📖 Space between


8. Forms

8.1 🔴 Always show focus states

Input, button phải có focus rõ ràng và accessible.

  • Nên: Dùng focus:ring-2 + focus:ring-*.
+ <input class="focus:ring-2 focus:ring-blue-500 focus:outline-none" />
  • Không nên: Tắt focus outline mà không thay thế.
- <input class="focus:outline-none" />

📖 Forms plugin / focus states


8.2 🟡 Consistent input sizing

Các input trong form nên có chiều cao/padding đồng nhất.

  • Nên: Dùng h-10 px-3w-full khi cần.
+ <input class="h-10 w-full px-3" />
  • Không nên: Mỗi input một kích thước.
- <input class="h-8 px-2" />
- <input class="h-12 px-4" />

8.3 🟡 Clear disabled states

Trạng thái disabled phải dễ nhận biết.

  • Nên: Dùng disabled:opacity-50 disabled:cursor-not-allowed.
+ <button class="disabled:opacity-50 disabled:cursor-not-allowed" disabled>Submit</button>
  • Không nên: Disabled nhưng nhìn như enabled.
- <button disabled>Submit</button>

8.4 🟢 Placeholder styling

Placeholder nên nhạt hơn text chính.

  • Nên: Dùng placeholder:text-gray-400.
+ <input class="placeholder:text-gray-400" placeholder="Search..." />
  • Không nên: Để placeholder đậm như text thường.
- <input placeholder="Search..." />

9. Responsive

9.1 🟡 Mobile-first approach

Tailwind là mobile-first – style base cho mobile, thêm breakpoint cho màn lớn.

  • Nên: Định nghĩa base cho mobile, thêm md:, lg:, xl:.
+ <p class="text-sm md:text-base">...</p>
  • Không nên: Thiết kế desktop trước rồi “gò” về mobile.
- <p class="text-base max-md:text-sm">...</p>

📖 Responsive design


9.2 🔴 Test at standard breakpoints

Phải test layout tại các breakpoint phổ biến.

  • Nên: Test ở 320, 375, 768, 1024, 1280, 1536 (hoặc tương đương).
+ Test all breakpoints
  • Không nên: Chỉ test trên 1 thiết bị dev.
- Single device testing

9.3 🟢 Control visibility with hidden/shown utilities

Dùng hidden, block, flex theo breakpoint thay vì 2 version component.

  • Nên: Dùng hidden md:block, md:hidden...
+ <div class="hidden md:block">Desktop nav</div>
  • Không nên: Tạo 2 component hoàn toàn khác nhau cho mobile/desktop nếu không cần.
- Separate mobile/desktop components với cùng nội dung

📖 Display


10. Buttons

10.1 🟡 Consistent button sizing

Button nên có padding/size nhất quán trong toàn hệ thống.

  • Nên: Dùng patterns như px-4 py-2 hoặc px-6 py-3.
+ <button class="px-4 py-2 text-sm">Primary</button>
  • Không nên: Mỗi button mỗi size tuỳ hứng.
- <button class="px-2 py-1 text-xs">...</button>
- <button class="px-6 py-4 text-lg">...</button>

10.2 🔴 Touch targets >= 44px

Trên mobile, target bấm tối thiểu ~44px.

  • Nên: Dùng min-h-[44px] min-w-[44px] cho touch targets.
+ <button class="min-h-[44px] min-w-[44px]">...</button>
  • Không nên: Button quá nhỏ khó bấm.
- <button class="h-8 w-8">...</button>

10.3 🔴 Show loading states

Action async nên có trạng thái loading rõ ràng.

  • Nên: Disable button + hiển thị spinner khi loading.
+ <button disabled class="disabled:opacity-50">
+ <Spinner class="mr-2" /> Saving...
+ </button>
  • Không nên: Cho phép click nhiều lần khi đang loading.
- <button>Save</button>

10.4 🔴 Accessible icon buttons

Button chỉ có icon phải có aria-label.

  • Nên: Thêm label ẩn cho screen reader.
+ <button aria-label="Close">
+ <XIcon />
+ </button>
  • Không nên: Icon button không label.
- <button><XIcon /></button>

11. Cards

11.1 🟢 Consistent card structure

Cards nên share cùng style base (border, shadow, radius...).

  • Nên: Dùng pattern như rounded-lg shadow-md p-6.
+ <div class="rounded-lg shadow-md p-6">...</div>
  • Không nên: Mỗi card một style riêng khó maintain.
- <div class="rounded-2xl shadow-lg p-6">...</div>

11.2 🟡 Card hover states for interactivity

Card clickable nên có hover feedback rõ ràng.

  • Nên: Dùng hover:shadow-lg transition-shadow.
+ <article class="rounded-lg shadow-md hover:shadow-lg transition-shadow">...</article>
  • Không nên: Card có click mà không có hover state.
- <article class="rounded-lg shadow-md cursor-pointer">...</article>

11.3 🟢 Consistent internal card spacing

Spacing bên trong card nên đồng nhất (space-y-*).

  • Nên: Dùng space-y-4 cho nội dung card.
+ <div class="p-6 space-y-4">...</div>
  • Không nên: Mỗi block trong card một mb-* khác nhau.
- <div class="p-6">
- <h3 class="mb-2">...</h3>
- <p class="mb-6">...</p>
- <button class="mb-3">...</button>
- </div>

12. Accessibility

12.1 🔴 Screen reader text

Icon/element không text vẫn cần context cho screen reader.

  • Nên: Dùng sr-only cho label ẩn.
+ <button>
+ <XIcon />
+ <span class="sr-only">Close menu</span>
+ </button>
  • Không nên: Icon button không label.
- <button><XIcon /></button>

📖 Screen readers


12.2 🟡 Use focus-visible

Chỉ hiển thị focus ring cho keyboard user (focus-visible).

  • Nên: Dùng focus-visible:ring-2.
+ <button class="focus-visible:ring-2 focus-visible:ring-blue-500">...</button>
  • Không nên: Dùng focus:ring-2 khiến click chuột cũng hiện ring.
- <button class="focus:ring-2 focus:ring-blue-500">...</button>

12.3 🔴 Respect reduced motion

Phải tôn trọng prefers-reduced-motion để giảm/loại bỏ animation.

  • Nên: Dùng motion-reduce:animate-none cho element animated.
+ <div class="animate-spin motion-reduce:animate-none">...</div>
  • Không nên: Bỏ qua hoàn toàn prefers-reduced-motion.
- No reduced motion support

📖 Reduced motion


13. Performance

13.1 🔴 Configure Tailwind content paths

Tailwind cần content đúng để tree-shake class không dùng.

  • Nên: Cấu hình content chuẩn trong tailwind.config.
+ content: ['./src/**/*.{js,ts,jsx,tsx}']
  • Không nên: Dùng purge (v2) hoặc config sai khiến CSS phình to.
- purge: [...]

📖 Content configuration


13.2 🟡 Use JIT mode (Tailwind v3+)

Tailwind v3 đã dùng JIT mặc định – giữ version/cấu hình mới.

  • Nên: Dùng Tailwind v3+ với JIT.
+ Tailwind v3 defaults
  • Không nên: Dùng Tailwind v2 không bật JIT.
- Tailwind v2 without JIT

13.3 🟢 Avoid @apply bloat

@apply hữu ích nhưng lạm dụng sẽ khó tracking style.

  • Nên: Dùng utility trực tiếp trong HTML cho case đơn giản.
+ <button class="px-4 py-2 rounded">...</button>
  • Không nên: Tạo class với @apply cho mọi thứ nhỏ lẻ.
- .btn { @apply px-4 py-2 rounded; }

📖 Reusing styles


14. Plugins & Customization

14.1 🟡 Prefer official Tailwind plugins

Forms/typography/aspect-ratio nên dùng plugin chính thức.

  • Nên: Thêm plugin vào tailwind.config.js.
+ plugins: [require('@tailwindcss/forms'), require('@tailwindcss/typography')]
  • Không nên: Tự viết reset/style form/typography từ đầu nếu không cần.
- Custom form reset CSS toàn bộ

📖 Plugins


14.2 🟡 Create custom utilities for repeated patterns

Pattern lặp lại nhiều lần nên được trừu tượng hoá thành utility.

  • Nên: Tạo utility trong config (vd shadow custom).
+ boxShadow: {
+ soft: '0 4px 20px rgba(0,0,0,0.1)',
+ }
  • Không nên: Dùng arbitrary value giống nhau ở nhiều chỗ.
- class="shadow-[0_4px_20px_rgba(0,0,0,0.1)]" lặp lại khắp nơi

14.3 🟢 Use arbitrary values when needed

Arbitrary values ([]) phù hợp cho one-off đặc biệt.

  • Nên: Dùng w-[350px] khi thực sự cần kích thước riêng.
+ <div class="w-[350px]">...</div>
  • Không nên: Viết inline style cho mọi giá trị đặc biệt.
- <div style="top: 117px">...</div>

📖 Arbitrary values


15. Interactivity

15.1 🟢 Use group and peer utilities

Các state đơn giản nên dùng group-*, peer-* thay vì JS.

  • Nên: Dùng group-hover, peer-checked để style theo parent/sibling.
+ <button class="group">
+ <span class="group-hover:text-blue-500">Hover me</span>
+ </button>
  • Không nên: Dùng JS onMouseEnter chỉ để đổi màu text.
- onMouseEnter={() => setHover(true)}

📖 Styling based on parent state


16. Modern Layout Shorthands

16.1 🟢 Use shrink-0 shorthand

shrink-0 là shorthand cho flex-shrink-0, gọn gàng hơn.

  • Nên: Dùng shrink-0 trong flex container.
+ <div class="shrink-0">...</div>
  • Không nên: Dùng cả flex-shrink-0 + flex-shrink.
- <div class="flex-shrink-0">...</div>

📖 Flex shrink


16.2 🟢 Use size-* for square dimensions

size-* set cùng lúc width + height cho element vuông.

  • Nên: Dùng size-6, size-8 cho icon/avatar vuông.
+ <div class="size-6 rounded-full bg-blue-500"></div>
  • Không nên: Lặp h-* + w-* cho cùng một giá trị.
- <div class="h-6 w-6 rounded-full bg-blue-500"></div>

📖 Size


Tóm tắt

NhómSố guidelineMức độ ưu tiên
Animation4🟡–🔴
Z-Index3🟢–🔴
Layout5🟢–🟡
Images5🟡–🔴
Typography4🟢–🟡
Colors5🟡
Spacing3🟢–🟡
Forms4🟢–🔴
Responsive3🟢–🔴
Buttons4🟡–🔴
Cards3🟢–🟡
Accessibility3🟡–🔴
Performance3🟢–🔴
Plugins3🟢–🟡
Interactivity1🟢
Layout misc2🟢

Nguồn dữ liệu: html-tailwind.csvui-ux-pro-max-skill.