Tailwind CSS

Layout & Spacing — Container, Display, Flexbox, Grid

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.

Tổng quan

Layout và spacing là nền tảng của mọi giao diện web. Tailwind CSS v4 cung cấp bộ utility cực mạnh cho display, position, flexbox, grid, spacing, sizing, overflow và scrollbar — tất cả đều map trực tiếp đến CSS nhưng nhanh hơn nhờ không phải viết CSS rời.

Câu PV:"Tailwind CSS xử lý layout như thế nào so với CSS thuần?"

"Tailwind cung cấp utility class map 1-1 với CSS properties — flex = display: flex, grid-cols-3 = grid-template-columns: repeat(3, 1fr). Điểm mạnh: responsive variants (md:flex, lg:grid-cols-4) viết ngay trong HTML không cần media query riêng. Container queries cũng có sẵn (@container, @md:grid-cols-2) từ v4.0."


1. Display

Các giá trị display được ánh xạ thành class:

ClassCSSGhi chú
blockdisplay: block
inlinedisplay: inline
inline-blockdisplay: inline-block
inline-flexdisplay: inline-flexFlex container nhưng inline
flexdisplay: flex
inline-griddisplay: inline-grid
griddisplay: grid
flow-rootdisplay: flow-rootClear float không cần clearfix
hiddendisplay: noneẨn element, xóa khỏi flow
contentsdisplay: contentsElement bị "bỏ qua", children lên thay
table, table-row, table-cell, table-caption, table-column, table-column-group, table-footer-group, table-header-group, table-row-groupdisplay: table; v.v...Layout kiểu bảng

Ví dụ cơ bản

<!-- Block vs Inline -->
<div class="block bg-blue-200 p-2 mb-2">Block — chiếm full width</div>
<span class="inline bg-green-200 p-2">Inline 1</span>
<span class="inline bg-green-200 p-2">Inline 2</span>

<!-- Inline-flex — container flex nhưng không ngắt dòng -->
<span class="inline-flex items-center gap-2 bg-yellow-200 px-3 py-1 rounded-full">
  <span class="w-2 h-2 bg-green-500 rounded-full"></span>
  Online
</span>

<!-- Contents — bỏ qua wrapper -->
<div class="grid grid-cols-2 gap-4">
  <div class="contents">
    <div class="bg-red-200 p-4">Item 1</div>
    <div class="bg-red-200 p-4">Item 2</div>
  </div>
</div>
contents hữu ích khi nào? Khi bạn có wrapper component nhưng không muốn nó ảnh hưởng đến grid/flex layout của parent. Ví dụ: <Card> component render children trực tiếp vào grid cha mà không tạo wrapper div thừa.

Bài tập 1: Navigation bar với flexhidden cho mobile toggle

Yêu cầu: Tạo navigation bar có logo bên trái, menu links ở giữa, button bên phải. Trên mobile (< 768px), menu links ẩn đi và hiển thị hamburger button.

<nav class="flex items-center justify-between px-6 py-4 bg-white shadow">
  <!-- Logo -->
  <a href="#" class="text-xl font-bold text-blue-600">Brand</a>

  <!-- Menu links — ẩn trên mobile, hiện từ md trở lên -->
  <div class="hidden md:flex items-center gap-6">
    <a href="#" class="text-gray-700 hover:text-blue-600 transition-colors">Home</a>
    <a href="#" class="text-gray-700 hover:text-blue-600 transition-colors">Features</a>
    <a href="#" class="text-gray-700 hover:text-blue-600 transition-colors">Pricing</a>
    <a href="#" class="text-gray-700 hover:text-blue-600 transition-colors">About</a>
  </div>

  <!-- Button bên phải -->
  <button class="hidden md:block bg-blue-600 text-white px-4 py-2 rounded-lg hover:bg-blue-700 transition-colors">
    Get Started
  </button>

  <!-- Hamburger — chỉ hiện trên mobile -->
  <button class="md:hidden text-gray-700">
    <svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
      <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
            d="M4 6h16M4 12h16M4 18h16"/>
    </svg>
  </button>
</nav>
Ý chính:hidden md:flex là pattern mobile-first kinh điển trong Tailwind — element bắt đầu ở trạng thái ẩn, hiện ra từ breakpoint chỉ định.

Bài tập 2: Hide/show sidebar với hidden + breakpoint variants

Yêu cầu: Layout có sidebar bên trái. Trên mobile, sidebar bị ẩn, chỉ hiện khi bấm toggle. Trên desktop (lg), sidebar luôn hiện.

<div class="flex min-h-screen">
  <!-- Overlay — chỉ trên mobile khi sidebar mở -->
  <div class="fixed inset-0 bg-black/50 z-10 lg:hidden" id="overlay"></div>

  <!-- Sidebar — ẩn mobile mặc định, luôn hiện trên lg -->
  <aside class="fixed lg:static inset-y-0 left-0 z-20 w-64 bg-gray-900 text-white
                -translate-x-full lg:translate-x-0 transition-transform duration-300"
         id="sidebar">
    <div class="p-6">
      <h2 class="text-xl font-bold mb-6">Sidebar</h2>
      <nav class="flex flex-col gap-3">
        <a href="#" class="text-gray-300 hover:text-white transition-colors">Dashboard</a>
        <a href="#" class="text-gray-300 hover:text-white transition-colors">Analytics</a>
        <a href="#" class="text-gray-300 hover:text-white transition-colors">Settings</a>
      </nav>
    </div>
  </aside>

  <!-- Main content -->
  <main class="flex-1 p-6 bg-gray-100">
    <button class="lg:hidden mb-4 px-3 py-2 bg-gray-800 text-white rounded"
            onclick="document.getElementById('sidebar').classList.toggle('-translate-x-full')">
      Toggle Sidebar
    </button>
    <h1 class="text-2xl font-bold">Main Content</h1>
  </main>
</div>
Pattern quan trọng:fixed lg:static — thay đổi hoàn toàn positioning context giữa mobile và desktop. Kết hợp -translate-x-full lg:translate-x-0 để slide in/out trên mobile.

2. Position

ClassCSS
staticposition: static
fixedposition: fixed
absoluteposition: absolute
relativeposition: relative
stickyposition: sticky

Inset utilities (inset-*, top-*, right-*, bottom-*, left-*)

<!-- Fixed to top -->
<div class="fixed top-0 inset-x-0 bg-white shadow z-50">Fixed Header</div>

<!-- Absolute centered -->
<div class="relative h-64 bg-gray-200">
  <div class="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 bg-blue-500 text-white p-4 rounded">
    Centered
  </div>
</div>

<!-- Sticky -->
<div class="sticky top-4 bg-yellow-200 p-2 z-10">Sticky — dừng ở top 16px</div>

Z-Index

<div class="z-0 bg-red-200 p-4">z-0</div>
<div class="z-10 bg-blue-200 p-4">z-10</div>
<div class="z-20 bg-green-200 p-4">z-20</div>
<div class="z-30 bg-purple-200 p-4">z-30</div>
<div class="z-40 bg-yellow-200 p-4">z-40</div>
<div class="z-50 bg-pink-200 p-4">z-50</div>
<div class="z-auto bg-gray-200 p-4">z-auto</div>

Bài tập 3: Fixed header luôn trên cùng khi scroll

Yêu cầu: Header cố định trên cùng, không bị nội dung đè lên khi scroll. Nội dung bên dưới cuộn bình thường.

<div class="min-h-[200vh]">
  <!-- Fixed header -->
  <header class="fixed top-0 inset-x-0 z-50 bg-white/80 backdrop-blur-md shadow-sm">
    <div class="max-w-6xl mx-auto flex items-center justify-between px-6 py-4">
      <span class="text-xl font-bold">My App</span>
      <nav class="flex gap-4">
        <a href="#" class="text-gray-600 hover:text-gray-900">Home</a>
        <a href="#" class="text-gray-600 hover:text-gray-900">About</a>
        <a href="#" class="text-gray-600 hover:text-gray-900">Contact</a>
      </nav>
    </div>
  </header>

  <!-- Nội dung — đẩy xuống bằng pt-20 để không bị header che -->
  <main class="pt-20 px-6">
    <h1 class="text-3xl font-bold mb-4">Page Content</h1>
    <p class="text-gray-600 mb-4">Scroll xuống để thấy header vẫn cố định trên cùng.</p>
    <!-- Thêm nhiều nội dung để test scroll -->
    <div class="space-y-4">
      <div class="h-48 bg-gray-100 rounded-lg"></div>
      <div class="h-48 bg-gray-100 rounded-lg"></div>
      <div class="h-48 bg-gray-100 rounded-lg"></div>
      <div class="h-48 bg-gray-100 rounded-lg"></div>
    </div>
  </main>
</div>
Pattern:fixed top-0 inset-x-0 = dính top + full width. bg-white/80 backdrop-blur-md = header trong suốt nhẹ với blur nền phía sau — hiệu ứng phổ biến trên landing page hiện đại.

