Skip to main content
Technology & EngineeringTailwind200 lines

Tailwind Fundamentals

Utility-first CSS fundamentals with Tailwind including class composition, spacing, typography, and layout primitives

Quick Summary30 lines
You are an expert in utility-first CSS development with Tailwind CSS.

## Key Points

- **Compose in markup first.** Reach for `@apply` or component extraction only when duplication is genuinely painful.
- **Use the design system.** Stick to the default scale (`p-4`, `text-lg`, `rounded-md`) for consistency; reach for arbitrary values sparingly.
- **Leverage semantic HTML.** Tailwind styles appearance, not semantics. Keep using proper elements (`<nav>`, `<main>`, `<button>`).
- **Sort classes consistently.** Use the official Prettier plugin (`prettier-plugin-tailwindcss`) to auto-sort class order.
- **Prefix responsive and state variants logically.** Read classes left-to-right as "base, then sm, then md" or "default, then hover."
- **Overusing `@apply`.** This recreates the problems Tailwind eliminates. Prefer framework-level component abstraction.
- **Forgetting `min-h-screen` on layout wrappers.** Without it, short pages leave empty space below content.
- **Using `w-screen` instead of `w-full`.** `w-screen` (100vw) includes scrollbar width and causes horizontal overflow; `w-full` (100%) respects the parent container.
- **Conflicting utilities.** Applying both `flex` and `grid` on the same element or contradictory widths leads to unpredictable results. Only one layout mode per element.
- **Not purging unused styles in production.** Ensure your `content` paths in the Tailwind config cover all template files so the final CSS is small.

## Quick Example

```html
<div class="bg-blue-100 text-blue-900">Light blue background, dark blue text</div>
<div class="bg-slate-800 text-slate-100">Dark slate background, light text</div>
<button class="bg-indigo-600 text-white hover:bg-indigo-700">Action</button>
```

```html
<div class="top-[117px] grid grid-cols-[1fr_2fr_1fr] bg-[#1a1a2e]">
  Custom values
</div>
```
skilldb get tailwind-skills/Tailwind FundamentalsFull skill: 200 lines
Paste into your CLAUDE.md or agent config

Utility-First Fundamentals — Tailwind CSS

You are an expert in utility-first CSS development with Tailwind CSS.

Overview

Tailwind CSS is a utility-first framework where you style elements by composing small, single-purpose classes directly in markup. Instead of writing custom CSS, you apply pre-built utilities like flex, pt-4, text-center, and bg-blue-500 to build designs entirely in HTML.

Core Philosophy

Tailwind's utility-first approach is a deliberate inversion of traditional CSS architecture. Instead of writing semantic class names that describe what an element is and maintaining a separate stylesheet that describes how it looks, you apply small, composable utility classes that describe appearance directly in the markup. This eliminates the indirection layer between HTML and CSS, removes the need to invent naming conventions, and makes it immediately visible what any element looks like just by reading its class list.

The power of this approach is not that it replaces CSS knowledge — it is that it codifies CSS knowledge into a constrained design system. When you use p-4 instead of writing padding: 1rem, you are not saving keystrokes; you are committing to a spacing scale that keeps your entire application consistent. The constraint is the feature. Arbitrary values exist as an escape hatch, but reaching for them frequently is a signal that your configuration needs updating, not that the constraint should be bypassed.

Tailwind works best when combined with component-based frameworks. The common objection that utility classes create duplication is solved by extracting reusable components in React, Vue, or Svelte — not by creating CSS abstractions with @apply. The component is the abstraction boundary, and within that boundary, utility classes provide maximum clarity and zero indirection.

Core Concepts

The Utility-First Workflow

Traditional CSS creates an abstraction layer between HTML and styles. Tailwind inverts this: styles live in the markup, eliminating the need to invent class names or maintain separate stylesheets.

<!-- Traditional approach -->
<div class="card-wrapper">
  <h2 class="card-title">Hello</h2>
</div>

<!-- Tailwind utility-first approach -->
<div class="rounded-lg border border-gray-200 bg-white p-6 shadow-sm">
  <h2 class="text-xl font-semibold text-gray-900">Hello</h2>
</div>

Spacing Scale

Tailwind uses a consistent spacing scale based on 0.25rem increments:

ClassValue
p-00
p-10.25rem (4px)
p-20.5rem (8px)
p-41rem (16px)
p-82rem (32px)

Spacing applies to padding (p-), margin (m-), gap (gap-), width (w-), height (h-), and more. Directional variants exist: px- (horizontal), py- (vertical), pt- (top), mr- (right), etc.

Typography

<!-- Font size and weight -->
<p class="text-sm font-medium">Small medium text</p>
<h1 class="text-4xl font-bold tracking-tight">Large heading</h1>

<!-- Text color and alignment -->
<p class="text-center text-gray-600">Centered muted text</p>

<!-- Line height and letter spacing -->
<p class="text-lg leading-relaxed tracking-wide">Readable body text</p>

Color System

Tailwind provides a palette with shades from 50 (lightest) to 950 (darkest):

<div class="bg-blue-100 text-blue-900">Light blue background, dark blue text</div>
<div class="bg-slate-800 text-slate-100">Dark slate background, light text</div>
<button class="bg-indigo-600 text-white hover:bg-indigo-700">Action</button>

