Bài 5. Responsive và các biến thể trạng thái

Sức mạnh của Tailwind nằm ở variant: tiền tố điều kiện áp dụng lớp khi màn hình đủ rộng (md:), khi rê chuột (hover:), focus, khi phần tử cha được rê (group-hover:), khi phần tử anh em được chọn (peer-checked:), khi ở chế độ tối (dark:). Bài này hệ thống các variant quan trọng.

55 phútTrung cấp
Bạn sẽ học được
  • Thiết kế mobile-first với sm, md, lg, xl, 2xl
  • Dùng hover, focus, focus-visible, active, disabled
  • Dùng group-* và peer-*
  • Dùng first, last, odd, even, has-*, container query @container

Một số khái niệm

Giống Bootstrap, Tailwind là mobile-first: lớp không tiền tố áp dụng mọi màn hình, md:grid-cols-3 áp dụng từ 768px trở lên. Breakpoint: sm 640px, md 768px, lg 1024px, xl 1280px, 2xl 1536px. Có thể kết hợp nhiều variant: md:hover:bg-green-700, dark:md:text-white.

VariantVí dụÁp dụng khi
Responsivemd:flex lg:w-1/3Màn hình ≥ breakpoint
Trạng tháihover:, focus:, active:, disabled:Tương tác
focus-visible:focus-visible:ring-2Focus bằng bàn phím
group-hover:Cha có class group được rêThẻ đổi màu cả khối
peer-checked:Phần tử anh em có class peer được chọnCông tắc, tab không JS
first:, last:, odd:, even:odd:bg-slate-50Theo vị trí
has-[:checked]:Cha chứa phần tử được chọnGiống :has()
@md: (container)@container + @md:flex-rowKhung chứa ≥ 448px
max-md:max-md:hiddenNhỏ hơn md

Lưới responsive

<div class="grid grid-cols-1 gap-3 sm:grid-cols-2 lg:grid-cols-4">
  <div class="rounded-xl bg-sky-100 p-4 text-center">Python</div><div class="rounded-xl bg-sky-100 p-4 text-center">JavaScript</div>
  <div class="rounded-xl bg-sky-100 p-4 text-center">PHP</div><div class="rounded-xl bg-sky-100 p-4 text-center">SQL</div>
</div>
<p class="mt-2 text-sm text-slate-500"><span class="md:hidden">Bạn đang ở màn hình nhỏ (dưới md).</span><span class="max-md:hidden">Bạn đang ở màn hình từ md trở lên.</span></p>
Kết quả hiển thị

hover, focus, group, peer

<a href="#" class="group block max-w-xs rounded-xl border border-slate-200 p-4 transition hover:border-green-500 hover:shadow-lg">
  <h3 class="font-semibold group-hover:text-green-700">Khóa học CSS</h3>
  <p class="text-sm text-slate-500">Rê chuột vào cả thẻ, tiêu đề đổi màu, mũi tên dịch sang <span class="inline-block transition group-hover:translate-x-1">→</span></p>
</a>
<label class="mt-4 inline-flex cursor-pointer items-center gap-3">
  <input type="checkbox" class="peer sr-only">
  <span class="relative h-6 w-11 rounded-full bg-slate-300 transition peer-checked:bg-green-600 after:absolute after:left-0.5 after:top-0.5 after:size-5 after:rounded-full after:bg-white after:transition peer-checked:after:translate-x-5"></span>
  <span class="text-sm">Công tắc không cần JavaScript</span>
</label>
<input class="mt-3 block w-64 rounded-lg border border-slate-300 px-3 py-2 outline-none focus:border-green-600 focus:ring-4 focus:ring-green-600/20 invalid:border-rose-500" type="email" placeholder="Email (gõ sai để thấy invalid:)">
Kết quả hiển thị

Vị trí, :has và container query

<ul class="max-w-xs divide-y divide-slate-200 rounded-lg border">
  <li class="p-2 first:font-bold odd:bg-slate-50">Sơn La</li><li class="p-2 odd:bg-slate-50">Điện Biên</li><li class="p-2 odd:bg-slate-50 last:text-rose-600">Lai Châu</li>
</ul>
<label class="mt-3 block max-w-xs rounded-lg border-2 p-3 has-[:checked]:border-green-600 has-[:checked]:bg-green-50"><input type="radio" name="g" class="mr-2">Gói Cơ bản (chọn để thấy has-)</label>
<div class="@container mt-3 max-w-md rounded-lg border p-3"><div class="flex flex-col gap-2 @sm:flex-row"><div class="h-16 rounded bg-slate-300 @sm:w-28"></div><p class="text-sm">Thẻ đổi bố cục theo khung chứa với @container và @sm:</p></div></div>
Kết quả hiển thị
Mẹo hay

Đặt variant theo thứ tự nhất quán (responsive trước, rồi trạng thái): md:hover:; tiện ích Prettier plugin for Tailwind tự sắp xếp lớp theo thứ tự chuẩn.

Lưu ý

hover: trên điện thoại cảm ứng có thể “dính” sau khi chạm; Tailwind v4 mặc định chỉ áp dụng hover cho thiết bị có chuột (@media (hover: hover)).

Thực hành
  1. Lưới thẻ 1 → 2 → 3 → 4 cột theo breakpoint.
  2. Thẻ bài viết: rê chuột cả thẻ, ảnh phóng to (group-hover:scale-105).
  3. Làm tab hoặc công tắc bằng peer-checked.
  4. Ẩn sidebar trên điện thoại bằng max-lg:hidden.
Tóm tắt bài học
  • Mobile-first: sm, md, lg, xl, 2xl; max-* cho chiều ngược.
  • hover, focus, focus-visible, active, disabled, invalid.
  • group-*, peer-*, has-[...] cho quan hệ giữa phần tử.
  • @container + @sm/@md cho container query.