
Tailwind CSS Best Practices for 2024
Learn the essential best practices for using Tailwind CSS effectively in your projects, including organization, performance, and maintainability tips.
Tailwind CSS Best Practices for 2024
Tailwind CSS has revolutionized how we write CSS, but with great power comes the need for great practices. Here are the essential best practices we've learned from building dozens of projects with Tailwind.
1. Organize Your Utilities with Component Classes
Instead of writing long utility chains everywhere, create component classes for reusable patterns:
/* styles/components.css */
@layer components {
.btn-primary {
@apply bg-mint-primary hover:bg-mint-dark text-charcoal font-semibold px-6 py-2 rounded-lg shadow-lg transition-all duration-300;
}
.card {
@apply bg-white dark:bg-dark-secondary rounded-lg shadow-lg p-6 border border-gray-200 dark:border-gray-700;
}
}
2. Use CSS Custom Properties for Dynamic Values
Leverage CSS custom properties for values that need to change dynamically:
:root {
--primary: 16 244 148; /* RGB values for HSL */
--primary-dark: 13 216 122;
}
.dark {
--primary: 16 244 148;
--primary-dark: 13 216 122;
}
Then use them in your Tailwind config:
// tailwind.config.js
module.exports = {
theme: {
extend: {
colors: {
primary: 'rgb(var(--primary) / <alpha-value>)',
'primary-dark': 'rgb(var(--primary-dark) / <alpha-value>)',
}
}
}
}
3. Implement a Consistent Spacing Scale
Stick to Tailwind's default spacing scale and avoid arbitrary values:
// ✅ Good - uses consistent spacing
<div className="p-4 mb-6 space-y-8">
<section className="mt-12 px-6">
<h2 className="mb-4">Title</h2>
</section>
</div>
// ❌ Avoid - arbitrary values break consistency
<div className="p-[17px] mb-[23px]">
<section className="mt-[49px]">
<h2 className="mb-[15px]">Title</h2>
</section>
</div>
4. Use Semantic Color Names
Instead of generic color names, use semantic names that describe their purpose:
// tailwind.config.js
module.exports = {
theme: {
extend: {
colors: {
// ✅ Semantic names
'brand-primary': '#10f494',
'brand-secondary': '#fd79a8',
'surface-primary': '#f5f3ee',
'surface-secondary': '#e4e2dd',
'text-primary': '#0c0c10',
'text-secondary': '#6b7280',
// ❌ Generic names (harder to maintain)
'green-custom': '#10f494',
'pink-custom': '#fd79a8',
}
}
}
}
5. Optimize for Performance
Purge Unused Styles
Ensure your purge configuration captures all files:
// tailwind.config.js
module.exports = {
content: [
'./pages/**/*.{js,ts,jsx,tsx,mdx}',
'./components/**/*.{js,ts,jsx,tsx,mdx}',
'./app/**/*.{js,ts,jsx,tsx,mdx}',
'./data/**/*.mdx', // Don't forget content files!
],
}
Use JIT Mode Features
Take advantage of Just-In-Time compilation:
// Dynamic values
<div className="grid-cols-[repeat(auto-fit,minmax(300px,1fr))]">
// Arbitrary properties
<div className="[mask-type:luminance]">
// Modifiers
<div className="lg:[&:nth-child(3)]:hover:bg-red-500">
6. Responsive Design Strategy
Use a mobile-first approach with meaningful breakpoints:
// ✅ Mobile-first approach
<div className="
w-full
sm:w-1/2
md:w-1/3
lg:w-1/4
xl:w-1/5
">
// Use consistent responsive patterns
<nav className="
flex flex-col space-y-2
md:flex-row md:space-y-0 md:space-x-6
">
7. Dark Mode Implementation
Implement dark mode consistently across your application:
// Use the class strategy
<div className="bg-white text-gray-900 dark:bg-gray-900 dark:text-white">
// Group dark mode variants
<button className="
bg-white text-gray-900 border-gray-300
dark:bg-gray-800 dark:text-white dark:border-gray-600
hover:bg-gray-50 dark:hover:bg-gray-700
">
8. Component Composition Patterns
Create flexible component APIs using Tailwind:
// Flexible Button component
function Button({
variant = 'primary',
size = 'md',
className = '',
...props
}) {
const baseClasses = 'font-semibold rounded-lg transition-all duration-300 focus:outline-none focus:ring-2'
const variants = {
primary: 'bg-mint-primary hover:bg-mint-dark text-charcoal focus:ring-mint-primary',
secondary: 'bg-gray-200 hover:bg-gray-300 text-gray-900 focus:ring-gray-300',
outline: 'border-2 border-mint-primary text-mint-primary hover:bg-mint-primary hover:text-charcoal'
}
const sizes = {
sm: 'px-3 py-1.5 text-sm',
md: 'px-4 py-2 text-base',
lg: 'px-6 py-3 text-lg'
}
return (
<button
className={cn(baseClasses, variants[variant], sizes[size], className)}
{...props}
/>
)
}
9. Accessibility Considerations
Don't forget accessibility when using Tailwind:
// Focus states
<button className="
focus:outline-none
focus:ring-2
focus:ring-mint-primary
focus:ring-offset-2
">
// Screen reader considerations
<div className="sr-only">
This content is only for screen readers
</div>
// High contrast mode
<div className="bg-blue-500 contrast-more:bg-blue-600">
10. Advanced Customization
Custom Animations
// tailwind.config.js
module.exports = {
theme: {
extend: {
animation: {
'fade-in': 'fadeIn 0.5s ease-in-out',
'slide-up': 'slideUp 0.3s ease-out',
'bounce-slow': 'bounce 2s infinite',
},
keyframes: {
fadeIn: {
'0%': { opacity: '0' },
'100%': { opacity: '1' },
},
slideUp: {
'0%': { transform: 'translateY(10px)', opacity: '0' },
'100%': { transform: 'translateY(0)', opacity: '1' },
}
}
}
}
}
Plugin Development
Create custom plugins for repeated patterns:
// tailwind.config.js
const plugin = require('tailwindcss/plugin')
module.exports = {
plugins: [
plugin(function({ addUtilities }) {
addUtilities({
'.mint-gradient': {
background: 'linear-gradient(135deg, #10f494 0%, #0dd87a 100%)',
},
'.glass-effect': {
background: 'rgba(255, 255, 255, 0.1)',
backdropFilter: 'blur(10px)',
border: '1px solid rgba(255, 255, 255, 0.2)',
}
})
})
]
}
Conclusion
Following these best practices will help you build more maintainable, performant, and accessible applications with Tailwind CSS. Remember, the key is consistency and thoughtful organization of your styles.
The beauty of Tailwind lies in its flexibility, but with that flexibility comes the responsibility to establish good patterns and stick to them throughout your project.
Ready to implement these practices in your next project? Check out our Tailwind CSS starter template that includes all these patterns pre-configured.