Tailwind CSS Core Concepts: Utility Classes and Prefix System

How Utility Classes Work

The core of Tailwind CSS is Utility Classes, where each class corresponds to a specific CSS property. By combining multiple utility classes, you can build complex styles directly in HTML.

Example

HTML
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Utility Class Mechanics</title>
  <script src="https://cdn.tailwindcss.com"></script>
</head>
<body class="min-h-screen bg-gray-100 p-8">
  <div class="bg-white rounded-lg shadow-md p-6 max-w-md mx-auto">
    <h2 class="text-2xl font-bold text-gray-800 mb-4">Utility Class Demo</h2>
    <p class="text-gray-600 leading-relaxed mb-4">
      Each class name corresponds to one CSS property
    </p>
    <button class="bg-blue-500 text-white px-4 py-2 rounded hover:bg-blue-600 transition-colors">
      Click Me
    </button>
  </div>
</body>
</html>
▶ Try it Yourself

What each class does in the code above:

Tailwind Class Corresponding CSS
bg-white background-color: #fff
rounded-lg border-radius: 0.5rem
shadow-md box-shadow: ...
p-6 padding: 1.5rem
text-2xl font-size: 1.5rem
font-bold font-weight: 700

Traditional CSS vs Tailwind The traditional approach requires creating semantic class names (e.g., .card) and defining styles in a CSS file, whereas Tailwind uses atomic utility classes directly, eliminating the need to write and maintain CSS files.

Hover/Focus State Prefixes

Tailwind uses state prefixes to handle interaction states, such as hover:, focus:, active:, etc. The syntax is intuitive and easy to use.

Example

HTML
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>State Prefix Demo</title>
  <script src="https://cdn.tailwindcss.com"></script>
</head>
<body class="min-h-screen bg-gray-50 flex items-center justify-center gap-8">
  <!-- Hover Effect -->
  <button class="bg-blue-500 text-white px-6 py-3 rounded-lg
                 hover:bg-blue-700 hover:shadow-lg hover:scale-105
                 transition-all duration-300">
    Hover Effect
  </button>

  <!-- Focus Effect -->
  <input type="text" placeholder="Click the input to see the effect"
         class="px-4 py-3 border-2 border-gray-300 rounded-lg
                focus:border-blue-500 focus:ring-2 focus:ring-blue-200
                focus:outline-none transition-all">

  <!-- Combined States -->
  <button class="bg-green-500 text-white px-6 py-3 rounded-lg
                 hover:bg-green-600
                 focus:ring-2 focus:ring-green-300
                 active:bg-green-700
                 disabled:opacity-50 disabled:cursor-not-allowed">
    Combined States
  </button>
</body>
</html>
▶ Try it Yourself

Traditional CSS vs Tailwind The traditional approach requires writing pseudo-class selectors like .button:hover and .button:focus, whereas Tailwind simply adds hover: or focus: prefixes to class names.

💡 Tip: Common state prefixes include: hover: (hover), focus: (focus), active: (active), disabled: (disabled), first: (first element), last: (last element)

Responsive Prefixes

Tailwind follows a mobile-first strategy, using responsive prefixes to set styles for different screen sizes: sm:, md:, lg:, xl:, 2xl:.

Example

HTML
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Responsive Prefix Demo</title>
  <script src="https://cdn.tailwindcss.com"></script>
</head>
<body class="min-h-screen bg-gray-100 p-4">
  <div class="max-w-6xl mx-auto">
    <h1 class="text-xl md:text-2xl lg:text-4xl font-bold text-center mb-8">
      Responsive Heading
    </h1>
    
    <!-- Responsive Grid -->
    <div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-4">
      <div class="bg-white p-4 rounded-lg shadow">Card 1</div>
      <div class="bg-white p-4 rounded-lg shadow">Card 2</div>
      <div class="bg-white p-4 rounded-lg shadow">Card 3</div>
      <div class="bg-white p-4 rounded-lg shadow">Card 4</div>
      <div class="bg-white p-4 rounded-lg shadow">Card 5</div>
      <div class="bg-white p-4 rounded-lg shadow">Card 6</div>
      <div class="bg-white p-4 rounded-lg shadow">Card 7</div>
      <div class="bg-white p-4 rounded-lg shadow">Card 8</div>
    </div>

    <!-- Responsive Show/Hide -->
    <div class="mt-8">
      <p class="block md:hidden text-center text-red-500">Only visible on small screens</p>
      <p class="hidden md:block lg:hidden text-center text-blue-500">Only visible on medium screens</p>
      <p class="hidden lg:block text-center text-green-500">Only visible on large screens</p>
    </div>
  </div>
</body>
</html>
▶ Try it Yourself

Breakpoint reference:

Prefix Min Width Typical Devices
sm: 640px Large phones, small tablets
md: 768px Tablets
lg: 1024px Laptops
xl: 1280px Desktop monitors
2xl: 1536px Large displays

Traditional CSS vs Tailwind The traditional approach requires writing numerous responsive rules inside @media queries, whereas Tailwind declares responsive behavior directly in HTML through prefixes.

Dark Mode Prefix

The dark: prefix makes dark mode adaptation effortless — simply define different styles for dark mode.

Example

HTML
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Dark Mode Demo</title>
  <script src="https://cdn.tailwindcss.com"></script>