Bài tập 4: Sticky sidebar trong blog layout

Yêu cầu: Blog layout 2 cột — nội dung chính bên trái, sidebar bên phải. Sidebar sticky — luôn trong viewport khi scroll bài viết dài.

<div class="max-w-6xl mx-auto px-6 py-8">
  <div class="flex flex-col lg:flex-row gap-8">
    <!-- Main content -->
    <article class="flex-1 min-w-0">
      <h1 class="text-3xl font-bold mb-4">Bài viết dài</h1>
      <div class="prose max-w-none">
        <p class="mb-4">Nội dung bài viết rất dài...</p>
        <!-- Giả lập nội dung dài -->
        <div class="space-y-4">
          <div class="h-32 bg-gray-100 rounded"></div>
          <div class="h-32 bg-gray-100 rounded"></div>
          <div class="h-32 bg-gray-100 rounded"></div>
          <div class="h-32 bg-gray-100 rounded"></div>
          <div class="h-32 bg-gray-100 rounded"></div>
          <div class="h-32 bg-gray-100 rounded"></div>
        </div>
      </div>
    </article>

    <!-- Sticky sidebar -->
    <aside class="w-full lg:w-80">
      <div class="sticky top-24 space-y-6">
        <div class="bg-gray-50 rounded-lg p-6">
          <h3 class="font-bold mb-2">Mục lục</h3>
          <ul class="space-y-2 text-sm text-gray-600">
            <li>Section 1</li>
            <li>Section 2</li>
            <li>Section 3</li>
          </ul>
        </div>
        <div class="bg-blue-50 rounded-lg p-6">
          <h3 class="font-bold mb-2">Bài viết liên quan</h3>
          <ul class="space-y-2 text-sm text-blue-600">
            <li>Bài viết A</li>
            <li>Bài viết B</li>
          </ul>
        </div>
      </div>
    </aside>
  </div>
</div>
Tại sao top-24? Vì thường có fixed header cao ~96px (24 trong scale Tailwind = 6rem). top-24 giúp sidebar dính ở vị trí ngay dưới header, không bị che.

Bài tập 5: Absolute positioned badge trên card

Yêu cầu: Card sản phẩm có badge "Sale" hoặc "New" ở góc trên bên phải, dùng absolute bên trong relative container.

<div class="grid grid-cols-1 md:grid-cols-3 gap-6 p-6">
  <!-- Card 1 — badge "New" -->
  <div class="relative bg-white rounded-xl shadow-md overflow-hidden group">
    <span class="absolute top-3 right-3 bg-green-500 text-white text-xs font-bold px-2 py-1 rounded-full z-10">
      New
    </span>
    <div class="h-48 bg-gradient-to-br from-blue-400 to-purple-500"></div>
    <div class="p-4">
      <h3 class="font-bold">Sản phẩm A</h3>
      <p class="text-gray-600 text-sm">Mô tả ngắn gọn</p>
    </div>
  </div>

  <!-- Card 2 — badge "Sale" -->
  <div class="relative bg-white rounded-xl shadow-md overflow-hidden">
    <span class="absolute top-3 right-3 bg-red-500 text-white text-xs font-bold px-2 py-1 rounded-full z-10">
      -30%
    </span>
    <div class="h-48 bg-gradient-to-br from-pink-400 to-orange-400"></div>
    <div class="p-4">
      <h3 class="font-bold">Sản phẩm B</h3>
      <p class="text-gray-600 text-sm">Đang giảm giá</p>
    </div>
  </div>

  <!-- Card 3 — double badge -->
  <div class="relative bg-white rounded-xl shadow-md overflow-hidden">
    <div class="absolute top-3 right-3 flex flex-col gap-1 z-10">
      <span class="bg-red-500 text-white text-xs font-bold px-2 py-1 rounded-full">Sale</span>
      <span class="bg-blue-500 text-white text-xs font-bold px-2 py-1 rounded-full">Hot</span>
    </div>
    <div class="h-48 bg-gradient-to-br from-teal-400 to-cyan-500"></div>
    <div class="p-4">
      <h3 class="font-bold">Sản phẩm C</h3>
      <p class="text-gray-600 text-sm">Bán chạy nhất</p>
    </div>
  </div>
</div>
Nguyên tắc vàng:absolute luôn cần cha relative (hoặc absolute/fixed). Nếu không có, element sẽ absolute so với viewport.

3. Container & Container Queries (v4.0 NEW)

Container queries cho phép component responsive dựa trên kích thước của chính nó, không phải viewport.

Container class và directive

ClassCSSGhi chú
@containercontainer-type: inline-sizeKích hoạt container query
@container-normalcontainer-type: normalStyle container (không query size)
@sm:, @md:, @lg:, @xl:Container query variantsĐiều kiện dựa trên width của container gần nhất
@container-size-* (v4.3)Custom container size@container-size-md, @container-size-lg...
<!-- Container query: card thay đổi layout dựa trên width của chính nó -->
<div class="@container border rounded-lg p-4">
  <div class="flex flex-col @md:flex-row gap-4">
    <div class="w-full @md:w-1/3 aspect-square bg-gray-200 rounded"></div>
    <div class="flex-1">
      <h3 class="text-lg @md:text-xl font-bold">Card Title</h3>
      <p class="text-gray-600 @md:mt-2">Card description here.</p>
    </div>
  </div>
</div>

Bài tập 6: Card component thay đổi layout dựa trên width của chính nó

Yêu cầu: Card khi nằm trong container nhỏ (< 320px) hiển thị dạng dọc (image trên, text dưới). Khi container > 400px (@md), hiển thị dạng ngang (image trái, text phải). Khi > 640px (@lg), có thêm badge, tag, và nút CTA.

<div class="grid grid-cols-1 md:grid-cols-2 gap-6 p-6">
  <!-- Column trái: width nhỏ → card dạng dọc -->
  <div>
    <div class="@container">
      <div class="bg-white border rounded-xl overflow-hidden
                  flex flex-col @md:flex-row
                  @lg:shadow-lg @lg:hover:shadow-xl @lg:transition-shadow">
        <!-- Image -->
        <div class="w-full @md:w-2/5 @lg:w-1/3 aspect-video @md:aspect-square bg-gradient-to-br from-violet-400 to-indigo-500 relative">
          <!-- Badge chỉ hiện từ @lg -->
          <span class="hidden @lg:block absolute top-3 left-3 bg-white/90 text-xs font-bold px-2 py-1 rounded-full backdrop-blur-sm">
            Featured
          </span>
        </div>

        <!-- Content -->
        <div class="p-4 @md:p-5 @lg:p-6 flex-1 flex flex-col justify-between">
          <div>
            <!-- Tags chỉ hiện từ @lg -->
            <div class="hidden @lg:flex gap-2 mb-2">
              <span class="text-xs bg-indigo-50 text-indigo-600 px-2 py-0.5 rounded-full">Design</span>
              <span class="text-xs bg-indigo-50 text-indigo-600 px-2 py-0.5 rounded-full">UI/UX</span>
            </div>
            <h3 class="font-bold text-gray-900 @lg:text-lg">Product Design Principles</h3>
            <p class="text-sm text-gray-600 mt-1 @lg:mt-2 line-clamp-2 @lg:line-clamp-3">
              Learn how to design better products with proven principles and methodologies
              that top companies use every day.
            </p>
          </div>
          <!-- CTA button chỉ hiện từ @lg -->
          <button class="hidden @lg:inline-flex mt-3 text-sm font-medium text-indigo-600 hover:text-indigo-700">
            Read more →
          </button>
        </div>
      </div>
    </div>
  </div>

  <!-- Column phải: width lớn hơn → card dạng ngang với full feature -->
  <div>
    <div class="@container">
      <div class="bg-white border rounded-xl overflow-hidden
                  flex flex-col @md:flex-row
                  @lg:shadow-lg @lg:hover:shadow-xl @lg:transition-shadow">
        <!-- Image -->
        <div class="w-full @md:w-2/5 @lg:w-1/3 aspect-video @md:aspect-square bg-gradient-to-br from-amber-400 to-orange-500 relative">
          <span class="hidden @lg:block absolute top-3 left-3 bg-white/90 text-xs font-bold px-2 py-1 rounded-full backdrop-blur-sm">
            Popular
          </span>
        </div>
        <!-- Content -->
        <div class="p-4 @md:p-5 @lg:p-6 flex-1 flex flex-col justify-between">
          <div>
            <div class="hidden @lg:flex gap-2 mb-2">
              <span class="text-xs bg-orange-50 text-orange-600 px-2 py-0.5 rounded-full">Development</span>
              <span class="text-xs bg-orange-50 text-orange-600 px-2 py-0.5 rounded-full">Frontend</span>
            </div>
            <h3 class="font-bold text-gray-900 @lg:text-lg">Modern CSS Techniques</h3>
            <p class="text-sm text-gray-600 mt-1 @lg:mt-2 line-clamp-2 @lg:line-clamp-3">
              Explore modern CSS features including container queries, cascade layers,
              and the latest layout techniques for responsive design.
            </p>
          </div>
          <button class="hidden @lg:inline-flex mt-3 text-sm font-medium text-orange-600 hover:text-orange-700">
            Read more →
          </button>
        </div>
      </div>
    </div>
  </div>