Layout with Flexbox and Grid

<!-- Flexbox row with gap -->
<div class="flex items-center gap-4">
  <img class="h-10 w-10 rounded-full" src="avatar.jpg" alt="" />
  <div>
    <p class="font-medium">Jane Doe</p>
    <p class="text-sm text-gray-500">Developer</p>
  </div>
</div>

<!-- CSS Grid -->
<div class="grid grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-3">
  <div class="rounded-lg bg-white p-4 shadow">Card 1</div>
  <div class="rounded-lg bg-white p-4 shadow">Card 2</div>
  <div class="rounded-lg bg-white p-4 shadow">Card 3</div>
</div>

<!-- Centering -->
<div class="flex min-h-screen items-center justify-center">
  <p>Perfectly centered</p>
</div>

Borders, Shadows, and Rounded Corners

<div class="rounded-md border border-gray-300 shadow-sm">Subtle card</div>
<div class="rounded-2xl border-2 border-blue-500 shadow-lg">Prominent card</div>
<div class="divide-y divide-gray-200">
  <div class="py-3">Row 1</div>
  <div class="py-3">Row 2</div>
</div>

Sizing and Constraints

<!-- Fixed and relative sizing -->
<div class="h-64 w-full">Full width, fixed height</div>
<div class="min-h-screen">At least viewport height</div>
<div class="max-w-prose mx-auto">Readable width container</div>

<!-- Aspect ratio -->
<div class="aspect-video w-full">16:9 container</div>

Implementation Patterns

Extracting Repeated Utilities with @apply

When a combination is repeated many times, extract it to a CSS class:

/* input.css */
@layer components {
  .btn-primary {
    @apply rounded-md bg-indigo-600 px-4 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600;
  }
}

Prefer component abstractions in your framework (React components, Vue components) over @apply for most cases.

State Variants

<!-- Hover, focus, active -->
<button class="bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 active:bg-blue-800">
  Click me
</button>

<!-- Group hover -->
<a class="group flex items-center gap-2">
  <span class="text-gray-700 group-hover:text-blue-600">Link text</span>
  <svg class="h-4 w-4 text-gray-400 group-hover:text-blue-600">...</svg>
</a>

<!-- First, last, odd, even -->
<ul>
  <li class="first:pt-0 last:pb-0 border-b py-3 odd:bg-gray-50">Item</li>
</ul>

Arbitrary Values

When the design system does not cover a value, use square bracket notation:

<div class="top-[117px] grid grid-cols-[1fr_2fr_1fr] bg-[#1a1a2e]">
  Custom values
</div>

Best Practices

  • Compose in markup first. Reach for @apply or component extraction only when duplication is genuinely painful.
  • Use the design system. Stick to the default scale (p-4, text-lg, rounded-md) for consistency; reach for arbitrary values sparingly.
  • Leverage semantic HTML. Tailwind styles appearance, not semantics. Keep using proper elements (<nav>, <main>, <button>).
  • Sort classes consistently. Use the official Prettier plugin (prettier-plugin-tailwindcss) to auto-sort class order.
  • Prefix responsive and state variants logically. Read classes left-to-right as "base, then sm, then md" or "default, then hover."

Common Pitfalls

  • Overusing @apply. This recreates the problems Tailwind eliminates. Prefer framework-level component abstraction.
  • Forgetting min-h-screen on layout wrappers. Without it, short pages leave empty space below content.
  • Using w-screen instead of w-full. w-screen (100vw) includes scrollbar width and causes horizontal overflow; w-full (100%) respects the parent container.
  • Conflicting utilities. Applying both flex and grid on the same element or contradictory widths leads to unpredictable results. Only one layout mode per element.
  • Not purging unused styles in production. Ensure your content paths in the Tailwind config cover all template files so the final CSS is small.

Anti-Patterns

  • @apply everywhere. Extracting utilities into CSS classes with @apply recreates the abstraction layer Tailwind eliminates. If you find yourself writing .card { @apply rounded-lg border p-6 shadow-sm; }, extract a framework component instead.

  • Fighting the design system with arbitrary values. Littering markup with w-[347px], mt-[13px], and text-[#4a5568] defeats the purpose of a constrained utility system. If a value is used more than once, add it to the Tailwind config; if it is truly one-off, question whether the design is correct.

  • Treating Tailwind as inline styles. Tailwind utilities are not inline styles — they participate in the cascade, support responsive prefixes, state variants, and dark mode. Developers who avoid Tailwind because "it looks like inline styles" miss that utilities provide a design-system-constrained vocabulary that inline styles never offer.

  • Mixing layout modes on a single element. Applying both flex and grid to the same element, or combining conflicting width utilities like w-full and w-64, produces unpredictable results. Each element gets one layout mode and one sizing strategy.

  • Skipping the Prettier plugin. Without prettier-plugin-tailwindcss, class lists accumulate in random order, making them harder to scan and more likely to contain duplicates or conflicts. Consistent class ordering is not cosmetic — it is a readability and maintenance tool.

Install this skill directly: skilldb add tailwind-skills

Get CLI access →