Back to docs
05Week 1

Tailwind CSS

Utility-first styling: every class does one thing, composability does the rest

How It Works

Traditional CSS requires you to write styles in a separate file and link them to HTML classes. Tailwind flips this: you apply small, single-purpose utility classes directly in your JSX.

Traditional CSS

/* styles.css */
.card {
  background-color: white;
  border-radius: 8px;
  padding: 24px;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}

.card-title {
  font-size: 20px;
  font-weight: 600;
  color: #111;
}
<div class="card">
  <h2 class="card-title">Hello</h2>
</div>

Tailwind CSS

<div className="bg-white rounded-lg p-6 shadow-sm">
  <h2 className="text-xl font-semibold text-gray-900">Hello</h2>
</div>

No separate file. No naming things. Every class does exactly one thing, and you compose them together to build any design.

The Spacing Scale

Tailwind uses a consistent spacing scale based on 4px increments. This applies to padding (p-), margin (m-), width (w-), height (h-), and gap (gap-).

ClassValuePixels
10.25rem4px
20.5rem8px
30.75rem12px
41rem16px
51.25rem20px
61.5rem24px
82rem32px
102.5rem40px
123rem48px
164rem64px
205rem80px
246rem96px
px1px1px

Examples: p-4 = 16px padding, mt-8 = 32px margin-top, gap-6 = 24px gap.

Layout Utilities

Flexbox

ClassWhat It Does
flexEnable flexbox
flex-rowHorizontal layout (default)
flex-colVertical layout
items-centerCenter items on cross axis
justify-centerCenter items on main axis
justify-betweenSpace items evenly with first/last at edges
gap-416px gap between flex children
flex-1Grow to fill available space
flex-wrapAllow items to wrap to next line

Grid

ClassWhat It Does
gridEnable CSS Grid
grid-cols-22-column grid
grid-cols-33-column grid
grid-cols-44-column grid
col-span-2Span 2 columns
gap-624px gap between grid items

Typography

ClassWhat It Does
text-xs12px font size
text-sm14px font size
text-base16px font size (default)
text-lg18px font size
text-xl20px font size
text-2xl24px font size
text-3xl30px font size
text-4xl36px font size
font-normal400 weight
font-medium500 weight
font-semibold600 weight
font-bold700 weight
leading-tightTight line height (1.25)
leading-relaxedRelaxed line height (1.625)
tracking-tightTight letter spacing
tracking-wideWide letter spacing
text-centerCenter-aligned text
uppercaseTransform text to uppercase

Colors

Tailwind includes a full color palette. Colors follow the format: {property}-{color}-{shade}

text-gray-900     ← Dark gray text
bg-blue-500       ← Medium blue background
border-red-300    ← Light red border

// Common properties:
text-{color}      ← Text color
bg-{color}        ← Background color
border-{color}    ← Border color

// Shade scale: 50 (lightest) → 950 (darkest)
gray-50, gray-100, gray-200, gray-300, gray-400,
gray-500, gray-600, gray-700, gray-800, gray-900, gray-950

Visual Utilities

ClassWhat It Does
rounded4px border radius
rounded-lg8px border radius
rounded-xl12px border radius
rounded-2xl16px border radius
rounded-fullFully rounded (circle/pill)
shadow-smSmall shadow
shadowDefault shadow
shadow-lgLarge shadow
border1px border
border-22px border
opacity-5050% opacity
opacity-0Fully transparent
transition-colorsAnimate color changes
transition-allAnimate all property changes
duration-200200ms transition duration
overflow-hiddenClip overflowing content

State Variants

Tailwind lets you apply styles conditionally based on element state. Prefix any utility class with a state variant:

// Hover state
<button className="bg-gray-900 hover:bg-gray-800">
  Click me
</button>

// Focus state
<input className="border-gray-300 focus:border-blue-500 focus:ring-2 focus:ring-blue-200" />

// Active state
<button className="bg-blue-500 active:bg-blue-700">
  Press me
</button>

// Disabled state
<button className="bg-gray-900 disabled:bg-gray-300 disabled:cursor-not-allowed" disabled>
  Can't click
</button>

// Dark mode
<div className="bg-white dark:bg-gray-900 text-gray-900 dark:text-white">
  Adapts to color scheme
</div>

Responsive Design

Tailwind is mobile-first. Styles without a prefix apply to all screen sizes. Prefixed styles apply at that breakpoint and above.

PrefixMin WidthTypical Device
sm:640pxLarge phones
md:768pxTablets
lg:1024pxLaptops
xl:1280pxDesktops
2xl:1536pxLarge desktops
// Stack on mobile, side-by-side on desktop
<div className="flex flex-col md:flex-row gap-6">
  <div className="w-full md:w-1/2">Left</div>
  <div className="w-full md:w-1/2">Right</div>
</div>

// 1 column on mobile, 2 on tablet, 3 on desktop
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
  <div>Card 1</div>
  <div>Card 2</div>
  <div>Card 3</div>
</div>

// Hide on mobile, show on desktop
<nav className="hidden lg:flex items-center gap-8">
  <a href="/about">About</a>
  <a href="/work">Work</a>
</nav>

Customizing Tailwind

You can extend or override Tailwind’s defaults in tailwind.config.ts:

// tailwind.config.ts
import type { Config } from "tailwindcss"

const config: Config = {
  content: [
    "./app/**/*.{js,ts,jsx,tsx}",
    "./components/**/*.{js,ts,jsx,tsx}",
  ],
  theme: {
    extend: {
      colors: {
        brand: {
          50: "#fef2f2",
          100: "#fee2e2",
          500: "#ef4444",
          900: "#7f1d1d",
        },
      },
      fontFamily: {
        sans: ["Inter", "sans-serif"],
        display: ["Space Grotesk", "sans-serif"],
      },
      borderRadius: {
        "4xl": "2rem",
      },
      animation: {
        "fade-in": "fadeIn 0.5s ease-out",
      },
      keyframes: {
        fadeIn: {
          "0%": { opacity: "0", transform: "translateY(10px)" },
          "100%": { opacity: "1", transform: "translateY(0)" },
        },
      },
    },
  },
  plugins: [],
}

export default config

After customizing, you can use your new tokens like any built-in class: text-brand-500, font-display, rounded-4xl, animate-fade-in.