Tailwind Best Practices & Common Patterns
Tailwind Best Practices & Common Patterns
As you build more projects with Tailwind CSS, following best practices and recognizing common patterns will make your code more maintainable, consistent, and efficient. This lesson covers proven techniques and patterns used by experienced Tailwind developers.
Class Ordering Conventions
Maintaining a consistent order for utility classes makes your code more readable and easier to maintain. While Tailwind doesn't enforce a specific order, following a logical pattern helps.
Recommended Class Order
A common convention is to order classes from layout to specific styling:
- Display & Position (flex, grid, absolute, relative)
- Box Model (w-, h-, p-, m-)
- Typography (text-, font-)
- Visual (bg-, border-, shadow-)
- Interactivity (hover:, focus:, cursor-)
- Responsive (sm:, md:, lg:)
Good Class Ordering Example
<!-- Layout → Box Model → Typography → Visual → Interactive → Responsive -->
<button class="
flex items-center justify-center
w-full px-6 py-3 mt-4
text-lg font-semibold text-white
bg-blue-600 rounded-lg shadow-md
hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500
sm:w-auto md:px-8 md:py-4
">
Click Me
</button>
<!-- Bad: Random ordering makes it hard to scan -->
<button class="
hover:bg-blue-700 text-white flex w-full md:px-8
bg-blue-600 items-center px-6 focus:ring-2
rounded-lg py-3 font-semibold sm:w-auto
">
Click Me
</button>
Organizing Long Class Lists
When components have many utility classes, organize them for better readability.
Multi-line Formatting
<!-- Break long class lists into logical groups -->
<div class="
relative flex flex-col
w-full max-w-md mx-auto
p-6 space-y-4
bg-white rounded-xl shadow-lg
border border-gray-200
hover:shadow-xl hover:border-gray-300
transition-all duration-300
sm:max-w-lg md:max-w-xl
dark:bg-gray-800 dark:border-gray-700
">
<!-- Card content -->
</div>
Use Prettier Plugin
Install prettier-plugin-tailwindcss to automatically sort your Tailwind classes. It follows official recommendations and integrates with your existing Prettier setup.
npm install -D prettier prettier-plugin-tailwindcss
Component Patterns
Certain patterns appear repeatedly in web development. Here are common Tailwind patterns to use as starting points.
Container Pattern
<!-- Standard container with max-width and horizontal padding -->
<div class="container mx-auto px-4 sm:px-6 lg:px-8">
<!-- Content -->
</div>
<!-- Full-width section with constrained content -->
<section class="w-full bg-gray-100">
<div class="max-w-7xl mx-auto px-4 py-12 sm:px-6 lg:px-8">
<!-- Constrained content -->
</div>
</section>
Card Pattern
<!-- Standard card component -->
<article class="
bg-white rounded-lg shadow-md
overflow-hidden
hover:shadow-lg
transition-shadow duration-300
">
<img
src="image.jpg"
alt="Card image"
class="w-full h-48 object-cover"
>
<div class="p-6">
<h3 class="text-xl font-bold text-gray-900 mb-2">
Card Title
</h3>
<p class="text-gray-600 mb-4">
Card description goes here...
</p>
<button class="
inline-flex items-center
px-4 py-2
bg-blue-600 text-white
rounded-md
hover:bg-blue-700
transition-colors
">
Learn More
</button>
</div>
</article>
Stack Pattern (Vertical Spacing)
<!-- Using space-y for consistent vertical rhythm -->
<div class="space-y-4">
<div class="p-4 bg-white rounded">Item 1</div>
<div class="p-4 bg-white rounded">Item 2</div>
<div class="p-4 bg-white rounded">Item 3</div>
</div>
<!-- Responsive stacks -->
<div class="space-y-4 md:space-y-6 lg:space-y-8">
<!-- Spacing increases on larger screens -->
</div>
<!-- Horizontal stack with gap -->
<div class="flex gap-4">
<div class="p-4 bg-white rounded">Item 1</div>
<div class="p-4 bg-white rounded">Item 2</div>
<div class="p-4 bg-white rounded">Item 3</div>
</div>
Button Pattern Library
<!-- Primary button -->
<button class="
px-4 py-2
bg-blue-600 text-white
font-medium rounded-md
hover:bg-blue-700
focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2
disabled:opacity-50 disabled:cursor-not-allowed
transition-colors
">
Primary Button
</button>
<!-- Secondary button -->
<button class="
px-4 py-2
bg-gray-200 text-gray-900
font-medium rounded-md
hover:bg-gray-300
focus:outline-none focus:ring-2 focus:ring-gray-500 focus:ring-offset-2
transition-colors
">
Secondary Button
</button>
<!-- Outline button -->
<button class="
px-4 py-2
border-2 border-blue-600
text-blue-600
font-medium rounded-md
hover:bg-blue-50
focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2
transition-colors
">
Outline Button
</button>
<!-- Ghost button -->
<button class="
px-4 py-2
text-blue-600
font-medium rounded-md
hover:bg-blue-50
focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2
transition-colors
">
Ghost Button
</button>
Spacing Consistency
Use Tailwind's spacing scale consistently to create visual rhythm and harmony.
Spacing Scale Best Practices
- Use 4-unit increments for most spacing (p-4, p-8, p-12)
- Use smaller increments (p-1, p-2) for tight spacing
- Maintain consistent padding/margin ratios (e.g., px-6 py-3 for buttons)
- Use space-y and gap utilities for consistent item spacing
Consistent Spacing Example
<!-- Hero section with consistent spacing -->
<section class="py-16 px-4 sm:py-24 sm:px-6 lg:py-32">
<div class="max-w-7xl mx-auto">
<div class="text-center space-y-6">
<h1 class="text-4xl font-bold sm:text-5xl lg:text-6xl">
Main Heading
</h1>
<p class="text-xl text-gray-600 max-w-2xl mx-auto">
Subheading text with consistent spacing
</p>
<div class="flex gap-4 justify-center mt-8">
<button class="px-6 py-3">Button 1</button>
<button class="px-6 py-3">Button 2</button>
</div>
</div>
</div>
</section>
Avoiding Common Mistakes
Common Tailwind Mistakes to Avoid
- Using arbitrary values too often: Stick to the design system when possible
- Not extracting components: Don't repeat the same long class lists everywhere
- Fighting the framework: Don't use custom CSS to undo Tailwind utilities
- Ignoring responsive design: Always test mobile-first
- Premature optimization: Don't worry about file size until it's actually a problem
Mistake: Overusing Arbitrary Values
<!-- Bad: Too many arbitrary values -->
<div class="w-[347px] h-[219px] p-[23px] text-[17.5px]">
Content
</div>
<!-- Good: Use design system values -->
<div class="w-80 h-56 p-6 text-lg">
Content
</div>
<!-- If you need custom values frequently, extend the config -->
<!-- tailwind.config.js -->
module.exports = {
theme: {
extend: {
spacing: {
'18': '4.5rem',
'88': '22rem',
}
}
}
}
Mistake: Not Extracting Components
<!-- Bad: Repeating long class lists -->
<button class="px-6 py-3 bg-blue-600 text-white font-semibold rounded-lg hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500">
Button 1
</button>
<button class="px-6 py-3 bg-blue-600 text-white font-semibold rounded-lg hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500">
Button 2
</button>
<button class="px-6 py-3 bg-blue-600 text-white font-semibold rounded-lg hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500">
Button 3
</button>
<!-- Good: Extract to a component -->
<!-- Button.vue / Button.jsx -->
<button class="btn-primary">
{{ text }}
</button>
<!-- Or use @apply in CSS -->
<style>
.btn-primary {
@apply px-6 py-3 bg-blue-600 text-white font-semibold rounded-lg;
@apply hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500;
}
</style>
Tailwind with SASS (When and Why)
While Tailwind is designed to reduce the need for custom CSS, sometimes combining it with SASS can be beneficial.
When to Use SASS with Tailwind
- Complex calculations: SASS functions for dynamic values
- Theme variables: Creating CSS custom properties from SASS variables
- Legacy codebases: Gradual migration from SASS to Tailwind
- Component libraries: Creating themeable component systems
SASS + Tailwind Example
// styles.scss
@import 'tailwindcss/base';
@import 'tailwindcss/components';
@import 'tailwindcss/utilities';
// SASS variables for theming
$primary-color: #3b82f6;
$secondary-color: #8b5cf6;
$spacing-unit: 0.25rem;
// Create custom components with @apply
.card {
@apply rounded-lg shadow-md overflow-hidden;
&-header {
@apply p-6 border-b border-gray-200;
background-color: lighten($primary-color, 45%);
}
&-body {
@apply p-6;
}
&-footer {
@apply p-6 bg-gray-50 border-t border-gray-200;
}
}
// Complex spacing calculations
.dynamic-spacing {
padding: calc($spacing-unit * 6);
@media (min-width: 768px) {
padding: calc($spacing-unit * 8);
}
}
// Theme mixins
@mixin theme-button($color) {
@apply px-4 py-2 rounded font-semibold transition-colors;
background-color: $color;
&:hover {
background-color: darken($color, 10%);
}
}
.btn-primary {
@include theme-button($primary-color);
@apply text-white;
}
.btn-secondary {
@include theme-button($secondary-color);
@apply text-white;
}
Utility-First Mindset Tips
Adopting the utility-first approach takes practice. Here are tips to help you think in utilities.
Thinking in Utilities
- Start with structure: Use flex/grid first, then style
- Think in layers: Layout → spacing → typography → colors → effects
- Use the docs: Tailwind's documentation is excellent for finding utilities
- Learn the scale: Memorize common spacing values (4, 8, 12, 16, etc.)
- Practice responsive: Always think mobile-first, then add breakpoints
- Embrace repetition: It's okay to repeat classes; extract when it hurts
Utility-First Problem Solving
<!-- Problem: Create a centered hero section -->
<!-- Step 1: Structure (flex, items-center, justify-center) -->
<section class="flex items-center justify-center">
<div>Hero Content</div>
</section>
<!-- Step 2: Sizing (min-h-screen, max-w-4xl) -->
<section class="flex items-center justify-center min-h-screen">
<div class="max-w-4xl">Hero Content</div>
</section>
<!-- Step 3: Spacing (px-4, py-16) -->
<section class="flex items-center justify-center min-h-screen px-4 py-16">
<div class="max-w-4xl">Hero Content</div>
</section>
<!-- Step 4: Typography (text-center, space-y-6) -->
<section class="flex items-center justify-center min-h-screen px-4 py-16">
<div class="max-w-4xl text-center space-y-6">
<h1 class="text-5xl font-bold">Hero Title</h1>
<p class="text-xl text-gray-600">Hero description</p>
</div>
</section>
<!-- Step 5: Colors and effects (bg-gradient-to-r) -->
<section class="flex items-center justify-center min-h-screen px-4 py-16 bg-gradient-to-r from-blue-500 to-purple-600">
<div class="max-w-4xl text-center space-y-6">
<h1 class="text-5xl font-bold text-white">Hero Title</h1>
<p class="text-xl text-blue-100">Hero description</p>
</div>
</section>
Practice Exercise 1: Refactor Component
Take this component with custom CSS and refactor it to use only Tailwind utilities:
<style>
.feature-card {
background: white;
border-radius: 12px;
padding: 32px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
transition: transform 0.3s, box-shadow 0.3s;
}
.feature-card:hover {
transform: translateY(-4px);
box-shadow: 0 12px 24px rgba(0, 0, 0, 0.15);
}
.feature-card h3 {
font-size: 24px;
font-weight: 700;
margin-bottom: 16px;
}
</style>
<div class="feature-card">
<h3>Feature Title</h3>
<p>Feature description</p>
</div>
Practice Exercise 2: Build a Navigation Pattern
Create a responsive navigation bar with the following requirements:
- Logo on the left
- Navigation links in the center (desktop) / hidden (mobile)
- CTA button on the right
- Mobile menu toggle button
- Sticky positioning on scroll
- Semi-transparent background with backdrop blur
Practice Exercise 3: Design System Audit
Review a Tailwind project you've built or one from GitHub and identify:
- Repeated class combinations that could be components
- Arbitrary values that could use the design system
- Inconsistent spacing patterns
- Missing responsive breakpoints
- Opportunities to use Tailwind patterns (space-y, gap, etc.)
Summary
Following best practices in Tailwind CSS leads to more maintainable and consistent codebases:
- Class ordering: Maintain logical order (layout → spacing → typography → visual → interactive → responsive)
- Component patterns: Recognize and reuse common patterns (containers, cards, buttons, stacks)
- Spacing consistency: Stick to the spacing scale for visual harmony
- Avoid mistakes: Don't overuse arbitrary values, extract components when needed
- SASS integration: Combine with SASS only when you need advanced features
- Utility-first mindset: Think in layers, build structure first, then add styling
In the next lesson, we'll explore accessibility features in Tailwind CSS and learn how to build inclusive user interfaces.