</div>
Câu PV:"Container query khác media query thế nào? Khi nào dùng cái nào?"

"Media query dựa trên viewport width, phù hợp cho page-level layout (sidebar, header, grid columns). Container query dựa trên width của phần tử cha, phù hợp cho component tái sử dụng — cùng một card component nhưng render khác nhau khi nằm trong sidebar hẹp vs main content rộng. Tailwind v4 hỗ trợ cả hai."

@container-size (v4.3 NEW)

<!-- Định nghĩa container với custom size -->
<div class="@container-size-md">
  <!-- Children query dựa trên size này -->
  <div class="@md:grid-cols-2">...</div>
</div>

4. Flexbox

Container properties (cha)

ClassCSS
flex / inline-flexdisplay: flex / display: inline-flex
flex-row / flex-row-reverseflex-direction: row / row-reverse
flex-col / flex-col-reverseflex-direction: column / column-reverse
flex-wrap / flex-wrap-reverse / flex-nowrapflex-wrap
flex-1 / flex-auto / flex-initial / flex-noneflex shorthand
grow / grow-0flex-grow: 1 / flex-grow: 0
shrink / shrink-0flex-shrink: 1 / flex-shrink: 0
basis-* (0..96, auto, full, fractions)flex-basis

Justify & Align

ClassCSS
justify-normal, justify-start, justify-end, justify-center, justify-between, justify-around, justify-evenly, justify-stretchjustify-content
justify-items-*justify-items
justify-self-*justify-self
content-normal, content-start, content-center, content-end, content-between, content-around, content-evenly, content-baseline, content-stretchalign-content
items-start, items-end, items-center, items-baseline, items-stretchalign-items
self-auto, self-start, self-end, self-center, self-stretch, self-baselinealign-self

Order & Gap

ClassCSS
order-* (1..12, first, last, none)order
gap-* (0..96, px, fractions)gap
gap-x-*, gap-y-*row-gap, column-gap

Bài tập 7: Centered card (cả ngang và dọc)

Yêu cầu: Canh giữa một card cả chiều ngang và chiều dọc trong viewport.

<div class="min-h-screen flex items-center justify-center bg-gray-100 p-6">
  <div class="bg-white rounded-2xl shadow-xl p-8 max-w-md w-full text-center">
    <div class="w-16 h-16 bg-blue-100 rounded-full flex items-center justify-center mx-auto mb-4">
      <svg class="w-8 h-8 text-blue-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
        <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
              d="M5 13l4 4L19 7"/>
      </svg>
    </div>
    <h2 class="text-2xl font-bold text-gray-900 mb-2">Thành công!</h2>
    <p class="text-gray-600 mb-6">Tài khoản của bạn đã được tạo. Vui lòng kiểm tra email để xác nhận.</p>
    <button class="w-full bg-blue-600 text-white py-2.5 rounded-lg hover:bg-blue-700 transition-colors font-medium">
      Đi đến Dashboard
    </button>
  </div>
</div>
Công thức căn giữa hoàn hảo:flex items-center justify-center trên container + min-h-screen để có full viewport height.

Bài tập 8: Holy Grail layout với flexbox

Yêu cầu: Layout kinh điển: header + 3 cột (nav trái, main giữa, aside phải) + footer. Cột giữa co giãn, 2 cột bên fixed width.

<div class="min-h-screen flex flex-col">
  <!-- Header -->
  <header class="bg-gray-900 text-white px-6 py-4 flex items-center justify-between">
    <h1 class="text-xl font-bold">Holy Grail</h1>
    <nav class="flex gap-4 text-sm">
      <a href="#" class="hover:text-gray-300">Home</a>
      <a href="#" class="hover:text-gray-300">About</a>
    </nav>
  </header>

  <!-- Body: 3 cột -->
  <div class="flex flex-1">
    <!-- Left nav -->
    <nav class="w-64 bg-gray-100 p-6 flex-shrink-0">
      <h3 class="font-bold mb-4">Navigation</h3>
      <ul class="space-y-2">
        <li>Link 1</li>
        <li>Link 2</li>
        <li>Link 3</li>
      </ul>
    </nav>

    <!-- Main content — flex-1 chiếm hết chỗ còn lại -->
    <main class="flex-1 p-6 min-w-0">
      <h2 class="text-2xl font-bold mb-4">Main Content</h2>
      <p class="text-gray-600">Nội dung chính ở đây. Cột này co giãn theo không gian còn lại.</p>
    </main>

    <!-- Right aside -->
    <aside class="w-72 bg-gray-50 p-6 flex-shrink-0">
      <h3 class="font-bold mb-4">Sidebar</h3>
      <p class="text-sm text-gray-600">Thông tin phụ.</p>
    </aside>
  </div>

  <!-- Footer -->
  <footer class="bg-gray-900 text-gray-400 px-6 py-4 text-center text-sm">
    &copy; 2026 Holy Grail Layout. Built with Tailwind CSS v4.
  </footer>
</div>
Công thức flex Holy Grail: Cha flex flex-col min-h-screen, thân flex flex-1, main content flex-1, side columns w-{value} flex-shrink-0. min-w-0 trên main để tránh overflow.

Bài tập 9: Responsive card grid với flex-wrap

Yêu cầu: Grid card dùng flexbox. Card tự xuống dòng khi không đủ chỗ. Mỗi card có min-width, không bóp nhỏ quá.

<div class="flex flex-wrap gap-6 p-6">
  <!-- Card 1 -->
  <div class="flex-1 min-w-[280px] max-w-sm bg-white rounded-xl shadow-md overflow-hidden">
    <div class="h-40 bg-gradient-to-br from-emerald-400 to-teal-500"></div>
    <div class="p-4">
      <h3 class="font-bold">Card 1</h3>
      <p class="text-gray-600 text-sm">Flex item với min-width 280px.</p>
    </div>
  </div>

  <!-- Card 2 -->
  <div class="flex-1 min-w-[280px] max-w-sm bg-white rounded-xl shadow-md overflow-hidden">
    <div class="h-40 bg-gradient-to-br from-rose-400 to-pink-500"></div>
    <div class="p-4">
      <h3 class="font-bold">Card 2</h3>
      <p class="text-gray-600 text-sm">Tự wrap khi không đủ chỗ.</p>
    </div>
  </div>

  <!-- Card 3 -->
  <div class="flex-1 min-w-[280px] max-w-sm bg-white rounded-xl shadow-md overflow-hidden">
    <div class="h-40 bg-gradient-to-br from-cyan-400 to-blue-500"></div>
    <div class="p-4">
      <h3 class="font-bold">Card 3</h3>
      <p class="text-gray-600 text-sm">Không cần media query.</p>
    </div>
  </div>

  <!-- Card 4 -->
  <div class="flex-1 min-w-[280px] max-w-sm bg-white rounded-xl shadow-md overflow-hidden">
    <div class="h-40 bg-gradient-to-br from-violet-400 to-purple-500"></div>
    <div class="p-4">
      <h3 class="font-bold">Card 4</h3>
      <p class="text-gray-600 text-sm">Tự động responsive.</p>
    </div>
  </div>

  <!-- Card 5 -->
  <div class="flex-1 min-w-[280px] max-w-sm bg-white rounded-xl shadow-md overflow-hidden">
    <div class="h-40 bg-gradient-to-br from-amber-400 to-orange-500"></div>
    <div class="p-4">
      <h3 class="font-bold">Card 5</h3>
      <p class="text-gray-600 text-sm">Flex-wrap + min-width = grid không cần breakpoint.</p>
    </div>
  </div>
</div>
Pattern này gọi là "flex-wrap grid":flex-1 min-w-[280px] — không cần media query, card tự động responsive. Mỗi card rộng ít nhất 280px, co giãn, tự xuống dòng.

Yêu cầu: Navbar: logo bên trái, nhóm link bên phải, căn đều 2 đầu.

<nav class="flex items-center justify-between px-8 py-4 bg-white border-b">
  <!-- Logo area — bên trái -->
  <div class="flex items-center gap-3">
    <div class="w-8 h-8 bg-blue-600 rounded-lg"></div>
    <span class="font-bold text-lg">Company</span>
  </div>

  <!-- Links — bên phải, grouped -->
  <div class="flex items-center gap-6">
    <a href="#" class="text-gray-600 hover:text-gray-900 text-sm font-medium">Products</a>
    <a href="#" class="text-gray-600 hover:text-gray-900 text-sm font-medium">Pricing</a>
    <a href="#" class="text-gray-600 hover:text-gray-900 text-sm font-medium">Docs</a>
    <button class="bg-gray-900 text-white px-4 py-2 rounded-lg text-sm font-medium hover:bg-gray-800">
      Sign In
    </button>
  </div>
