Typography, Colors & Backgrounds
1. Font Family (font-sans, font-serif, font-mono, custom fonts trong @theme)
Tailwind CSS cung cấp sẵn 3 font stack mặc định:
| Class | CSS | Mô tả |
|---|---|---|
font-sans | ui-sans-serif, system-ui, sans-serif, ... | Font không chân, tối ưu cho UI |
font-serif | ui-serif, Georgia, Cambria, ... | Font có chân, dùng cho bài viết dài |
font-mono | ui-monospace, SFMono-Regular, ... | Font monospace, dùng cho code |
Trong Tailwind CSS v4, bạn có thể thêm custom font family thông qua @theme directive trong CSS:
/* app/assets/css/main.css */
@import "tailwindcss";
@theme {
--font-sans: 'Inter', ui-sans-serif, system-ui, sans-serif;
--font-display: 'Clash Display', ui-sans-serif, system-ui, sans-serif;
--font-mono: 'JetBrains Mono', ui-monospace, monospace;
}
Sau khi định nghĩa trong @theme, bạn dùng class tương ứng:
<h1 class="font-sans">Heading với Inter</h1>
<h2 class="font-display">Display heading</h2>
<code class="font-mono">console.log('hello')</code>
tailwind.config.js. Mọi custom đều định nghĩa trong @theme block — gọn hơn, type-safe hơn, và tận dụng CSS cascade tự nhiên.Bài tập 1: Setup custom Google Font (Inter) trong @theme
Yêu cầu: Import Google Font Inter vào project Nuxt, định nghĩa --font-sans trong @theme, và áp dụng cho toàn bộ body.
Bước 1 — Import font trong nuxt.config.ts:
// nuxt.config.ts
export default defineNuxtConfig({
app: {
head: {
link: [
{
rel: 'stylesheet',
href: 'https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap'
}
]
}
}
})
Bước 2 — Khai báo trong CSS:
/* app/assets/css/main.css */
@import "tailwindcss";
@theme {
--font-sans: 'Inter', ui-sans-serif, system-ui, sans-serif;
}
Bước 3 — Áp dụng cho body trong layout:
<!-- app/layouts/default.vue -->
<template>
<body class="font-sans antialiased">
<slot />
</body>
</template>
Bài tập 2: Typography scale cho headings + body text
Yêu cầu: Tạo một typography system gồm:
h1: font-display, 48px, boldh2: font-display, 36px, semiboldh3: font-sans, 24px, semiboldbody: font-sans, 16px, leading-relaxedsmall: font-sans, 14px, text-gray-500
<template>
<article class="max-w-3xl mx-auto px-6 py-12">
<h1 class="font-display text-5xl font-bold tracking-tight text-gray-900">
Tiêu đề bài viết chính
</h1>
<h2 class="font-display text-4xl font-semibold tracking-tight text-gray-800 mt-12">
Section heading cấp 2
</h2>
<h3 class="font-sans text-2xl font-semibold text-gray-800 mt-8">
Sub-section cấp 3
</h3>
<p class="text-base leading-relaxed text-gray-700 mt-4">
Nội dung body text với leading-relaxed để đọc thoải mái hơn.
Khoảng cách dòng 1.625 giúp mắt không bị mỏi khi đọc đoạn văn dài.
</p>
<small class="block text-sm text-gray-500 mt-2">
Caption hoặc ghi chú nhỏ đi kèm
</small>
</article>
</template>
2. Font Size & Weight (text-xs -> text-9xl, font-thin -> font-black)
Tailwind cung cấp scale từ text-xs (12px) đến text-9xl (128px). Mỗi level đi kèm line-height tối ưu.
<p class="text-xs">Extra small — 12px / line-height 1rem</p>
<p class="text-sm">Small — 14px / line-height 1.25rem</p>
<p class="text-base">Base — 16px / line-height 1.5rem</p>
<p class="text-lg">Large — 18px / line-height 1.75rem</p>
<p class="text-xl">Extra large — 20px / line-height 1.75rem</p>
<p class="text-2xl">2XL — 24px / line-height 2rem</p>
<p class="text-3xl">3XL — 30px / line-height 2.25rem</p>
<p class="text-4xl">4XL — 36px / line-height 2.5rem</p>
<p class="text-5xl">5XL — 48px / line-height 1</p>
<p class="text-6xl">6XL — 60px / line-height 1</p>
<p class="text-7xl">7XL — 72px / line-height 1</p>
<p class="text-8xl">8XL — 96px / line-height 1</p>
<p class="text-9xl">9XL — 128px / line-height 1</p>
Font Weight
| Class | Weight | Mô tả |
|---|---|---|
font-thin | 100 | Mỏng nhất, dùng cho display text lớn |
font-extralight | 200 | Rất nhẹ |
font-light | 300 | Nhẹ |
font-normal | 400 | Bình thường (default) |
font-medium | 500 | Vừa phải, phổ biến cho UI text |
font-semibold | 600 | Hơi đậm, heading phụ |
font-bold | 700 | Đậm, heading chính |
font-extrabold | 800 | Rất đậm |
font-black | 900 | Đậm nhất, hero text |
Responsive modifiers
Mọi utility text-* và font-* đều có thể kết hợp với responsive prefix:
<!-- Nhỏ hơn trên mobile, lớn dần theo breakpoint -->
<h1 class="text-3xl md:text-4xl lg:text-5xl xl:text-6xl">
Responsive heading
</h1>
Bài tập 3: Responsive heading sizes (nhỏ hơn trên mobile)
Yêu cầu: Tạo hero section với heading và subheading có kích thước responsive theo từng breakpoint.
<template>
<section class="bg-gradient-to-br from-indigo-50 to-white py-20 px-6">
<div class="max-w-4xl mx-auto text-center">
<h1 class="text-3xl sm:text-4xl md:text-5xl lg:text-6xl font-black tracking-tight text-gray-900">
Xây dựng sản phẩm
<span class="text-indigo-600">nhanh hơn</span>
</h1>
<p class="mt-6 text-base sm:text-lg md:text-xl text-gray-600 max-w-2xl mx-auto leading-relaxed">
Nền tảng giúp team của bạn ship code nhanh gấp 3 lần.
Không cần config phức tạp, chỉ cần code.
</p>
<div class="mt-10 flex flex-col sm:flex-row gap-4 justify-center">
<button class="px-6 py-3 bg-indigo-600 text-white font-semibold rounded-lg text-sm sm:text-base hover:bg-indigo-700 transition-colors">
Bắt đầu miễn phí
</button>
<button class="px-6 py-3 border border-gray-300 text-gray-700 font-semibold rounded-lg text-sm sm:text-base hover:bg-gray-50 transition-colors">
Xem demo
</button>
</div>
</div>
</section>
</template>
3. Line Height, Letter Spacing, Text Align, Vertical Align
Line Height (leading-*)
<p class="leading-none">line-height: 1 — tiêu đề lớn</p>
<p class="leading-tight">line-height: 1.25 — heading</p>
<p class="leading-snug">line-height: 1.375 — subheading</p>
<p class="leading-normal">line-height: 1.5 — body text tiêu chuẩn</p>
<p class="leading-relaxed">line-height: 1.625 — bài viết dài</p>
<p class="leading-loose">line-height: 2 — text thoáng</p>
Letter Spacing (tracking-*)
<p class="tracking-tighter">-0.05em — heading lớn</p>
<p class="tracking-tight">-0.025em — heading vừa</p>
<p class="tracking-normal">0 — body text</p>
<p class="tracking-wide">0.025em — subheading</p>
<p class="tracking-wider">0.05em — label nhỏ</p>
<p class="tracking-widest">0.1em — uppercase label</p>
Text Align
<p class="text-left">Căn trái (default)</p>
<p class="text-center">Căn giữa</p>
<p class="text-right">Căn phải</p>
<p class="text-justify">Căn đều hai bên</p>
<p class="text-start">Theo hướng viết (LTR = left)</p>
<p class="text-end">Ngược hướng viết (LTR = right)</p>
Line Clamp (truncate nhiều dòng) — line-clamp-*
<!-- Giới hạn 3 dòng, thêm "..." ở cuối -->
<p class="line-clamp-3">
Đoạn văn rất dài sẽ bị cắt sau 3 dòng và thêm dấu ba chấm ở cuối...
</p>
<!-- Có sẵn: line-clamp-1 đến line-clamp-6 -->
<!-- Hoặc line-clamp-none để bỏ giới hạn -->
Bài tập 4: Blog card với 3-line title truncation
Yêu cầu: Thiết kế blog card với:
- Title bị giới hạn 2 dòng
- Description bị giới hạn 3 dòng
- Ảnh thumbnail, category tag, date
<template>
<article class="group bg-white rounded-2xl shadow-sm border border-gray-100 overflow-hidden hover:shadow-md transition-shadow">
<div class="aspect-[16/9] overflow-hidden">
<img
src="https://images.unsplash.com/photo-1498050108023-c5249f4df085"
alt="Blog thumbnail"
class="w-full h-full object-cover group-hover:scale-105 transition-transform duration-300"
/>
</div>
<div class="p-5">
<div class="flex items-center gap-2 mb-3">
<span class="px-2.5 py-0.5 bg-indigo-50 text-indigo-700 text-xs font-medium rounded-full">
Nuxt 4
</span>
<span class="text-xs text-gray-400">12 Tháng 7, 2026</span>
</div>
<!-- Title — giới hạn 2 dòng -->
<h3 class="text-lg font-semibold text-gray-900 line-clamp-2 leading-snug group-hover:text-indigo-600 transition-colors">
Hướng dẫn tối ưu SEO cho Nuxt 4 với useSeoMeta, Server Routes và Dynamic Rendering
</h3>
<!-- Description — giới hạn 3 dòng -->
<p class="mt-2 text-sm text-gray-600 line-clamp-3 leading-relaxed">
Tìm hiểu cách tận dụng useSeoMeta để tạo meta tags động,
kết hợp Server Routes để generate sitemap XML, và dùng
Hybrid Rendering để tối ưu tốc độ tải trang blog.
Hướng dẫn chi tiết từ cơ bản đến nâng cao.
</p>
<div class="mt-4 flex items-center gap-3">
<img
src="https://i.pravatar.cc/40?img=1"
alt="Author"
class="w-8 h-8 rounded-full"
/>
<span class="text-sm font-medium text-gray-700">Nguyen Van A</span>
<span class="text-xs text-gray-400 ml-auto">8 phút đọc</span>
</div>
</div>
</article>
</template>
Bài tập 5: Centered hero text với proper line-height
Yêu cầu: Hero section với heading lớn, subheading, mỗi loại có line-height và letter-spacing riêng.
<template>
<section class="min-h-[80vh] flex items-center justify-center bg-slate-900 px-6">
<div class="text-center max-w-3xl">
<h1 class="text-4xl sm:text-5xl md:text-6xl lg:text-7xl font-black text-white leading-none tracking-tighter">
Design that
<span class="bg-gradient-to-r from-cyan-400 to-blue-500 bg-clip-text text-transparent">
speaks
</span>
for itself
</h1>
<p class="mt-8 text-lg sm:text-xl text-slate-400 leading-relaxed max-w-xl mx-auto">
Ship beautiful interfaces faster with a utility-first CSS framework
that lets you stay in your HTML and never leave your flow.
</p>
<div class="mt-10">
<button class="px-8 py-3.5 bg-white text-slate-900 font-semibold rounded-xl text-base tracking-wide hover:bg-slate-200 transition-colors">
Get started
</button>
</div>
</div>
</section>
</template>
4. Text Decoration, Transform, Overflow
Decoration
<p class="underline">Gạch chân</p>
<p class="line-through">Gạch ngang</p>
<p class="overline">Gạch trên</p>
<p class="no-underline">Bỏ gạch chân (hữu ích cho link)</p>
<!-- Kiểm soát style, color, thickness, offset -->
<a href="#" class="underline decoration-indigo-500 decoration-2 underline-offset-4">
Link với gạch chân tùy chỉnh
</a>
<a href="#" class="underline decoration-wavy decoration-amber-400 underline-offset-2">
Link với gạch chân lượn sóng
</a>
<a href="#" class="underline decoration-dotted decoration-pink-400">
Link với gạch chân chấm chấm
</a>
Text Transform
<p class="uppercase">CHỮ IN HOA — label, badge</p>
<p class="lowercase">chữ thường</p>
<p class="capitalize">Mỗi Từ Viết Hoa Chữ Cái Đầu</p>
<p class="normal-case">Bỏ transform — revert về mặc định</p>
Text Overflow
<!-- truncate = text-ellipsis + overflow-hidden + whitespace-nowrap -->
<p class="truncate w-64">
Đoạn text rất dài chỉ hiển thị 1 dòng và bị cắt với dấu ba chấm...
</p>
<!-- text-ellipsis: thêm "..." ở cuối -->
<p class="text-ellipsis overflow-hidden whitespace-nowrap w-64">
Đoạn text bị cắt và thêm dấu ...
</p>
<!-- text-clip: cắt cứng không thêm dấu -->
<p class="text-clip overflow-hidden whitespace-nowrap w-64">
Đoạn text bị cắt cứng không dấu
</p>
Bài tập 6: Styled link hover effects (underline animation)
Yêu cầu: Tạo link có hiệu ứng gạch chân trượt từ trái qua phải khi hover.
<template>
<div class="max-w-2xl mx-auto p-12 space-y-8">
<h2 class="text-2xl font-bold text-gray-900">Link Hover Effects</h2>
<!-- Effect 1: Gạch chân mở rộng từ giữa -->
<a href="#"
class="relative inline-block text-lg font-medium text-indigo-600
after:absolute after:bottom-0 after:left-1/2 after:-translate-x-1/2
after:h-[2px] after:w-0 after:bg-indigo-600
after:transition-all after:duration-300
hover:after:w-full pb-1">
Underline mở rộng từ giữa
</a>
<!-- Effect 2: Gạch chân trượt từ trái -->
<div>
<a href="#"
class="relative inline-block text-lg font-medium text-emerald-600
after:absolute after:bottom-0 after:left-0
after:h-[2px] after:w-0 after:bg-emerald-600
after:transition-all after:duration-300
hover:after:w-full pb-1">
Underline trượt từ trái
</a>
</div>
<!-- Effect 3: Đổi màu + gạch chân đứt đoạn -->
<div>
<a href="#"
class="text-lg font-medium text-gray-500 no-underline
hover:text-rose-500 hover:underline hover:decoration-dashed
hover:decoration-rose-400 hover:underline-offset-4
transition-all duration-200">
Dashed underline + đổi màu
</a>
</div>
<!-- Effect 4: Highlight background khi hover -->
<div>
<a href="#"
class="relative inline-block text-lg font-medium text-gray-900
before:absolute before:bottom-1 before:left-0 before:w-full
before:h-2 before:bg-amber-200/50 before:-z-10
before:transition-all before:duration-300
hover:before:h-full hover:before:bottom-0 px-1">
Highlight nền lan từ dưới lên
</a>
</div>
</div>
</template>
5. List Style
<!-- Danh sách có dấu chấm (default) -->
<ul class="list-disc list-inside space-y-2">
<li>Item thứ nhất</li>
<li>Item thứ hai</li>
<li>Item thứ ba</li>
</ul>
<!-- Danh sách đánh số -->
<ol class="list-decimal list-inside space-y-2">
<li>Bước 1: Cài đặt</li>
<li>Bước 2: Cấu hình</li>
<li>Bước 3: Deploy</li>
</ol>
<!-- Bỏ marker -->
<ul class="list-none space-y-2">
<li>Item không có marker — thường dùng custom marker</li>
</ul>
<!-- list-inside: marker nằm trong flow text -->
<!-- list-outside: marker nằm ngoài (default) -->
<ul class="list-disc list-outside ml-5 space-y-2">
<li>Marker nằm bên trái, text thẳng hàng</li>
<li>Phù hợp cho nội dung dài nhiều dòng</li>
</ul>
list-image-* cho phép dùng ảnh tùy chỉnh làm marker: list-image-[url('/check.svg')] hoặc list-image-none.Bài tập 7: Styled unordered list với custom markers
Yêu cầu: Tạo danh sách với custom marker sử dụng pseudo-element hoặc icon.
<template>
<div class="max-w-xl mx-auto p-8">
<h2 class="text-xl font-bold text-gray-900 mb-6">Lợi ích khi dùng Tailwind CSS</h2>
<!-- Custom marker với custom class -->
<ul class="space-y-4">
<li class="flex items-start gap-3">
<span class="flex-shrink-0 w-6 h-6 rounded-full bg-emerald-100 text-emerald-600 flex items-center justify-center text-sm font-bold mt-0.5">
✓
</span>
<span class="text-gray-700">
<strong class="text-gray-900">Utility-first:</strong> Không cần đặt tên class, code nhanh hơn 3x.
</span>
</li>
<li class="flex items-start gap-3">
<span class="flex-shrink-0 w-6 h-6 rounded-full bg-emerald-100 text-emerald-600 flex items-center justify-center text-sm font-bold mt-0.5">
✓
</span>
<span class="text-gray-700">
<strong class="text-gray-900">Bundle size:</strong> Chỉ giữ CSS bạn dùng — production thường vài KB.
</span>
</li>
<li class="flex items-start gap-3">
<span class="flex-shrink-0 w-6 h-6 rounded-full bg-emerald-100 text-emerald-600 flex items-center justify-center text-sm font-bold mt-0.5">
✓
</span>
<span class="text-gray-700">
<strong class="text-gray-900">Responsive:</strong> Prefix `sm:` `md:` `lg:` giúp responsive ngay trong HTML.
</span>
</li>
<li class="flex items-start gap-3">
<span class="flex-shrink-0 w-6 h-6 rounded-full bg-emerald-100 text-emerald-600 flex items-center justify-center text-sm font-bold mt-0.5">
✓
</span>
<span class="text-gray-700">
<strong class="text-gray-900">Design system:</strong> Scale có sẵn (spacing, color, typography) giúp consistent.
</span>
</li>
</ul>
</div>
</template>
6. Text Shadow (v4.1 NEW)
Tailwind CSS v4.1 giới thiệu utility text-shadow — thay thế hoàn toàn cho việc phải dùng custom CSS.
<h1 class="text-shadow">Text shadow mặc định</h1>
<h1 class="text-shadow-sm">Shadow nhỏ</h1>
<h1 class="text-shadow-md">Shadow vừa</h1>
<h1 class="text-shadow-lg">Shadow lớn</h1>
<h1 class="text-shadow-none">Không shadow</h1>
Custom text shadow qua @theme:
@theme {
--text-shadow-glow: 0 0 10px rgba(59, 130, 246, 0.5);
--text-shadow-neon: 0 0 5px #0ff, 0 0 10px #0ff;
}
<h1 class="text-shadow-glow">Glow effect</h1>
<h1 class="text-shadow-neon">Neon text</h1>
Bài tập 8: Hero text với text shadow để dễ đọc trên ảnh
Yêu cầu: Hero section có background image, text đọc được nhờ text-shadow.
<template>
<section class="relative min-h-[70vh] flex items-center justify-center overflow-hidden">
<!-- Background image -->
<img
src="https://images.unsplash.com/photo-1506905925346-21bda4d32df4"
alt="Mountain landscape"
class="absolute inset-0 w-full h-full object-cover"
/>
<!-- Overlay tối -->
<div class="absolute inset-0 bg-black/40"></div>
<!-- Nội dung -->
<div class="relative z-10 text-center px-6 max-w-4xl">
<h1 class="text-4xl sm:text-5xl md:text-6xl lg:text-7xl font-black text-white leading-none tracking-tighter text-shadow-lg">
Khám phá thế giới
</h1>
<p class="mt-6 text-lg sm:text-xl text-white/90 leading-relaxed max-w-2xl mx-auto text-shadow-sm">
Những chuyến phiêu lưu đáng nhớ bắt đầu từ một bước chân.
Cùng chúng tôi khám phá những vùng đất mới.
</p>
<button class="mt-10 px-8 py-3.5 bg-white text-gray-900 font-semibold rounded-xl text-base hover:bg-gray-100 transition-colors text-shadow-none">
Bắt đầu hành trình
</button>
</div>
</section>
</template>
7. Colors -- OKLCH System (v4.0 NEW)
Tailwind CSS v4 chuyển hoàn toàn sang OKLCH color space — một cuộc cách mạng về màu sắc.
Full default color palette
Tailwind cung cấp 22 họ màu, mỗi họ có scale từ 50 -> 950:
Neutral / Gray tones
slate, gray, zinc, neutral, stone — dùng cho text, background, border. Mỗi loại có undertone khác nhau (slate hơi xanh, stone hơi ấm).Warm colors
red, orange, amber, yellow — cảnh báo, CTA, nhấn mạnh.Cool colors
lime, green, emerald, teal, cyan, sky, blue, indigo, violet, purple, fuchsia, pink, rose — brand, link, accent.NEW v4.2
mauve, olive, mist, taupe — 4 họ màu mới, tinh tế hơn cho thiết kế hiện đại.Cú pháp sử dụng
<!-- Text color -->
<p class="text-red-500">Chữ đỏ</p>
<p class="text-blue-600">Chữ xanh dương</p>
<!-- Background color -->
<div class="bg-emerald-500">Nền xanh lá</div>
<div class="bg-slate-100">Nền xám nhạt</div>
<!-- Border color -->
<div class="border border-indigo-400">Viền tím</div>
Opacity modifier (cú pháp /)
Thay vì dùng bg-opacity-* riêng, Tailwind v4 dùng cú pháp / gọn hơn:
<!-- Opacity 75% -->
<div class="bg-red-500/75">Nền đỏ 75% opacity</div>
<!-- Opacity 50% -->
<p class="text-blue-600/50">Chữ xanh 50% opacity</p>
<!-- Opacity 25% -->
<div class="border-purple-400/25">Viền tím 25% opacity</div>
<!-- Opacity 10% cho overlay nhẹ -->
<div class="bg-black/10">Overlay đen 10%</div>
Bài tập 9: Color palette cho 1 landing page (primary/secondary/accent)
Yêu cầu: Định nghĩa color system trong @theme cho landing page SaaS với:
- Primary: Indigo
- Secondary: Teal
- Accent: Amber
- Neutral: Slate
/* app/assets/css/main.css */
@import "tailwindcss";
@theme {
--color-primary-50: var(--color-indigo-50);
--color-primary-100: var(--color-indigo-100);
--color-primary-200: var(--color-indigo-200);
--color-primary-300: var(--color-indigo-300);
--color-primary-400: var(--color-indigo-400);
--color-primary-500: var(--color-indigo-500);
--color-primary-600: var(--color-indigo-600);
--color-primary-700: var(--color-indigo-700);
--color-primary-800: var(--color-indigo-800);
--color-primary-900: var(--color-indigo-900);
--color-primary-950: var(--color-indigo-950);
--color-secondary-500: var(--color-teal-500);
--color-secondary-600: var(--color-teal-600);
--color-accent-400: var(--color-amber-400);
--color-accent-500: var(--color-amber-500);
}
<!-- Sử dụng trong component -->
<template>
<div class="max-w-4xl mx-auto p-8 space-y-6">
<!-- Primary button -->
<button class="px-6 py-3 bg-primary-600 text-white font-semibold rounded-lg hover:bg-primary-700 transition-colors">
CTA chinh — Primary
</button>
<!-- Secondary button -->
<button class="px-6 py-3 bg-secondary-500 text-white font-semibold rounded-lg hover:bg-secondary-600 transition-colors">
Hành động phụ — Secondary
</button>
<!-- Accent badge -->
<span class="inline-flex px-3 py-1 bg-accent-400/20 text-accent-500 text-sm font-medium rounded-full">
Mới ra mắt
</span>
<!-- Section với nền primary nhạt -->
<section class="bg-primary-50 rounded-2xl p-8">
<h2 class="text-primary-900 text-2xl font-bold">Tính năng nổi bật</h2>
<p class="text-primary-700 mt-2">Mô tả ngắn gọn về tính năng.</p>
</section>
</div>
</template>
Bài tập 10: Accessible color contrast checker concept
Yêu cầu: Tạo component minh họa các cặp màu đạt chuẩn WCAG AA/AAA.
<template>
<div class="max-w-3xl mx-auto p-8 space-y-8">
<h2 class="text-2xl font-bold text-gray-900">Kiểm tra độ tương phản màu (WCAG)</h2>
<p class="text-gray-600">
WCAG yêu cầu contrast ratio tối thiểu <strong>4.5:1</strong> cho text thường và <strong>3:1</strong> cho text lớn (>=18px bold hoặc >=24px).
</p>
<!-- Pass AA: text-gray-900 trên bg-white = ratio ~15:1 -->
<div class="p-6 bg-white border rounded-xl">
<p class="text-sm text-gray-500 mb-2">Pass AA (ratio ~15:1)</p>
<p class="text-gray-900 text-lg font-medium">Text đen chuẩn trên nền trắng — luôn đạt AA/AAA</p>
</div>
<!-- Pass AA: text-white trên bg-indigo-600 = ratio ~6.2:1 -->
<div class="p-6 bg-indigo-600 rounded-xl">
<p class="text-sm text-indigo-200 mb-2">Pass AA (ratio ~6.2:1)</p>
<p class="text-white text-lg font-medium">Chữ trắng trên nền indigo-600 — đạt AA</p>
</div>
<!-- Fail: text-gray-400 trên bg-white = ratio ~2.6:1 -->
<div class="p-6 bg-white border rounded-xl">
<p class="text-sm text-red-500 mb-2">Fail AA (ratio ~2.6:1) — Không nên dùng!</p>
<p class="text-gray-400 text-lg">Chữ xám nhạt trên nền trắng — khó đọc</p>
</div>
<!-- Pass AA: text-gray-600 trên bg-white = ratio ~5.4:1 -->
<div class="p-6 bg-white border rounded-xl">
<p class="text-sm text-emerald-600 mb-2">Pass AA (ratio ~5.4:1) — Tối thiểu cho body text</p>
<p class="text-gray-600 text-base">Nên dùng text-gray-600 trở lên cho body text trên nền trắng.</p>
</div>
<!-- Bảng tham khảo nhanh -->
<div class="overflow-x-auto">
<table class="w-full text-sm border-collapse">
<thead>
<tr class="bg-gray-50">
<th class="border px-4 py-2 text-left">Text Color</th>
<th class="border px-4 py-2 text-left">Background</th>
<th class="border px-4 py-2 text-left">Ratio (xấp xỉ)</th>
<th class="border px-4 py-2 text-left">WCAG AA</th>
</tr>
</thead>
<tbody>
<tr>
<td class="border px-4 py-2"><code>text-gray-900</code></td>
<td class="border px-4 py-2"><code>bg-white</code></td>
<td class="border px-4 py-2">15:1</td>
<td class="border px-4 py-2 text-emerald-600 font-medium">Pass AAA</td>
</tr>
<tr>
<td class="border px-4 py-2"><code>text-gray-600</code></td>
<td class="border px-4 py-2"><code>bg-white</code></td>
<td class="border px-4 py-2">5.4:1</td>
<td class="border px-4 py-2 text-emerald-600 font-medium">Pass AA</td>
</tr>
<tr>
<td class="border px-4 py-2"><code>text-white</code></td>
<td class="border px-4 py-2"><code>bg-blue-600</code></td>
<td class="border px-4 py-2">5.1:1</td>
<td class="border px-4 py-2 text-emerald-600 font-medium">Pass AA</td>
</tr>
<tr>
<td class="border px-4 py-2"><code>text-gray-500</code></td>
<td class="border px-4 py-2"><code>bg-white</code></td>
<td class="border px-4 py-2">3.5:1</td>
<td class="border px-4 py-2 text-red-500 font-medium">Fail</td>
</tr>
<tr>
<td class="border px-4 py-2"><code>text-gray-400</code></td>
<td class="border px-4 py-2"><code>bg-white</code></td>
<td class="border px-4 py-2">2.6:1</td>
<td class="border px-4 py-2 text-red-500 font-medium">Fail</td>
</tr>
</tbody>
</table>
</div>
</div>
</template>
Bài tập 11: Gradient text sử dụng bg-gradient-to-r + bg-clip-text
Yêu cầu: Tạo heading với chữ gradient, sử dụng bg-clip-text + text-transparent.
<template>
<div class="max-w-3xl mx-auto p-12 space-y-12 bg-slate-900 rounded-2xl">
<!-- Gradient text cơ bản: xanh -> tím -->
<h2 class="text-4xl font-black bg-gradient-to-r from-blue-400 to-purple-500 bg-clip-text text-transparent">
Gradient từ xanh sang tím
</h2>
<!-- Gradient text 3 màu -->
<h2 class="text-4xl font-black bg-gradient-to-r from-rose-400 via-fuchsia-400 to-indigo-400 bg-clip-text text-transparent">
Gradient 3 màu qua fuchsia
</h2>
<!-- Gradient text với hướng khác -->
<h2 class="text-4xl font-black bg-gradient-to-br from-emerald-300 to-teal-500 bg-clip-text text-transparent">
Gradient chéo xuống phải
</h2>
<!-- Gradient text kết hợp animation (concept) -->
<h2 class="text-4xl font-black bg-gradient-to-r from-amber-400 via-orange-500 to-red-500 bg-clip-text text-transparent bg-[length:200%_auto] animate-gradient">
Gradient có animation
</h2>
</div>
</template>
<style scoped>
@keyframes gradient-shift {
0% { background-position: 0% center; }
100% { background-position: 200% center; }
}
.animate-gradient {
animation: gradient-shift 3s linear infinite;
}
</style>
8. Background (bg-*, bg-gradient-*, bg-opacity)
Background cơ bản
<div class="bg-red-500">Màu nền đơn</div>
<div class="bg-white">Nền trắng</div>
<div class="bg-transparent">Nền trong suốt</div>
<div class="bg-current">Dùng màu text hiện tại</div>
Gradient (Linear, Radial, Conic)
<!-- Linear gradient -->
<div class="bg-gradient-to-r from-cyan-500 to-blue-500">
Gradient trái -> phải
</div>
<div class="bg-gradient-to-b from-white to-gray-100">
Gradient trên -> dưới
</div>
<div class="bg-gradient-to-tr from-pink-500 via-red-500 to-yellow-500">
Gradient chéo với via (middle stop)
</div>
bg-radial-* và bg-conic-* mà không cần custom CSS.<!-- Radial gradient -->
<div class="bg-radial from-white to-slate-300">
Radial gradient từ tâm
</div>
<div class="bg-radial from-blue-100 via-blue-200 to-blue-400">
Radial gradient 3 stops
</div>
<div class="bg-radial-[at_25%_25%] from-white to-slate-300">
Radial gradient với tâm tại 25% 25%
</div>
<!-- Conic gradient -->
<div class="bg-conic from-red-500 via-yellow-500 to-red-500">
Conic gradient — hiệu ứng vòng tròn
</div>
<div class="bg-conic/[at_50%] from-sky-400 via-indigo-400 to-sky-400">
Conic với tâm xác định
</div>
Background Clip, Origin, Position
<!-- bg-clip: kiểm soát vùng background chiếm -->
<div class="bg-clip-border">Background đến border (default)</div>
<div class="bg-clip-padding">Background đến padding</div>
<div class="bg-clip-content">Background chỉ trong content box</div>
<div class="bg-clip-text">Background chỉ hiển thị trên text</div>
<!-- bg-origin: kiểm soát gốc tọa độ background -->
<div class="bg-origin-border">Gốc từ border</div>
<div class="bg-origin-padding">Gốc từ padding (default)</div>
<div class="bg-origin-content">Gốc từ content</div>
<!-- bg-position -->
<div class="bg-center">Căn giữa</div>
<div class="bg-top">Căn trên</div>
<div class="bg-right-bottom">Góc phải dưới</div>
<!-- bg-repeat -->
<div class="bg-repeat">Lặp</div>
<div class="bg-no-repeat">Không lặp</div>
<div class="bg-repeat-x">Lặp ngang</div>
<div class="bg-repeat-y">Lặp dọc</div>
Bài tập 12: Hero section với gradient overlay trên ảnh
Yêu cầu: Hero section có background image + gradient overlay + nội dung text.
<template>
<section class="relative min-h-[80vh] flex items-center bg-cover bg-center"
style="background-image: url('https://images.unsplash.com/photo-1522071820081-009f0129c71c')">
<!-- Gradient overlay: tối dần từ trái sang phải -->
<div class="absolute inset-0 bg-gradient-to-r from-slate-900/90 via-slate-900/50 to-transparent"></div>
<!-- Nội dung nằm trên overlay -->
<div class="relative z-10 max-w-2xl px-8 lg:px-16 py-20">
<span class="inline-block px-3 py-1 bg-indigo-500/20 text-indigo-300 text-sm font-medium rounded-full mb-6">
Ra mắt tháng 7/2026
</span>
<h1 class="text-4xl sm:text-5xl lg:text-6xl font-black text-white leading-none tracking-tight">
Làm việc nhóm
<br/>
<span class="bg-gradient-to-r from-indigo-400 to-cyan-400 bg-clip-text text-transparent">
hiệu quả hơn
</span>
</h1>
<p class="mt-6 text-lg text-slate-300 leading-relaxed max-w-lg">
Nền tảng collaboration thế hệ mới — real-time editing,
video call tích hợp, và AI assistant trong cùng một workspace.
</p>
<div class="mt-8 flex gap-4">
<button class="px-6 py-3 bg-indigo-500 text-white font-semibold rounded-lg hover:bg-indigo-600 transition-colors">
Dùng thử miễn phí
</button>
<button class="px-6 py-3 border border-white/30 text-white font-semibold rounded-lg hover:bg-white/10 transition-colors">
Xem video
</button>
</div>
</div>
</section>
</template>
Bài tập 13: Card với radial gradient background
Yêu cầu: Thiết kế pricing card với radial gradient nền tạo điểm nhấn.
<template>
<div class="max-w-sm mx-auto">
<div class="relative overflow-hidden rounded-2xl border border-slate-200 bg-white p-8">
<!-- Radial gradient accent ở góc trên phải -->
<div class="absolute -top-20 -right-20 w-60 h-60 bg-radial from-indigo-100 to-transparent rounded-full"></div>
<!-- Nội dung -->
<div class="relative z-10">
<span class="text-sm font-semibold text-indigo-600 uppercase tracking-wider">Pro Plan</span>
<div class="mt-4">
<span class="text-5xl font-black text-gray-900">$29</span>
<span class="text-gray-500 text-lg">/tháng</span>
</div>
<p class="mt-4 text-gray-600 text-sm leading-relaxed">
Dành cho freelancer và team nhỏ cần đầy đủ tính năng.
</p>
<ul class="mt-6 space-y-3">
<li class="flex items-center gap-2 text-sm text-gray-700">
<span class="text-emerald-500 font-bold">✓</span>
Unlimited projects
</li>
<li class="flex items-center gap-2 text-sm text-gray-700">
<span class="text-emerald-500 font-bold">✓</span>
50GB storage
</li>
<li class="flex items-center gap-2 text-sm text-gray-700">
<span class="text-emerald-500 font-bold">✓</span>
Priority support
</li>
<li class="flex items-center gap-2 text-sm text-gray-700">
<span class="text-emerald-500 font-bold">✓</span>
API access
</li>
</ul>
<button class="mt-8 w-full py-3 bg-indigo-600 text-white font-semibold rounded-lg hover:bg-indigo-700 transition-colors">
Bắt đầu dùng thử
</button>
</div>
</div>
</div>
</template>
Bài tập 14: Striped table rows với even:bg-gray-50
Yêu cầu: Bảng dữ liệu với hàng xen kẽ màu, header nổi bật.
<template>
<div class="max-w-3xl mx-auto p-8">
<div class="overflow-hidden rounded-xl border border-gray-200">
<table class="w-full text-sm">
<thead>
<tr class="bg-gray-900 text-white">
<th class="px-6 py-3.5 text-left font-semibold">Tên dự án</th>
<th class="px-6 py-3.5 text-left font-semibold">Trạng thái</th>
<th class="px-6 py-3.5 text-left font-semibold">Thành viên</th>
<th class="px-6 py-3.5 text-right font-semibold">Tiến độ</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-200">
<tr class="even:bg-gray-50 hover:bg-indigo-50/50 transition-colors">
<td class="px-6 py-4 font-medium text-gray-900">Redesign Website</td>
<td class="px-6 py-4">
<span class="px-2.5 py-0.5 bg-emerald-100 text-emerald-700 text-xs font-medium rounded-full">Active</span>
</td>
<td class="px-6 py-4 text-gray-600">8 người</td>
<td class="px-6 py-4 text-right font-medium text-gray-900">75%</td>
</tr>
<tr class="even:bg-gray-50 hover:bg-indigo-50/50 transition-colors">
<td class="px-6 py-4 font-medium text-gray-900">Mobile App v2</td>
<td class="px-6 py-4">
<span class="px-2.5 py-0.5 bg-amber-100 text-amber-700 text-xs font-medium rounded-full">Review</span>
</td>
<td class="px-6 py-4 text-gray-600">5 người</td>
<td class="px-6 py-4 text-right font-medium text-gray-900">90%</td>
</tr>
<tr class="even:bg-gray-50 hover:bg-indigo-50/50 transition-colors">
<td class="px-6 py-4 font-medium text-gray-900">API Integration</td>
<td class="px-6 py-4">
<span class="px-2.5 py-0.5 bg-blue-100 text-blue-700 text-xs font-medium rounded-full">In Progress</span>
</td>
<td class="px-6 py-4 text-gray-600">3 người</td>
<td class="px-6 py-4 text-right font-medium text-gray-900">45%</td>
</tr>
<tr class="even:bg-gray-50 hover:bg-indigo-50/50 transition-colors">
<td class="px-6 py-4 font-medium text-gray-900">Documentation</td>
<td class="px-6 py-4">
<span class="px-2.5 py-0.5 bg-gray-100 text-gray-600 text-xs font-medium rounded-full">Draft</span>
</td>
<td class="px-6 py-4 text-gray-600">2 người</td>
<td class="px-6 py-4 text-right font-medium text-gray-900">20%</td>
</tr>
</tbody>
</table>
</div>
</div>
</template>
9. Border & Outline
Border
<!-- Border cơ bản -->
<div class="border">Border 1px solid (default)</div>
<div class="border-2">Border 2px</div>
<div class="border-4">Border 4px</div>
<div class="border-0">Không border</div>
<!-- Border color -->
<div class="border border-red-500">Border đỏ</div>
<div class="border border-slate-200">Border xám nhạt</div>
<!-- Border style -->
<div class="border border-dashed">Border đứt đoạn</div>
<div class="border border-dotted">Border chấm</div>
<div class="border border-double">Border đôi</div>
<!-- Border từng cạnh -->
<div class="border-t-2 border-b border-l-4 border-r-0">
Mỗi cạnh độ dày khác nhau
</div>
Border Radius
<div class="rounded-sm">Bo góc nhỏ (2px)</div>
<div class="rounded">Bo góc vừa (4px)</div>
<div class="rounded-md">Bo góc trung bình (6px)</div>
<div class="rounded-lg">Bo góc lớn (8px)</div>
<div class="rounded-xl">Bo góc XL (12px)</div>
<div class="rounded-2xl">Bo góc 2XL (16px)</div>
<div class="rounded-3xl">Bo góc 3XL (24px)</div>
<div class="rounded-full">Bo tròn hoàn toàn (circle/pill)</div>
<!-- Bo góc từng góc -->
<div class="rounded-t-xl rounded-b-sm">Bo góc riêng biệt</div>
<div class="rounded-tl-lg rounded-br-lg">Chỉ bo 2 góc chéo</div>
Outline & Ring
<!-- Outline (không chiếm không gian, nằm ngoài border) -->
<button class="outline outline-2 outline-offset-2 outline-blue-500">
Outline style
</button>
<!-- Ring (thay thế outline với box-shadow — đẹp hơn) -->
<input class="ring-2 ring-blue-500 focus:ring-4" placeholder="Ring focus" />
<!-- Ring inset -->
<div class="ring-2 ring-inset ring-indigo-500">Ring inset</div>
inset-shadow-* và inset-ring-*: Thay thế hoàn toàn cho shadow-inner và ring-inset cũ. Cú pháp độc lập, rõ ràng hơn.<div class="inset-shadow-sm">Inner shadow nhỏ</div>
<div class="inset-shadow-md">Inner shadow vừa</div>
<div class="inset-ring-2 inset-ring-indigo-500">Inner ring</div>
Bài tập 15: Input field với focus ring styling
Yêu cầu: Form input field với trạng thái mặc định, focus, error.
<template>
<div class="max-w-md mx-auto p-8 space-y-6">
<h2 class="text-xl font-bold text-gray-900">Form đăng nhập</h2>
<!-- Input mặc định -->
<div>
<label class="block text-sm font-medium text-gray-700 mb-1.5">Email</label>
<input
type="email"
placeholder="you@example.com"
class="w-full px-4 py-2.5 border border-gray-300 rounded-lg text-sm
placeholder:text-gray-400
focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500
transition-shadow duration-200"
/>
</div>
<!-- Input với error state -->
<div>
<label class="block text-sm font-medium text-gray-700 mb-1.5">Mật khẩu</label>
<input
type="password"
placeholder="Nhập mật khẩu"
class="w-full px-4 py-2.5 border border-red-300 rounded-lg text-sm
placeholder:text-gray-400
focus:outline-none focus:ring-2 focus:ring-red-500 focus:border-red-500
transition-shadow duration-200"
/>
<p class="mt-1 text-xs text-red-600">Mật khẩu phải có ít nhất 8 ký tự</p>
</div>
<!-- Input disabled -->
<div>
<label class="block text-sm font-medium text-gray-400 mb-1.5">Username (khóa)</label>
<input
type="text"
value="nguyenvana"
disabled
class="w-full px-4 py-2.5 border border-gray-200 rounded-lg text-sm
bg-gray-50 text-gray-400 cursor-not-allowed"
/>
</div>
<button class="w-full py-2.5 bg-indigo-600 text-white font-semibold rounded-lg
hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2
transition-colors duration-200">
Đăng nhập
</button>
</div>
</template>
Bài tập 16: Card với hover border effect
Yêu cầu: Grid card có border chuyển màu và nổi shadow khi hover.
<template>
<div class="max-w-5xl mx-auto p-8">
<h2 class="text-2xl font-bold text-gray-900 mb-8">Dịch vụ của chúng tôi</h2>
<div class="grid grid-cols-1 md:grid-cols-3 gap-6">
<!-- Card 1 -->
<div class="group p-6 bg-white rounded-xl border border-gray-200
hover:border-indigo-400 hover:shadow-lg
transition-all duration-300 cursor-pointer">
<div class="w-12 h-12 bg-indigo-100 rounded-lg flex items-center justify-center mb-4
group-hover:bg-indigo-200 transition-colors">
<svg class="w-6 h-6 text-indigo-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M9.75 17L9 20l-1 1h8l-1-1-.75-3M3 13h18M5 17h14a2 2 0 002-2V5a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z" />
</svg>
</div>
<h3 class="text-lg font-semibold text-gray-900 group-hover:text-indigo-600 transition-colors">
Web Development
</h3>
<p class="mt-2 text-sm text-gray-600 leading-relaxed">
Xây dựng website chuẩn SEO, tốc độ cao với công nghệ mới nhất.
</p>
</div>
<!-- Card 2 -->
<div class="group p-6 bg-white rounded-xl border border-gray-200
hover:border-emerald-400 hover:shadow-lg
transition-all duration-300 cursor-pointer">
<div class="w-12 h-12 bg-emerald-100 rounded-lg flex items-center justify-center mb-4
group-hover:bg-emerald-200 transition-colors">
<svg class="w-6 h-6 text-emerald-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M12 18h.01M7 21h10a2 2 0 002-2V5a2 2 0 00-2-2H7a2 2 0 00-2 2v14a2 2 0 002 2z" />
</svg>
</div>
<h3 class="text-lg font-semibold text-gray-900 group-hover:text-emerald-600 transition-colors">
Mobile Apps
</h3>
<p class="mt-2 text-sm text-gray-600 leading-relaxed">
Ứng dụng iOS và Android native, hiệu năng cao, UX mượt mà.
</p>
</div>
<!-- Card 3 -->
<div class="group p-6 bg-white rounded-xl border border-gray-200
hover:border-purple-400 hover:shadow-lg
transition-all duration-300 cursor-pointer">
<div class="w-12 h-12 bg-purple-100 rounded-lg flex items-center justify-center mb-4
group-hover:bg-purple-200 transition-colors">
<svg class="w-6 h-6 text-purple-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M13 10V3L4 14h7v7l9-11h-7z" />
</svg>
</div>
<h3 class="text-lg font-semibold text-gray-900 group-hover:text-purple-600 transition-colors">
AI Solutions
</h3>
<p class="mt-2 text-sm text-gray-600 leading-relaxed">
Tích hợp AI/ML vào sản phẩm — chatbot, recommendation, automation.
</p>
</div>
</div>
</div>
</template>
Bài tập 17: Avatar với rounded-full + ring
Yêu cầu: Avatar group với ring, online indicator, và stacked layout.
<template>
<div class="max-w-md mx-auto p-8 space-y-8">
<h2 class="text-xl font-bold text-gray-900">Avatar Styles</h2>
<!-- Avatar đơn với ring -->
<div class="flex items-center gap-4">
<img
src="https://i.pravatar.cc/80?img=1"
alt="User"
class="w-12 h-12 rounded-full ring-2 ring-white shadow-sm"
/>
<div>
<p class="text-sm font-semibold text-gray-900">Nguyen Van A</p>
<p class="text-xs text-gray-500">Fullstack Developer</p>
</div>
</div>
<!-- Avatar với online indicator -->
<div class="flex items-center gap-4">
<div class="relative">
<img
src="https://i.pravatar.cc/80?img=5"
alt="User"
class="w-12 h-12 rounded-full ring-2 ring-white"
/>
<span class="absolute bottom-0 right-0 w-3.5 h-3.5 bg-emerald-500 border-2 border-white rounded-full"></span>
</div>
<div>
<p class="text-sm font-semibold text-gray-900">Tran Thi B</p>
<p class="text-xs text-emerald-600 font-medium">Online</p>
</div>
</div>
<!-- Avatar với offline indicator -->
<div class="flex items-center gap-4">
<div class="relative">
<img
src="https://i.pravatar.cc/80?img=8"
alt="User"
class="w-12 h-12 rounded-full ring-2 ring-white"
/>
<span class="absolute bottom-0 right-0 w-3.5 h-3.5 bg-gray-400 border-2 border-white rounded-full"></span>
</div>
<div>
<p class="text-sm font-semibold text-gray-900">Le Van C</p>
<p class="text-xs text-gray-400">Offline</p>
</div>
</div>
<!-- Stacked avatar group -->
<div>
<p class="text-sm text-gray-500 mb-3">12 thành viên trong team</p>
<div class="flex -space-x-2">
<img src="https://i.pravatar.cc/40?img=1" class="w-10 h-10 rounded-full ring-2 ring-white" alt="" />
<img src="https://i.pravatar.cc/40?img=2" class="w-10 h-10 rounded-full ring-2 ring-white" alt="" />
<img src="https://i.pravatar.cc/40?img=3" class="w-10 h-10 rounded-full ring-2 ring-white" alt="" />
<img src="https://i.pravatar.cc/40?img=4" class="w-10 h-10 rounded-full ring-2 ring-white" alt="" />
<div class="w-10 h-10 rounded-full ring-2 ring-white bg-indigo-100 flex items-center justify-center text-xs font-bold text-indigo-600">
+8
</div>
</div>
</div>
<!-- Avatar sizes -->
<div class="flex items-end gap-4">
<img src="https://i.pravatar.cc/24?img=6" class="w-6 h-6 rounded-full ring-1 ring-white" alt="" />
<img src="https://i.pravatar.cc/32?img=6" class="w-8 h-8 rounded-full ring-2 ring-white" alt="" />
<img src="https://i.pravatar.cc/48?img=6" class="w-12 h-12 rounded-full ring-2 ring-white" alt="" />
<img src="https://i.pravatar.cc/64?img=6" class="w-16 h-16 rounded-full ring-2 ring-white" alt="" />
<img src="https://i.pravatar.cc/96?img=6" class="w-24 h-24 rounded-full ring-2 ring-white" alt="" />
</div>
</div>
</template>
10. Divide & Box Shadow
Divide
<!-- Divide ngang giữa các item -->
<ul class="divide-y divide-gray-200">
<li class="py-3">Item 1</li>
<li class="py-3">Item 2</li>
<li class="py-3">Item 3</li>
</ul>
<!-- Divide dọc giữa các item trong flex row -->
<div class="flex divide-x divide-gray-300">
<div class="px-4">Column 1</div>
<div class="px-4">Column 2</div>
<div class="px-4">Column 3</div>
</div>
<!-- Đảo chiều divide -->
<div class="flex flex-row-reverse divide-x divide-x-reverse">
<div class="px-4">RTL column</div>
</div>
Box Shadow
<div class="shadow-sm">Shadow nhỏ — card tinh tế</div>
<div class="shadow">Shadow vừa (default)</div>
<div class="shadow-md">Shadow trung bình — card nổi</div>
<div class="shadow-lg">Shadow lớn — modal, dropdown</div>
<div class="shadow-xl">Shadow XL — elevated component</div>
<div class="shadow-2xl">Shadow 2XL — floating element</div>
<div class="shadow-inner">Shadow bên trong</div>
<div class="shadow-none">Không shadow</div>
/* Custom shadow trong @theme */
@theme {
--shadow-card: 0 2px 15px -3px rgba(0, 0, 0, 0.07),
0 10px 20px -2px rgba(0, 0, 0, 0.04);
--shadow-glow: 0 0 20px rgba(99, 102, 241, 0.3);
}
Bài tập 18: Stacked list với divider lines
Yêu cầu: Danh sách notification với divider giữa các item.
<template>
<div class="max-w-lg mx-auto p-8">
<div class="bg-white rounded-xl border border-gray-200 shadow-sm overflow-hidden">
<!-- Header -->
<div class="px-5 py-4 border-b border-gray-200">
<h3 class="text-lg font-semibold text-gray-900">Thông báo</h3>
</div>
<!-- List với divide -->
<ul class="divide-y divide-gray-100">
<li class="px-5 py-4 hover:bg-gray-50 transition-colors cursor-pointer">
<div class="flex items-start gap-3">
<div class="flex-shrink-0 w-9 h-9 bg-blue-100 rounded-full flex items-center justify-center">
<span class="text-blue-600 text-sm">💬</span>
</div>
<div class="flex-1 min-w-0">
<p class="text-sm font-medium text-gray-900">Bình luận mới</p>
<p class="text-sm text-gray-600 truncate">Nguyen Van A đã bình luận vào bài viết của bạn</p>
<p class="text-xs text-gray-400 mt-1">5 phút trước</p>
</div>
<span class="flex-shrink-0 w-2 h-2 bg-blue-500 rounded-full mt-2"></span>
</div>
</li>
<li class="px-5 py-4 hover:bg-gray-50 transition-colors cursor-pointer">
<div class="flex items-start gap-3">
<div class="flex-shrink-0 w-9 h-9 bg-emerald-100 rounded-full flex items-center justify-center">
<span class="text-emerald-600 text-sm">✓</span>
</div>
<div class="flex-1 min-w-0">
<p class="text-sm font-medium text-gray-900">Deploy thành công</p>
<p class="text-sm text-gray-600 truncate">Production build #142 đã deploy thành công</p>
<p class="text-xs text-gray-400 mt-1">1 giờ trước</p>
</div>
</div>
</li>
<li class="px-5 py-4 hover:bg-gray-50 transition-colors cursor-pointer">
<div class="flex items-start gap-3">
<div class="flex-shrink-0 w-9 h-9 bg-amber-100 rounded-full flex items-center justify-center">
<span class="text-amber-600 text-sm">⚠</span>
</div>
<div class="flex-1 min-w-0">
<p class="text-sm font-medium text-gray-900">Cảnh báo billing</p>
<p class="text-sm text-gray-600 truncate">Gói Pro của bạn sẽ hết hạn sau 3 ngày</p>
<p class="text-xs text-gray-400 mt-1">3 giờ trước</p>
</div>
<span class="flex-shrink-0 w-2 h-2 bg-amber-500 rounded-full mt-2"></span>
</div>
</li>
<li class="px-5 py-4 hover:bg-gray-50 transition-colors cursor-pointer">
<div class="flex items-start gap-3">
<div class="flex-shrink-0 w-9 h-9 bg-purple-100 rounded-full flex items-center justify-center">
<span class="text-purple-600 text-sm">🚀</span>
</div>
<div class="flex-1 min-w-0">
<p class="text-sm font-medium text-gray-900">Tính năng mới</p>
<p class="text-sm text-gray-600 truncate">AI code review đã sẵn sàng trên workspace của bạn</p>
<p class="text-xs text-gray-400 mt-1">1 ngày trước</p>
</div>
</div>
</li>
</ul>
<!-- Footer -->
<div class="px-5 py-3 border-t border-gray-200 bg-gray-50">
<button class="text-sm font-medium text-indigo-600 hover:text-indigo-700 transition-colors">
Xem tất cả thông báo
</button>
</div>
</div>
</div>
</template>
Bài tập 19: Card elevation system (sm -> 2xl)
Yêu cầu: Demo toàn bộ 6 level shadow của Tailwind trên card giống hệt nhau.
<template>
<div class="max-w-5xl mx-auto p-8">
<h2 class="text-2xl font-bold text-gray-900 mb-8">Card Elevation System</h2>
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-8">
<!-- shadow-sm -->
<div class="shadow-sm bg-white rounded-xl p-6">
<span class="text-xs font-semibold text-gray-400 uppercase tracking-wider">Level 1</span>
<h3 class="text-lg font-semibold text-gray-900 mt-1">shadow-sm</h3>
<p class="text-sm text-gray-500 mt-2">Tinh tế, nhẹ nhàng. Dùng cho card trong layout phẳng.</p>
</div>
<!-- shadow -->
<div class="shadow bg-white rounded-xl p-6">
<span class="text-xs font-semibold text-gray-400 uppercase tracking-wider">Level 2</span>
<h3 class="text-lg font-semibold text-gray-900 mt-1">shadow</h3>
<p class="text-sm text-gray-500 mt-2">Default elevation. Card cơ bản, section container.</p>
</div>
<!-- shadow-md -->
<div class="shadow-md bg-white rounded-xl p-6">
<span class="text-xs font-semibold text-gray-400 uppercase tracking-wider">Level 3</span>
<h3 class="text-lg font-semibold text-gray-900 mt-1">shadow-md</h3>
<p class="text-sm text-gray-500 mt-2">Card nổi vừa. Dùng cho card tương tác được.</p>
</div>
<!-- shadow-lg -->
<div class="shadow-lg bg-white rounded-xl p-6">
<span class="text-xs font-semibold text-gray-400 uppercase tracking-wider">Level 4</span>
<h3 class="text-lg font-semibold text-gray-900 mt-1">shadow-lg</h3>
<p class="text-sm text-gray-500 mt-2">Dropdown menu, popover, card hover state.</p>
</div>
<!-- shadow-xl -->
<div class="shadow-xl bg-white rounded-xl p-6">
<span class="text-xs font-semibold text-gray-400 uppercase tracking-wider">Level 5</span>
<h3 class="text-lg font-semibold text-gray-900 mt-1">shadow-xl</h3>
<p class="text-sm text-gray-500 mt-2">Modal, dialog, sticky header khi scroll.</p>
</div>
<!-- shadow-2xl -->
<div class="shadow-2xl bg-white rounded-xl p-6">
<span class="text-xs font-semibold text-gray-400 uppercase tracking-wider">Level 6</span>
<h3 class="text-lg font-semibold text-gray-900 mt-1">shadow-2xl</h3>
<p class="text-sm text-gray-500 mt-2">Floating action button, toast notification, tooltip.</p>
</div>
</div>
</div>
</template>
1. Layout & Spacing
Tailwind CSS v4 layout system — container queries, display types, flexbox, grid, spacing (padding, margin, gap). Bài tập từng khái niệm.
3. Interactive & Effects
Tailwind CSS v4 — hover/focus/active states, transitions, transforms 3D, animations, filters, backdrop. Bài tập interactive components.