Episode 1 — Fundamentals / 1.11 — CSS Frameworks TailwindCSS and Bootstrap
1.11.c — TailwindCSS Setup & Basics
In one sentence: TailwindCSS is a utility-first CSS framework that lets you build designs directly in HTML by composing small, single-purpose classes — configured via a central file and compiled to ship only what you use.
Navigation: ← 1.11.b — Utility-First vs Component-Based · 1.11.d — Building with TailwindCSS →
1. What is TailwindCSS?
Tailwind is a utility-first CSS framework that provides thousands of low-level classes like flex, pt-4, text-center, and bg-blue-500. Instead of writing custom CSS, you compose these classes directly in your HTML.
Why it's popular:
- No context-switching between HTML and CSS files
- Production CSS is tiny — unused classes are automatically removed
- A single config file controls the entire design system (colors, spacing, fonts, breakpoints)
- Works with any frontend stack (React, Vue, Svelte, plain HTML)
2. Installation
Option A — Using the CLI (simplest)
npm install -D tailwindcss
npx tailwindcss init
This creates tailwind.config.js. Then add Tailwind directives to your CSS entry file:
/* src/input.css */
@tailwind base;
@tailwind components;
@tailwind utilities;
Build with:
npx tailwindcss -i ./src/input.css -o ./dist/output.css --watch
Option B — With a bundler (Vite, Webpack, etc.)
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p
The -p flag also creates postcss.config.js. Your bundler processes Tailwind through PostCSS automatically.
Configure content paths
Tell Tailwind where to scan for class names so it can purge unused styles:
// tailwind.config.js
module.exports = {
content: [
"./index.html",
"./src/**/*.{js,ts,jsx,tsx,html}",
],
theme: {
extend: {},
},
plugins: [],
};
If a class appears nowhere in these files, it will not be in the production CSS.
3. Core concept: utility classes
Each utility class maps to one (or a small set of) CSS properties:
| Utility class | CSS it generates |
|---|---|
flex | display: flex |
items-center | align-items: center |
p-4 | padding: 1rem |
mt-2 | margin-top: 0.5rem |
text-lg | font-size: 1.125rem; line-height: 1.75rem |
bg-blue-500 | background-color: #3b82f6 |
rounded-lg | border-radius: 0.5rem |
shadow-md | box-shadow: 0 4px 6px -1px rgba(0,0,0,.1), … |
w-full | width: 100% |
hidden | display: none |
You compose them on elements:
<div class="flex items-center gap-4 p-4 bg-white rounded-lg shadow-md">
<img class="w-12 h-12 rounded-full" src="avatar.jpg" alt="User" />
<div>
<p class="font-semibold text-gray-900">Jane Doe</p>
<p class="text-sm text-gray-500">Developer</p>
</div>
</div>
4. Responsive prefixes
Tailwind is mobile-first. Unprefixed utilities apply at all sizes. Prefixed utilities apply at that breakpoint and above:
| Prefix | Min-width | Typical device |
|---|---|---|
sm: | 640px | Large phones |
md: | 768px | Tablets |
lg: | 1024px | Laptops |
xl: | 1280px | Desktops |
2xl: | 1536px | Large screens |
<!-- Stack on mobile, side-by-side on medium+ -->
<div class="flex flex-col md:flex-row gap-4">
<div class="w-full md:w-1/2">Left</div>
<div class="w-full md:w-1/2">Right</div>
</div>
Read this as: "column layout by default; at md (768px+), switch to row."
5. State variants
Apply styles conditionally based on element state:
| Variant | When it applies |
|---|---|
hover: | Mouse over element |
focus: | Element has focus |
active: | Element is being clicked |
disabled: | Element is disabled |
first: | First child |
last: | Last child |
odd: | Odd children |
group-hover: | Parent with group class is hovered |
<button class="bg-blue-600 text-white px-4 py-2 rounded
hover:bg-blue-700 focus:ring-2 focus:ring-blue-500
active:bg-blue-800 disabled:opacity-50">
Submit
</button>
Combine responsive + state: md:hover:bg-blue-700 — hover effect only on medium screens and above.
6. The spacing and color systems
Spacing scale (default)
Tailwind uses a consistent scale where 1 unit = 0.25rem (4px):
| Class | Value | Pixels (at 16px root) |
|---|---|---|
p-0 | 0 | 0px |
p-1 | 0.25rem | 4px |
p-2 | 0.5rem | 8px |
p-4 | 1rem | 16px |
p-6 | 1.5rem | 24px |
p-8 | 2rem | 32px |
Works with margins (m-), gaps (gap-), widths (w-), heights (h-), and more.
Color palette
Colors follow the pattern {property}-{color}-{shade}:
bg-red-500 → background-color: red, medium shade
text-gray-700 → color: dark gray
border-green-300 → border-color: light green
Shades range from 50 (lightest) to 950 (darkest).
7. The @apply directive
Extract repeated utility patterns into custom classes:
/* In your CSS file */
.btn-primary {
@apply bg-blue-600 text-white font-semibold py-2 px-4 rounded-lg
hover:bg-blue-700 focus:outline-none focus:ring-2
focus:ring-blue-500 focus:ring-offset-2;
}
<!-- Now use a single class -->
<button class="btn-primary">Save</button>
Use sparingly. Overusing @apply recreates the problems Tailwind was designed to avoid — hidden styles and naming fatigue. Prefer component abstraction (React/Vue components) over @apply for reuse.
8. Customizing the config
// tailwind.config.js
module.exports = {
content: ["./src/**/*.{html,js,jsx,tsx}"],
theme: {
extend: {
colors: {
brand: {
50: "#eff6ff",
500: "#3b82f6",
900: "#1e3a8a",
},
},
fontFamily: {
sans: ["Inter", "system-ui", "sans-serif"],
},
spacing: {
18: "4.5rem",
},
},
},
plugins: [],
};
extend adds to defaults. Defining at the theme level (without extend) replaces defaults entirely. Use extend unless you intentionally want to remove default values.
9. Key takeaways
- Tailwind gives you utility classes — each does one CSS thing; you compose them in HTML.
contentpaths in the config determine which files are scanned; unused classes are purged.- Responsive prefixes (
sm:,md:,lg:) are mobile-first — unprefixed = all sizes. - State variants (
hover:,focus:,active:) apply styles conditionally. @applyextracts repeated patterns into custom classes — use sparingly.- Customize via
tailwind.config.js— colors, fonts, spacing, breakpoints.
Explain-It Challenge
Explain without notes:
- What the
contentarray intailwind.config.jsdoes and why it matters for production bundle size. - How Tailwind's responsive prefixes work (what does
md:flexmean?). - When you should use
@applyand when you should prefer a component abstraction instead.
Navigation: ← 1.11.b — Utility-First vs Component-Based · 1.11.d — Building with TailwindCSS →