</nav>
Pattern cực phổ biến:flex items-center justify-between — logo trái, nav phải. Đây là navbar pattern bạn sẽ viết hàng trăm lần.

5. Grid

Grid container

ClassCSS
grid / inline-griddisplay: grid
grid-cols-* (1..12, none, subgrid)grid-template-columns
grid-rows-* (1..6, none, subgrid)grid-template-rows
grid-flow-row / grid-flow-col / grid-flow-dense / grid-flow-row-dense / grid-flow-col-densegrid-auto-flow
auto-cols-auto / auto-cols-min / auto-cols-max / auto-cols-frgrid-auto-columns
auto-rows-auto / auto-rows-min / auto-rows-max / auto-rows-frgrid-auto-rows

Grid item (span)

ClassCSS
col-span-* (1..12, full)grid-column: span N
col-start-* / col-end-* (1..13, auto)grid-column-start / end
row-span-* (1..6, full)grid-row: span N
row-start-* / row-end-* (1..7, auto)grid-row-start / end

Grid alignment

ClassCSS
justify-items-start / end / center / stretchjustify-items
justify-self-auto / start / end / center / stretchjustify-self
place-content-*shorthand align-content + justify-content
place-items-*shorthand align-items + justify-items
place-self-*shorthand align-self + justify-self

Ví dụ cơ bản

<!-- Grid 3 cột đều -->
<div class="grid grid-cols-3 gap-4">
  <div class="bg-blue-200 p-4">1</div>
  <div class="bg-blue-200 p-4">2</div>
  <div class="bg-blue-200 p-4">3</div>
</div>

<!-- Span columns -->
<div class="grid grid-cols-4 gap-4">
  <div class="col-span-2 bg-green-200 p-4">Span 2</div>
  <div class="bg-green-200 p-4">1</div>
  <div class="bg-green-200 p-4">1</div>
</div>

<!-- Grid flow dense — fill holes -->
<div class="grid grid-cols-3 grid-flow-dense gap-4">
  <div class="col-span-2 bg-purple-200 p-4">Span 2</div>
  <div class="bg-purple-200 p-4">3</div>
  <div class="bg-purple-200 p-4">4</div>
  <div class="bg-purple-200 p-4">5</div>
</div>

<!-- Subgrid (dùng với cha grid) -->
<div class="grid grid-cols-3 gap-4">
  <div class="grid grid-cols-subgrid col-span-3 gap-4">
    <div class="bg-yellow-200 p-4">Sub 1</div>
    <div class="bg-yellow-200 p-4">Sub 2</div>
    <div class="bg-yellow-200 p-4">Sub 3</div>
  </div>
</div>

Bài tập 11: 12-column grid system

Yêu cầu: Tạo layout 12 cột, các phần tử span với độ rộng khác nhau.

<div class="p-6 space-y-6">
  <h2 class="text-xl font-bold mb-4">12-Column Grid System</h2>

  <!-- Row 1: 3 cột đều nhau (4+4+4) -->
  <div class="grid grid-cols-12 gap-4">
    <div class="col-span-4 bg-blue-100 rounded-lg p-4 text-center font-medium text-blue-700">
      4 cols
    </div>
    <div class="col-span-4 bg-blue-100 rounded-lg p-4 text-center font-medium text-blue-700">
      4 cols
    </div>
    <div class="col-span-4 bg-blue-100 rounded-lg p-4 text-center font-medium text-blue-700">
      4 cols
    </div>
  </div>

  <!-- Row 2: 8+4 -->
  <div class="grid grid-cols-12 gap-4">
    <div class="col-span-8 bg-green-100 rounded-lg p-4 text-center font-medium text-green-700">
      8 cols — main content
    </div>
    <div class="col-span-4 bg-green-50 rounded-lg p-4 text-center font-medium text-green-600">
      4 cols — sidebar
    </div>
  </div>

  <!-- Row 3: 3+6+3 -->
  <div class="grid grid-cols-12 gap-4">
    <div class="col-span-3 bg-purple-100 rounded-lg p-4 text-center font-medium text-purple-700">
      3 cols
    </div>
    <div class="col-span-6 bg-purple-100 rounded-lg p-4 text-center font-medium text-purple-700">
      6 cols
    </div>
    <div class="col-span-3 bg-purple-100 rounded-lg p-4 text-center font-medium text-purple-700">
      3 cols
    </div>
  </div>

  <!-- Row 4: 2+2+2+2+2+2 -->
  <div class="grid grid-cols-12 gap-4">
    <div class="col-span-2 bg-orange-100 rounded-lg p-4 text-center font-medium text-orange-700 text-sm">2</div>
    <div class="col-span-2 bg-orange-100 rounded-lg p-4 text-center font-medium text-orange-700 text-sm">2</div>
    <div class="col-span-2 bg-orange-100 rounded-lg p-4 text-center font-medium text-orange-700 text-sm">2</div>
    <div class="col-span-2 bg-orange-100 rounded-lg p-4 text-center font-medium text-orange-700 text-sm">2</div>
    <div class="col-span-2 bg-orange-100 rounded-lg p-4 text-center font-medium text-orange-700 text-sm">2</div>
    <div class="col-span-2 bg-orange-100 rounded-lg p-4 text-center font-medium text-orange-700 text-sm">2</div>
  </div>
</div>

Yêu cầu: Gallery ảnh responsive dùng grid, thay đổi số cột theo breakpoint.

<div class="p-6">
  <h2 class="text-xl font-bold mb-4">Responsive Image Gallery</h2>
  <div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4">
    <!-- Item 1 -->
    <div class="group relative aspect-square rounded-xl overflow-hidden bg-gray-200">
      <div class="absolute inset-0 bg-gradient-to-br from-indigo-400 to-blue-500
                  flex items-center justify-center text-white text-4xl font-bold">
        1
      </div>
      <div class="absolute inset-0 bg-black/40 opacity-0 group-hover:opacity-100
                  transition-opacity flex items-center justify-center">
        <span class="text-white font-medium">View Image</span>
      </div>
    </div>
    <!-- Item 2 -->
    <div class="group relative aspect-square rounded-xl overflow-hidden bg-gray-200">
      <div class="absolute inset-0 bg-gradient-to-br from-rose-400 to-pink-500
                  flex items-center justify-center text-white text-4xl font-bold">
        2
      </div>
      <div class="absolute inset-0 bg-black/40 opacity-0 group-hover:opacity-100
                  transition-opacity flex items-center justify-center">
        <span class="text-white font-medium">View Image</span>
      </div>
    </div>
    <!-- Item 3 -->
    <div class="group relative aspect-square rounded-xl overflow-hidden bg-gray-200">
      <div class="absolute inset-0 bg-gradient-to-br from-emerald-400 to-teal-500
                  flex items-center justify-center text-white text-4xl font-bold">
        3
      </div>
      <div class="absolute inset-0 bg-black/40 opacity-0 group-hover:opacity-100
                  transition-opacity flex items-center justify-center">
        <span class="text-white font-medium">View Image</span>
      </div>
    </div>
    <!-- Item 4 -->
    <div class="group relative aspect-square rounded-xl overflow-hidden bg-gray-200">
      <div class="absolute inset-0 bg-gradient-to-br from-amber-400 to-orange-500
                  flex items-center justify-center text-white text-4xl font-bold">
        4
      </div>
      <div class="absolute inset-0 bg-black/40 opacity-0 group-hover:opacity-100
                  transition-opacity flex items-center justify-center">
        <span class="text-white font-medium">View Image</span>
      </div>
    </div>
    <!-- Item 5 -->
    <div class="group relative aspect-square rounded-xl overflow-hidden bg-gray-200">
      <div class="absolute inset-0 bg-gradient-to-br from-violet-400 to-purple-500
                  flex items-center justify-center text-white text-4xl font-bold">
        5
      </div>
      <div class="absolute inset-0 bg-black/40 opacity-0 group-hover:opacity-100
                  transition-opacity flex items-center justify-center">
        <span class="text-white font-medium">View Image</span>
      </div>
    </div>
    <!-- Item 6 -->
    <div class="group relative aspect-square rounded-xl overflow-hidden bg-gray-200">
      <div class="absolute inset-0 bg-gradient-to-br from-cyan-400 to-sky-500
                  flex items-center justify-center text-white text-4xl font-bold">
        6
      </div>
      <div class="absolute inset-0 bg-black/40 opacity-0 group-hover:opacity-100
                  transition-opacity flex items-center justify-center">
        <span class="text-white font-medium">View Image</span>
      </div>
    </div>
  </div>