</head>
<body class="min-h-screen bg-white dark:bg-gray-900 transition-colors">
  <div class="max-w-2xl mx-auto p-8">
    <h1 class="text-3xl font-bold text-gray-800 dark:text-white mb-6">
      Dark Mode Example
    </h1>
    
    <div class="bg-gray-100 dark:bg-gray-800 rounded-xl p-6 mb-6">
      <p class="text-gray-600 dark:text-gray-300 leading-relaxed">
        This text appears dark gray in light mode and light gray in dark mode.
        The background color switches accordingly.
      </p>
    </div>

    <div class="flex gap-4">
      <button class="bg-blue-500 dark:bg-blue-600 text-white px-6 py-3 rounded-lg
                     hover:bg-blue-600 dark:hover:bg-blue-700 transition-colors">
        Primary Button
      </button>
      <button class="border border-gray-300 dark:border-gray-600
                     text-gray-700 dark:text-gray-300 px-6 py-3 rounded-lg
                     hover:bg-gray-100 dark:hover:bg-gray-800 transition-colors">
        Secondary Button
      </button>
    </div>
  </div>

  <script>
    // Example code to toggle dark mode
    function toggleDarkMode() {
      document.documentElement.classList.toggle('dark');
    }
  </script>
</body>
</html>
▶ Try it Yourself

Traditional CSS vs Tailwind The traditional approach requires writing separate CSS classes for dark mode or using [data-theme="dark"] selectors, whereas Tailwind simply adds a dark: prefix to class names.

⚠️ Note: To enable dark mode, set darkMode: 'class' in the Tailwind configuration, or add the dark class to the <html> tag.

Arbitrary Value Syntax

Tailwind's arbitrary value syntax allows you to insert any CSS value using square brackets [], providing maximum flexibility.

Example

HTML
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Arbitrary Value Syntax Demo</title>
  <script src="https://cdn.tailwindcss.com"></script>
</head>
<body class="min-h-screen bg-gray-100 p-8">
  <div class="max-w-4xl mx-auto space-y-8">
    <!-- Custom Width and Height -->
    <div class="bg-white p-6 rounded-lg shadow">
      <h3 class="font-semibold mb-4">Custom Size</h3>
      <div class="w-[300px] h-[200px] bg-blue-200 rounded flex items-center justify-center">
        300px × 200px
      </div>
    </div>

    <!-- Custom Colors -->
    <div class="bg-white p-6 rounded-lg shadow">
      <h3 class="font-semibold mb-4">Custom Colors</h3>
      <div class="flex gap-4">
        <div class="w-20 h-20 bg-[#ff6b6b] rounded-lg"></div>
        <div class="w-20 h-20 bg-[#4ecdc4] rounded-lg"></div>
        <div class="w-20 h-20 bg-[rgb(102,51,153)] rounded-lg"></div>
        <div class="w-20 h-20 bg-[hsl(207,90%,54%)] rounded-lg"></div>
      </div>
    </div>

    <!-- Custom Spacing -->
    <div class="bg-white p-6 rounded-lg shadow">
      <h3 class="font-semibold mb-4">Custom Spacing</h3>
      <div class="space-y-[15px]">
        <div class="bg-gray-200 p-3 rounded">Spacing 15px</div>
        <div class="bg-gray-200 p-3 rounded">Spacing 15px</div>
        <div class="bg-gray-200 p-3 rounded">Spacing 15px</div>
      </div>
    </div>

    <!-- Custom Font Size -->
    <div class="bg-white p-6 rounded-lg shadow">
      <h3 class="font-semibold mb-4">Custom Font</h3>
      <p class="text-[22px] leading-[32px] text-[#333]">
        Custom 22px font size, 32px line height
      </p>
    </div>
  </div>
</body>
</html>
▶ Try it Yourself

Supported arbitrary value formats:

Syntax Example Description
Fixed value w-[100px] Pixel value
Color value bg-[#ff0000] Hexadecimal color
RGB text-[rgb(255,0,0)] RGB color
CSS variable p-[var(--spacing)] Using CSS variables
Calculated value w-[calc(100%-2rem)] calc expression

Traditional CSS vs Tailwind The traditional approach requires creating custom CSS rules for special values, whereas Tailwind's arbitrary value syntax lets you use any CSS value directly in a class name without additional configuration.

💡 Tip: Spaces in arbitrary values must be replaced with underscores, e.g., grid-cols-[1fr_2fr_1fr] represents grid-template-columns: 1fr 2fr 1fr.

❓ FAQ

Q Do Utility Classes make HTML bloated?
A While there are more class names in HTML, you can reuse code through components (e.g., React, Vue components) during development. In production builds, Tailwind automatically removes unused classes, resulting in a very small final CSS file.
Q Are responsive prefixes mobile-first or desktop-first?
A Tailwind follows a mobile-first strategy. Styles without prefixes apply to all screens, and sm: and above take effect at the corresponding breakpoint and up.
Q How can I support both system preference and manual dark mode switching?
A You can use the darkMode: 'selector' configuration and toggle the dark class on <html> via JavaScript. Combine this with the prefers-color-scheme media query for automatic detection.
Q Does the arbitrary value syntax affect performance?
A Arbitrary values are processed at build time and have no runtime performance impact. However, it's recommended to extract commonly used values into theme configuration for code consistency.

📖 Summary

📝 Exercises

  1. ⭐ Create a button group with normal, hover, focus, and disabled states, demonstrating style changes across different states

  2. ⭐⭐ Create a responsive card list that shows 1 column on mobile, 2 on tablet, 3 on desktop, and 4 on large screens, with light/dark mode toggle

  3. ⭐⭐⭐ Use arbitrary value syntax to create a custom-sized grid layout with irregular column width distribution (e.g., a 1:2:1 ratio) and custom spacing

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