</div>
Mobile-first grid pattern:grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 — bắt đầu từ 1 cột (mobile), tăng dần. Ghi nhớ: trong Tailwind, breakpoint là min-width — class không prefix = mobile, sm: = >= 640px, lg: = >= 1024px.

Bài tập 13: Dashboard layout với sidebar + header + main + widgets

Yêu cầu: Dashboard admin: sidebar trái cố định, header top, main content với grid widgets.

<div class="min-h-screen flex">
  <!-- Sidebar — cố định bên trái -->
  <aside class="w-64 bg-gray-900 text-white flex-shrink-0 hidden lg:block">
    <div class="p-6">
      <h2 class="text-lg font-bold mb-8">Admin Panel</h2>
      <nav class="space-y-2">
        <a href="#" class="flex items-center gap-3 px-3 py-2 rounded-lg bg-gray-800 text-white">
          <span class="w-5 h-5 bg-blue-400 rounded"></span> Dashboard
        </a>
        <a href="#" class="flex items-center gap-3 px-3 py-2 rounded-lg text-gray-400 hover:text-white hover:bg-gray-800 transition-colors">
          <span class="w-5 h-5 bg-gray-600 rounded"></span> Users
        </a>
        <a href="#" class="flex items-center gap-3 px-3 py-2 rounded-lg text-gray-400 hover:text-white hover:bg-gray-800 transition-colors">
          <span class="w-5 h-5 bg-gray-600 rounded"></span> Products
        </a>
        <a href="#" class="flex items-center gap-3 px-3 py-2 rounded-lg text-gray-400 hover:text-white hover:bg-gray-800 transition-colors">
          <span class="w-5 h-5 bg-gray-600 rounded"></span> Settings
        </a>
      </nav>
    </div>
  </aside>

  <!-- Main area -->
  <div class="flex-1 min-w-0 bg-gray-50">
    <!-- Header -->
    <header class="bg-white border-b px-6 py-4 flex items-center justify-between">
      <h1 class="text-xl font-bold text-gray-900">Dashboard</h1>
      <div class="flex items-center gap-4">
        <span class="text-sm text-gray-600">Admin User</span>
        <div class="w-8 h-8 bg-gray-300 rounded-full"></div>
      </div>
    </header>

    <!-- Content grid -->
    <main class="p-6">
      <!-- Stats cards -->
      <div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4 mb-6">
        <div class="bg-white rounded-xl p-5 shadow-sm">
          <p class="text-sm text-gray-500 mb-1">Total Users</p>
          <p class="text-2xl font-bold text-gray-900">12,543</p>
          <p class="text-xs text-green-600 mt-1">+12.5% from last month</p>
        </div>
        <div class="bg-white rounded-xl p-5 shadow-sm">
          <p class="text-sm text-gray-500 mb-1">Revenue</p>
          <p class="text-2xl font-bold text-gray-900">$45,200</p>
          <p class="text-xs text-green-600 mt-1">+8.2% from last month</p>
        </div>
        <div class="bg-white rounded-xl p-5 shadow-sm">
          <p class="text-sm text-gray-500 mb-1">Active Now</p>
          <p class="text-2xl font-bold text-gray-900">342</p>
          <p class="text-xs text-red-600 mt-1">-3.1% from last hour</p>
        </div>
        <div class="bg-white rounded-xl p-5 shadow-sm">
          <p class="text-sm text-gray-500 mb-1">Conversion</p>
          <p class="text-2xl font-bold text-gray-900">3.24%</p>
          <p class="text-xs text-green-600 mt-1">+0.4% from last week</p>
        </div>
      </div>

      <!-- Charts & tables area -->
      <div class="grid grid-cols-1 lg:grid-cols-3 gap-4">
        <!-- Main chart — span 2 -->
        <div class="lg:col-span-2 bg-white rounded-xl p-5 shadow-sm">
          <h3 class="font-bold text-gray-900 mb-4">Revenue Overview</h3>
          <div class="h-64 bg-gray-100 rounded flex items-center justify-center text-gray-400">
            Chart Area (span 2 columns)
          </div>
        </div>
        <!-- Side widget -->
        <div class="bg-white rounded-xl p-5 shadow-sm">
          <h3 class="font-bold text-gray-900 mb-4">Recent Activity</h3>
          <div class="space-y-3">
            <div class="flex gap-3 text-sm">
              <div class="w-2 h-2 bg-blue-500 rounded-full mt-1.5 flex-shrink-0"></div>
              <p class="text-gray-600">New user registered</p>
            </div>
            <div class="flex gap-3 text-sm">
              <div class="w-2 h-2 bg-green-500 rounded-full mt-1.5 flex-shrink-0"></div>
              <p class="text-gray-600">Order #1234 completed</p>
            </div>
            <div class="flex gap-3 text-sm">
              <div class="w-2 h-2 bg-orange-500 rounded-full mt-1.5 flex-shrink-0"></div>
              <p class="text-gray-600">Payment pending</p>
            </div>
          </div>
        </div>
      </div>
    </main>
  </div>
</div>
Dashboard pattern: Flex sidebar + flex-1 main. Stats cards dùng grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 responsive. Charts dùng lg:col-span-2 cho element chiếm 2/3 grid.

6. Spacing

Padding

ClassCSS
p-* (0..96, px)padding 4 phía
px-*, py-*padding-left + right, padding-top + bottom
pt-*, pr-*, pb-*, pl-*padding-top / right / bottom / left

Margin

ClassCSS
m-* (0..96, px, auto)margin 4 phía
mx-*, my-*margin-left + right, top + bottom
mt-*, mr-*, mb-*, ml-*margin-top / right / bottom / left

Logical Properties (v4.2 NEW)

Hỗ trợ layout đa ngôn ngữ (LTR/RTL) — thay vì physical directions:

ClassCSSGhi chú
pbs-*, mbs-*padding-block-start, margin-block-start"Top" logic
pbe-*, mbe-*padding-block-end, margin-block-end"Bottom" logic
pis-*, mis-*padding-inline-start, margin-inline-start"Left" logic (start of text direction)
pie-*, mie-*padding-inline-end, margin-inline-end"Right" logic (end of text direction)
inline-*Logical inline margin/paddingShorthand
block-*Logical block margin/paddingShorthand
<!-- Logical properties: tự động đúng cho mọi ngôn ngữ -->
<div dir="ltr" class="bg-gray-100 p-4 rounded mb-4">
  <p class="mis-4 text-gray-700">LTR: mis (margin-inline-start) = margin left</p>
</div>
<div dir="rtl" class="bg-gray-100 p-4 rounded">
  <p class="mis-4 text-gray-700">RTL: mis (margin-inline-start) = margin right</p>
</div>

Space Between

ClassCSS
space-x-* (> 0)margin-left cho mỗi child trừ child đầu
space-y-* (> 0)margin-top cho mỗi child trừ child đầu
space-x-reverse, space-y-reverseĐảo chiều space
<!-- Dùng space-y cho vertical rhythm -->
<div class="space-y-4">
  <p class="bg-blue-100 p-3 rounded">Paragraph 1</p>
  <p class="bg-blue-100 p-3 rounded">Paragraph 2</p>
  <p class="bg-blue-100 p-3 rounded">Paragraph 3</p>
</div>

<!-- Dùng gap thay thế (khuyến nghị dùng flex/grid) -->
<div class="flex gap-4">
  <button class="bg-gray-200 px-4 py-2 rounded">Button 1</button>
  <button class="bg-gray-200 px-4 py-2 rounded">Button 2</button>
</div>

Negative Margins & Auto Margins

<!-- Auto margin: đẩy element về phía đối diện -->
<div class="flex bg-gray-200 p-2 rounded">
  <span>Left</span>
  <span class="ml-auto bg-blue-200 px-2 rounded">Right (ml-auto)</span>
</div>

<!-- Negative margin: kéo element ra ngoài container -->
<div class="bg-gray-100 p-8">
  <div class="bg-blue-500 text-white p-4 -mx-4 rounded">
    Full-width inside padded container (-mx-4)
  </div>
</div>
space-y-* vs gap-*:space-y-* thêm margin-top cho child (chỉ hoạt động khi children là block/inline). gap-* dùng với flex/grid container. Khuyến nghị: luôn dùng gap cho flex/grid, space-y-* chỉ khi children không phải flex/grid item.

Bài tập 14: Spacing system cho blog article (consistent vertical rhythm)

Yêu cầu: Bài viết blog với khoảng cách dọc nhất quán giữa các phần tử: heading, paragraph, image, blockquote, list.

<article class="max-w-2xl mx-auto px-6 py-12 space-y-8">
  <!-- Title section -->
  <header class="space-y-3">
    <div class="flex gap-2">
      <span class="text-xs bg-blue-50 text-blue-600 px-2 py-1 rounded-full">Technology</span>
      <span class="text-xs bg-purple-50 text-purple-600 px-2 py-1 rounded-full">CSS</span>
    </div>
    <h1 class="text-3xl font-bold text-gray-900 leading-tight">
      Building Consistent Spacing Systems with Tailwind CSS
    </h1>
    <div class="flex items-center gap-3 text-sm text-gray-500">
      <div class="w-8 h-8 bg-gray-300 rounded-full"></div>
      <span>John Doe</span>
      <span>·</span>
      <span>July 8, 2026</span>
    </div>
  </header>

  <!-- Intro paragraph -->
  <p class="text-lg text-gray-700 leading-relaxed">
    A well-designed spacing system is the invisible foundation of every great UI.
    In this article, we'll explore how Tailwind CSS v4 helps you maintain consistent
    vertical rhythm across your entire layout.
  </p>

  <!-- Image placeholder -->
  <figure class="space-y-2">
    <div class="aspect-video bg-gradient-to-br from-slate-400 to-slate-600 rounded-xl flex items-center justify-center text-white text-lg">
      Featured Image
    </div>
    <figcaption class="text-sm text-gray-500 text-center italic">
      Figure 1: Consistent spacing makes content more readable.
    </figcaption>
  </figure>

  <!-- Section heading + paragraph -->
  <section class="space-y-4">
    <h2 class="text-2xl font-bold text-gray-900">Why Spacing Matters</h2>
    <p class="text-gray-700 leading-relaxed">
      Vertical rhythm creates a predictable reading experience. When headings,
      paragraphs, and images all follow the same spacing scale, users can scan
      content faster and focus on what matters.
    </p>
    <p class="text-gray-700 leading-relaxed">
      Tailwind's spacing scale (based on 4px increments) ensures every element
      aligns to the same baseline grid, eliminating uneven gaps.
    </p>
  </section>

  <!-- Blockquote -->
  <blockquote class="border-l-4 border-blue-500 pl-4 py-2 bg-blue-50 rounded-r-lg">
    <p class="text-gray-700 italic">
      "Design is not just what it looks like and feels like. Design is how it works."
    </p>
    <footer class="text-sm text-gray-500 mt-2">— Steve Jobs</footer>
  </blockquote>

  <!-- Bullet list -->
  <section class="space-y-3">
    <h3 class="text-xl font-bold text-gray-900">Key Principles</h3>
    <ul class="space-y-2 list-disc list-inside text-gray-700">
      <li>Use multiples of 4px (Tailwind's default scale)</li>
      <li>Maintain consistent spacing between same-level elements</li>
      <li>Increase spacing before new sections</li>
      <li>Keep line-height proportional to font-size</li>
    </ul>
  </section>

  <!-- Conclusion -->
  <hr class="border-gray-200">
  <p class="text-gray-700 leading-relaxed">
    A consistent spacing system is one of the easiest ways to make your designs
    look polished and professional. Tailwind CSS v4 makes it effortless.
  </p>
</article>
Vertical rhythm pattern: Dùng space-y-8 trên container chính (khoảng cách lớn giữa section), space-y-4 cho nội dung trong section (paragraphs, heading nhỏ), space-y-2 cho list/detail. Cấp bậc spacing phản ánh cấp bậc nội dung.

Bài tập 15: Card với internal spacing chuẩn (padding + gap)

Yêu cầu: Card sản phẩm có ảnh, tiêu đề, mô tả, giá, và nút. Internal spacing rõ ràng và nhất quán.

<div class="max-w-sm mx-auto bg-white rounded-2xl shadow-lg overflow-hidden">
  <!-- Image -->
  <div class="aspect-video bg-gradient-to-br from-blue-400 to-indigo-600 relative">
    <span class="absolute top-3 left-3 bg-white/90 text-xs font-bold px-2 py-1 rounded-full backdrop-blur-sm">
      New Arrival
    </span>
  </div>

  <!-- Content — padding + flex column with gap -->
  <div class="p-5 flex flex-col gap-4">
    <!-- Title + category -->
    <div>
      <p class="text-xs font-medium text-indigo-600 uppercase tracking-wide mb-1">Electronics</p>
      <h3 class="text-lg font-bold text-gray-900">Wireless Headphones Pro</h3>
    </div>

    <!-- Description -->
    <p class="text-sm text-gray-600 leading-relaxed">
      Premium noise-canceling wireless headphones with 30-hour battery life
      and spatial audio support.
    </p>

    <!-- Features (dùng gap thay vì space-y) -->
    <div class="flex gap-3">
      <span class="text-xs bg-gray-100 text-gray-700 px-2 py-1 rounded-full">ANC</span>
      <span class="text-xs bg-gray-100 text-gray-700 px-2 py-1 rounded-full">30h Battery</span>
      <span class="text-xs bg-gray-100 text-gray-700 px-2 py-1 rounded-full">Bluetooth 5.3</span>
    </div>

    <!-- Price + CTA -->
    <div class="flex items-center justify-between pt-2 border-t border-gray-100">
      <div>
        <span class="text-2xl font-bold text-gray-900">$299</span>
        <span class="text-sm text-gray-400 line-through ml-2">$399</span>
      </div>
      <button class="bg-indigo-600 text-white px-4 py-2 rounded-lg text-sm font-medium
                     hover:bg-indigo-700 transition-colors">
        Add to Cart
      </button>
    </div>
  </div>
</div>
Internal spacing pattern: Container p-5 cho padding đều, bên trong flex flex-col gap-4 cho khoảng cách giữa các phần. pt-2 border-t cho separator giữa mô tả và giá — phân tách visual rõ ràng.

7. Sizing

Width & Height

ClassCSSGhi chú
w-* (0..96, auto, full, screen, min, max, fit, fractions)width
h-* (0..96, auto, full, screen, min, max, fit, fractions)height
min-w-*, max-w-*min-width, max-width
min-h-*, max-h-*min-height, max-height
size-*width + height cùng lúc

Viewport Units

ClassCSSGhi chú
w-screen, h-screenwidth: 100vw, height: 100vh
min-h-screenmin-height: 100vhFull height tối thiểu
h-dvhheight: 100dvhDynamic viewport height
h-svhheight: 100svhSmall viewport height
h-lvhheight: 100lvhLarge viewport height
dvh vs svh vs lvh:dvh = dynamic viewport height — tự điều chỉnh khi mobile browser bar show/hide. svh = small (bar visible), lvh = large (bar hidden). Dùng dvh cho full-screen layout mobile để tránh bị che bởi browser UI.

Logical Sizing (v4.2 NEW)

ClassCSS
inline-size-*, block-size-*inline-size, block-size
min-inline-size-*, min-block-size-*min-inline-size, min-block-size
max-inline-size-*, max-block-size-*max-inline-size, max-block-size

Bài tập 16: Full-screen hero section với min-h-screen

Yêu cầu: Hero section full màn hình, nội dung căn giữa, có background gradient, CTA button.

<section class="min-h-screen flex items-center justify-center bg-gradient-to-br from-slate-900 via-purple-900 to-slate-900 relative overflow-hidden">
  <!-- Decorative background elements -->
  <div class="absolute top-20 left-20 w-72 h-72 bg-purple-500/20 rounded-full blur-3xl"></div>
  <div class="absolute bottom-20 right-20 w-96 h-96 bg-blue-500/10 rounded-full blur-3xl"></div>

  <!-- Content -->
  <div class="relative z-10 max-w-3xl mx-auto px-6 text-center">
    <span class="inline-block text-sm font-medium text-purple-300 bg-white/10 px-3 py-1 rounded-full mb-6 backdrop-blur-sm">
      Tailwind CSS v4 — Now with Oxide Engine
    </span>
    <h1 class="text-4xl sm:text-5xl lg:text-6xl font-bold text-white leading-tight mb-6">
      Build Faster with
      <span class="bg-gradient-to-r from-purple-400 to-pink-400 bg-clip-text text-transparent">
        Utility-First CSS
      </span>
    </h1>
    <p class="text-lg text-gray-300 max-w-xl mx-auto mb-8 leading-relaxed">
      Tailwind CSS v4 is rebuilt from the ground up with the Oxide Engine in Rust,
      delivering 5x faster builds and an all-new CSS-first configuration.
    </p>
    <div class="flex flex-col sm:flex-row items-center justify-center gap-4">
      <button class="w-full sm:w-auto bg-white text-slate-900 px-8 py-3 rounded-xl font-semibold hover:bg-gray-100 transition-colors">
        Get Started Free
      </button>
      <button class="w-full sm:w-auto bg-white/10 text-white px-8 py-3 rounded-xl font-semibold hover:bg-white/20 transition-colors backdrop-blur-sm">
        View Docs
      </button>
    </div>
  </div>

  <!-- Scroll indicator -->
  <div class="absolute bottom-8 left-1/2 -translate-x-1/2 animate-bounce">
    <div class="w-6 h-10 border-2 border-white/30 rounded-full flex items-start justify-center p-1.5">
      <div class="w-1.5 h-1.5 bg-white/60 rounded-full"></div>
    </div>
  </div>
</section>
Hero pattern phổ biến:min-h-screen flex items-center justify-center — đảm bảo luôn full viewport. Background gradient + blur decorative circles tạo chiều sâu. max-w-3xl mx-auto giới hạn text width cho readability.

Bài tập 17: Image giữ aspect ratio + max-width

Yêu cầu: Container ảnh responsive — ảnh không bị méo, không tràn container, giữ đúng tỉ lệ.

<div class="max-w-2xl mx-auto p-6 space-y-8">
  <h2 class="text-xl font-bold">Responsive Image Patterns</h2>

  <!-- Pattern 1: Fixed aspect ratio với object-fit -->
  <div>
    <h3 class="font-medium mb-2">Fixed Aspect Ratio (16:9)</h3>
    <div class="aspect-video bg-gray-200 rounded-xl overflow-hidden">
      <div class="w-full h-full bg-gradient-to-br from-blue-400 to-purple-500
                  flex items-center justify-center text-white text-2xl font-bold">
        16:9 Image
      </div>
    </div>
  </div>

  <!-- Pattern 2: Square (1:1) -->
  <div>
    <h3 class="font-medium mb-2">Square (1:1)</h3>
    <div class="grid grid-cols-3 gap-4">
      <div class="aspect-square bg-gray-200 rounded-lg overflow-hidden">
        <div class="w-full h-full bg-gradient-to-br from-emerald-400 to-teal-500
                    flex items-center justify-center text-white font-bold">1:1</div>
      </div>
      <div class="aspect-square bg-gray-200 rounded-lg overflow-hidden">
        <div class="w-full h-full bg-gradient-to-br from-rose-400 to-pink-500
                    flex items-center justify-center text-white font-bold">1:1</div>
      </div>
      <div class="aspect-square bg-gray-200 rounded-lg overflow-hidden">
        <div class="w-full h-full bg-gradient-to-br from-amber-400 to-orange-500
                    flex items-center justify-center text-white font-bold">1:1</div>
      </div>
    </div>
  </div>

  <!-- Pattern 3: 4:3 aspect ratio -->
  <div>
    <h3 class="font-medium mb-2">4:3 Aspect Ratio</h3>
    <div class="aspect-[4/3] max-w-md bg-gray-200 rounded-xl overflow-hidden">
      <div class="w-full h-full bg-gradient-to-br from-indigo-400 to-cyan-500
                  flex items-center justify-center text-white font-bold text-lg">
        4:3
      </div>
    </div>
  </div>

  <!-- Pattern 4: Full width, auto height, max-width constraint -->
  <div>
    <h3 class="font-medium mb-2">Full Width with Max Constraint</h3>
    <div class="w-full max-w-lg bg-gray-200 rounded-xl overflow-hidden">
      <div class="aspect-video bg-gradient-to-br from-violet-400 to-fuchsia-500
                  flex items-center justify-center text-white font-bold">
        w-full + max-w-lg
      </div>
    </div>
  </div>
</div>
Image patterns cần nhớ:
  • aspect-video = 16:9, aspect-square = 1:1, aspect-[4/3] = custom ratio.
  • w-full max-w-lg = responsive full width nhưng không vượt quá max-width.
  • object-cover + object-center cho ảnh thật (thẻ <img>) để crop thay vì méo.

8. Overflow

ClassCSS
overflow-autooverflow: auto — scrollbar khi cần
overflow-hiddenoverflow: hidden — cắt nội dung
overflow-clipoverflow: clip — giống hidden nhưng không tạo scroll container
overflow-visibleoverflow: visible
overflow-scrolloverflow: scroll — luôn có scrollbar
overflow-x-*, overflow-y-*Overflow theo trục
overscroll-auto, overscroll-contain, overscroll-noneoverscroll-behavior

Bài tập 18: Scrollable sidebar với fixed height

Yêu cầu: Sidebar có chiều cao cố định, nội dung bên trong cuộn được.

<div class="flex min-h-screen bg-gray-100">
  <!-- Scrollable sidebar -->
  <aside class="w-64 bg-white border-r flex flex-col">
    <!-- Header sidebar — fixed -->
    <div class="p-4 border-b">
      <h2 class="font-bold text-gray-900">Channels</h2>
    </div>

    <!-- Scrollable content -->
    <nav class="flex-1 overflow-y-auto p-4 space-y-1">
      <!-- 20 channel items — scroll sẽ xuất hiện -->
      <a href="#" class="flex items-center gap-2 px-3 py-2 rounded-lg bg-indigo-50 text-indigo-700 font-medium text-sm">
        <span class="text-lg">#</span> general
      </a>
      <a href="#" class="flex items-center gap-2 px-3 py-2 rounded-lg text-gray-600 hover:bg-gray-50 font-medium text-sm">
        <span class="text-lg">#</span> random
      </a>
      <a href="#" class="flex items-center gap-2 px-3 py-2 rounded-lg text-gray-600 hover:bg-gray-50 font-medium text-sm">
        <span class="text-lg">#</span> announcements
      </a>
      <!-- Thêm nhiều items để tạo scroll -->
      <a href="#" class="flex items-center gap-2 px-3 py-2 rounded-lg text-gray-600 hover:bg-gray-50 font-medium text-sm">
        <span class="text-lg">#</span> design
      </a>
      <a href="#" class="flex items-center gap-2 px-3 py-2 rounded-lg text-gray-600 hover:bg-gray-50 font-medium text-sm">
        <span class="text-lg">#</span> frontend
      </a>
      <a href="#" class="flex items-center gap-2 px-3 py-2 rounded-lg text-gray-600 hover:bg-gray-50 font-medium text-sm">
        <span class="text-lg">#</span> backend
      </a>
      <a href="#" class="flex items-center gap-2 px-3 py-2 rounded-lg text-gray-600 hover:bg-gray-50 font-medium text-sm">
        <span class="text-lg">#</span> devops
      </a>
      <a href="#" class="flex items-center gap-2 px-3 py-2 rounded-lg text-gray-600 hover:bg-gray-50 font-medium text-sm">
        <span class="text-lg">#</span> help
      </a>
      <a href="#" class="flex items-center gap-2 px-3 py-2 rounded-lg text-gray-600 hover:bg-gray-50 font-medium text-sm">
        <span class="text-lg">#</span> jobs
      </a>
      <a href="#" class="flex items-center gap-2 px-3 py-2 rounded-lg text-gray-600 hover:bg-gray-50 font-medium text-sm">
        <span class="text-lg">#</span> projects
      </a>
      <a href="#" class="flex items-center gap-2 px-3 py-2 rounded-lg text-gray-600 hover:bg-gray-50 font-medium text-sm">
        <span class="text-lg">#</span> resources
      </a>
      <a href="#" class="flex items-center gap-2 px-3 py-2 rounded-lg text-gray-600 hover:bg-gray-50 font-medium text-sm">
        <span class="text-lg">#</span> events
      </a>
      <a href="#" class="flex items-center gap-2 px-3 py-2 rounded-lg text-gray-600 hover:bg-gray-50 font-medium text-sm">
        <span class="text-lg">#</span> feedback
      </a>
      <a href="#" class="flex items-center gap-2 px-3 py-2 rounded-lg text-gray-600 hover:bg-gray-50 font-medium text-sm">
        <span class="text-lg">#</span> mentoring
      </a>
      <a href="#" class="flex items-center gap-2 px-3 py-2 rounded-lg text-gray-600 hover:bg-gray-50 font-medium text-sm">
        <span class="text-lg">#</span> open-source
      </a>
    </nav>

    <!-- Footer sidebar — fixed -->
    <div class="p-4 border-t">
      <div class="flex items-center gap-2">
        <div class="w-8 h-8 bg-indigo-500 rounded-full"></div>
        <span class="text-sm font-medium">User Name</span>
      </div>
    </div>
  </aside>

  <!-- Main content -->
  <main class="flex-1 p-6">
    <h1 class="text-2xl font-bold">Main Content Area</h1>
  </main>
</div>
Scrollable sidebar pattern: Cấu trúc flex flex-col với header (fixed), nav giữa flex-1 overflow-y-auto, footer (fixed). flex-1 làm nav chiếm hết chiều cao còn lại, overflow-y-auto chỉ hiện scrollbar khi nội dung vượt quá.

9. Scrollbar Styling (v4.3 NEW)

Tailwind CSS v4.3 thêm built-in scrollbar utilities — không cần plugin riêng nữa.

ClassCSSGhi chú
scrollbar-autoScrollbar mặc định của OS
scrollbar-thinScrollbar mỏng hơn
scrollbar-noneẨn scrollbar nhưng vẫn scroll đượcCực kỳ hữu ích
scrollbar-thumb-*Màu của thumb (phần kéo)scrollbar-thumb-gray-300
scrollbar-track-*Màu của track (rãnh)scrollbar-track-gray-100
scrollbar-gutter-stableDành chỗ cho scrollbar ngay cả khi không scrollTránh layout shift
<!-- Scrollbar mỏng với màu tùy chỉnh -->
<div class="h-48 overflow-y-auto scrollbar-thin scrollbar-thumb-gray-400 scrollbar-track-gray-100 p-4 bg-white rounded-lg">
  <p class="text-gray-700">Nội dung cuộn với scrollbar được style...</p>
  <!-- nhiều content -->
</div>

<!-- Ẩn scrollbar nhưng vẫn scroll -->
<div class="h-48 overflow-y-auto scrollbar-none p-4 bg-white rounded-lg">
  <p class="text-gray-700">Scrollbar bị ẩn nhưng vẫn scroll được bằng touch/swipe/wheel...</p>
</div>

<!-- scrollbar-gutter: tránh layout shift -->
<div class="h-48 overflow-y-auto scrollbar-gutter-stable p-4 bg-white rounded-lg">
  <p>Dành chỗ cho scrollbar ngay cả khi chưa đủ nội dung để scroll → không bị giật layout.</p>
</div>

Bài tập 19: Custom scrollbar cho chat message list

Yêu cầu: Khung chat với danh sách tin nhắn có scrollbar tùy chỉnh — mỏng, màu phù hợp theme, gutter stable.

<div class="max-w-md mx-auto bg-white rounded-2xl shadow-lg overflow-hidden flex flex-col" style="height: 500px;">
  <!-- Chat header -->
  <div class="px-5 py-4 border-b flex items-center gap-3">
    <div class="w-10 h-10 bg-gradient-to-br from-blue-400 to-indigo-500 rounded-full flex items-center justify-center text-white font-bold">
      A
    </div>
    <div>
      <h3 class="font-semibold text-gray-900">Alice Nguyen</h3>
      <p class="text-xs text-green-500">Online</p>
    </div>
  </div>

  <!-- Message list — scrollable với custom scrollbar -->
  <div class="flex-1 overflow-y-auto scrollbar-thin scrollbar-thumb-gray-300
              scrollbar-track-transparent scrollbar-gutter-stable
              hover:scrollbar-thumb-gray-400 transition-colors
              px-5 py-4 space-y-4">
    <!-- Received message -->
    <div class="flex gap-3">
      <div class="w-8 h-8 bg-gray-300 rounded-full flex-shrink-0 mt-1"></div>
      <div class="bg-gray-100 rounded-2xl rounded-tl-sm px-4 py-2.5 max-w-[75%]">
        <p class="text-sm text-gray-800">Chào bạn! Khóa học Tailwind CSS v4 thế nào rồi?</p>
        <span class="text-xs text-gray-400 mt-1 block">10:30 AM</span>
      </div>
    </div>

    <!-- Sent message -->
    <div class="flex gap-3 justify-end">
      <div class="bg-blue-600 text-white rounded-2xl rounded-tr-sm px-4 py-2.5 max-w-[75%]">
        <p class="text-sm">Rất hay! Đang học phần Layout & Spacing. Container queries mới cực kỳ hữu ích.</p>
        <span class="text-xs text-blue-200 mt-1 block">10:31 AM</span>
      </div>
      <div class="w-8 h-8 bg-blue-500 rounded-full flex-shrink-0 mt-1"></div>
    </div>

    <!-- Received message 2 -->
    <div class="flex gap-3">
      <div class="w-8 h-8 bg-gray-300 rounded-full flex-shrink-0 mt-1"></div>
      <div class="bg-gray-100 rounded-2xl rounded-tl-sm px-4 py-2.5 max-w-[75%]">
        <p class="text-sm text-gray-800">Tuyệt! Phần scrollbar mới trong v4.3 cũng rất đáng học. Để mình gửi link docs cho.</p>
        <span class="text-xs text-gray-400 mt-1 block">10:32 AM</span>
      </div>
    </div>

    <!-- Sent message 2 -->
    <div class="flex gap-3 justify-end">
      <div class="bg-blue-600 text-white rounded-2xl rounded-tr-sm px-4 py-2.5 max-w-[75%]">
        <p class="text-sm">Cảm ơn bạn! Để mình xem thử.</p>
        <span class="text-xs text-blue-200 mt-1 block">10:33 AM</span>
      </div>
      <div class="w-8 h-8 bg-blue-500 rounded-full flex-shrink-0 mt-1"></div>
    </div>

    <!-- Tin nhắn dài tạo scroll -->
    <div class="flex justify-center">
      <span class="text-xs text-gray-400 bg-gray-50 px-3 py-1 rounded-full">Hôm nay</span>
    </div>

    <!-- Received message 3 -->
    <div class="flex gap-3">
      <div class="w-8 h-8 bg-gray-300 rounded-full flex-shrink-0 mt-1"></div>
      <div class="bg-gray-100 rounded-2xl rounded-tl-sm px-4 py-2.5 max-w-[75%]">
        <p class="text-sm text-gray-800">À, bài tập trong tài liệu — nhớ làm hết nhé! Mỗi bài đều có pattern thực tế áp dụng được ngay.</p>
        <span class="text-xs text-gray-400 mt-1 block">10:35 AM</span>
      </div>
    </div>

    <!-- Sent message 3 -->
    <div class="flex gap-3 justify-end">
      <div class="bg-blue-600 text-white rounded-2xl rounded-tr-sm px-4 py-2.5 max-w-[75%]">
        <p class="text-sm">Yes sir! Đang làm đến bài tập 19 luôn nè.</p>
        <span class="text-xs text-blue-200 mt-1 block">10:36 AM</span>
      </div>
      <div class="w-8 h-8 bg-blue-500 rounded-full flex-shrink-0 mt-1"></div>
    </div>

    <!-- Received message 4 -->
    <div class="flex gap-3">
      <div class="w-8 h-8 bg-gray-300 rounded-full flex-shrink-0 mt-1"></div>
      <div class="bg-gray-100 rounded-2xl rounded-tl-sm px-4 py-2.5 max-w-[75%]">
        <p class="text-sm text-gray-800">Good job! Học xong phần này là master layout Tailwind rồi. Tiếp theo là Typography & Colors nhé!</p>
        <span class="text-xs text-gray-400 mt-1 block">10:37 AM</span>
      </div>
    </div>
  </div>

  <!-- Input area -->
  <div class="px-5 py-4 border-t flex gap-3">
    <input type="text" placeholder="Nhập tin nhắn..."
           class="flex-1 bg-gray-100 rounded-full px-4 py-2.5 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:bg-white transition-colors">
    <button class="bg-blue-600 text-white w-10 h-10 rounded-full flex items-center justify-center hover:bg-blue-700 transition-colors flex-shrink-0">
      <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
        <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 12h14M12 5l7 7-7 7"/>
      </svg>
    </button>
  </div>
</div>
Chat scrollbar pattern:scrollbar-thin scrollbar-thumb-gray-300 scrollbar-track-transparent — scrollbar trong suốt hòa vào nền, chỉ thấy thumb. hover:scrollbar-thumb-gray-400 làm thumb đậm hơn khi hover để dễ nhìn. scrollbar-gutter-stable tránh layout shift khi scrollbar xuất hiện.

Tổng kết

Bạn đã học qua 9 nhóm utility cho layout và spacing trong Tailwind CSS v4, kèm 19 bài tập thực hành:

  1. Display (Bài tập 1-2): Navigation bar, sidebar toggle
  2. Position (Bài tập 3-5): Fixed header, sticky sidebar, absolute badge
  3. Container Queries (Bài tập 6): Card responsive theo width của chính nó
  4. Flexbox (Bài tập 7-10): Centered card, Holy Grail, flex-wrap grid, navbar
  5. Grid (Bài tập 11-13): 12-column system, responsive gallery, dashboard
  6. Spacing (Bài tập 14-15): Blog vertical rhythm, card internal spacing
  7. Sizing (Bài tập 16-17): Hero section, responsive images
  8. Overflow (Bài tập 18): Scrollable sidebar
  9. Scrollbar (Bài tập 19): Chat message list custom scrollbar
Câu PV tổng kết Layout:"Bạn dùng Tailwind xây layout phức tạp (dashboard, admin panel) như thế nào?"

"Tôi kết hợp flexbox cho page-level layout (sidebar + main content), grid cho content-area layout (stats cards, charts), container queries cho component tái sử dụng (card thay đổi trong các ngữ cảnh khác nhau). Mobile-first responsive: bắt đầu với mobile layout, thêm sm:, md:, lg: để enhance khi màn hình lớn hơn. Pattern hay dùng: flex min-h-screen cho app shell, grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 cho card grid, sticky top-24 cho sidebar trong blog."

Tiếp theo: 2. Typography & Colors — Font, text size, OKLCH colors, text shadow (v4.1), dark mode.

© 2026 .NET Fresher Guide. All rights reserved.

Về Trang Web

Hướng dẫn toàn diện để chuẩn bị phỏng vấn vị trí .NET Fresher với nội dung từ lý thuyết đến thực hành.