Tailwind CSS Advanced Techniques
Tailwind CSS Advanced Techniques
Tailwind CSS has revolutionized how we write CSS. Beyond the basics, there are powerful techniques that can make your styling even more efficient and maintainable.
Customizing Tailwind Configuration
Extending the Theme
// tailwind.config.js
module.exports = {
theme: {
extend: {
colors: {
brand: {
50: '#f0f9ff',
100: '#e0f2fe',
200: '#bae6fd',
300: '#7dd3fc',
400: '#38bdf8',
500: '#0ea5e9',
600: '#0284c7',
700: '#0369a1',
800: '#075985',
900: '#0c4a6e',
},
primary: '#3b82f6',
secondary: '#8b5cf6',
},
fontFamily: {
sans: ['Inter var', 'sans-serif'],
display: ['Cal Sans', 'sans-serif'],
},
spacing: {
'18': '4.5rem',
'128': '32rem',
},
borderRadius: {
'4xl': '2rem',
},
},
},
}
Adding Custom Utilities
// tailwind.config.js
const plugin = require('tailwindcss/plugin')
module.exports = {
plugins: [
plugin(function ({ addUtilities, theme, variants }) {
const newUtilities = {
'.text-shadow': {
textShadow: '0 2px 4px rgba(0, 0, 0, 0.1)',
},
'.text-shadow-lg': {
textShadow: '0 4px 8px rgba(0, 0, 0, 0.2)',
},
'.text-shadow-none': {
textShadow: 'none',
},
}
addUtilities(newUtilities)
}),
],
}
Creating Custom Components
Reusable Card Component
<!-- Using @apply for component classes -->
<style>
.card {
@apply bg-white rounded-xl shadow-lg overflow-hidden;
}
.card-header {
@apply px-6 py-4 border-b border-gray-100;
}
.card-body {
@apply p-6;
}
.card-footer {
@apply px-6 py-4 bg-gray-50;
}
</style>
<!-- In your HTML -->
<div class="card">
<div class="card-header">
<h3 class="text-lg font-semibold">Card Title</h3>
</div>
<div class="card-body">
<p>Card content goes here...</p>
</div>
<div class="card-footer">
<button class="btn btn-primary">Action</button>
</div>
</div>
Button Variants
// tailwind.config.js
plugin(function ({ addComponents, theme }) {
const buttons = {
'.btn': {
padding: '.75rem 1.5rem',
borderRadius: '.5rem',
fontWeight: '600',
transition: 'all 150ms ease',
'&:hover': {
transform: 'translateY(-1px)',
},
},
'.btn-primary': {
backgroundColor: theme('colors.blue.600'),
color: theme('colors.white'),
'&:hover': {
backgroundColor: theme('colors.blue.700'),
},
},
'.btn-secondary': {
backgroundColor: theme('colors.gray.200'),
color: theme('colors.gray.900'),
'&:hover': {
backgroundColor: theme('colors.gray.300'),
},
},
'.btn-outline': {
backgroundColor: 'transparent',
borderWidth: '2px',
borderColor: theme('colors.blue.600'),
color: theme('colors.blue.600'),
'&:hover': {
backgroundColor: theme('colors.blue.600'),
color: theme('colors.white'),
},
},
}
addComponents(buttons)
})
Advanced Responsive Patterns
Responsive Grid with Auto-fit
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-6">
<!-- Cards that automatically fill available space -->
<div class="bg-white rounded-lg p-6 shadow">Card 1</div>
<div class="bg-white rounded-lg p-6 shadow">Card 2</div>
<div class="bg-white rounded-lg p-6 shadow">Card 3</div>
<div class="bg-white rounded-lg p-6 shadow">Card 4</div>
</div>
Responsive Typography
<h1 class="text-2xl sm:text-3xl md:text-4xl lg:text-5xl xl:text-6xl font-bold leading-tight">
Responsive Heading
</h1>
<p class="text-sm sm:text-base md:text-lg text-gray-600 max-w-prose">
This paragraph adjusts its size based on the viewport.
</p>
Responsive Visibility Patterns
<!-- Mobile-first approach -->
<div class="hidden md:block">
This content is hidden on mobile, visible on medium screens and up.
</div>
<div class="block md:hidden">
This content is only visible on mobile.
</div>
<!-- More complex breakpoints -->
<div class="hidden lg:grid xl:grid-cols-3">
Grid visible only on large screens and up.
</div>
State Variants
Hover, Focus, and Active States
<button class="bg-blue-500 hover:bg-blue-600 active:bg-blue-700
text-white px-4 py-2 rounded transition-colors duration-200">
Click me
</button>
<!-- Focus ring -->
<input
type="text"
class="border border-gray-300 rounded px-4 py-2
focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent"
/>
Group Hover
<div class="group relative overflow-hidden rounded-lg cursor-pointer">
<img src="image.jpg" alt="" class="w-full h-48 object-cover
group-hover:scale-110 transition-transform duration-300" />
<div class="absolute inset-0 bg-black bg-opacity-0
group-hover:bg-opacity-50 transition-all duration-300 flex items-center justify-center">
<span class="text-white opacity-0 group-hover:opacity-100 transition-opacity duration-300">
View Details
</span>
</div>
</div>
Peer States (Tailwind 3.x)
<div>
<input type="checkbox" id="toggle" class="peer hidden" />
<label for="toggle" class="cursor-pointer">
<div class="w-14 h-8 bg-gray-300 rounded-full peer-checked:bg-blue-500
transition-colors duration-300 relative">
<div class="absolute top-1 left-1 w-6 h-6 bg-white rounded-full shadow
peer-checked:translate-x-6 transition-transform duration-300">
</div>
</div>
</label>
</div>
Dark Mode
Enabling Dark Mode
// tailwind.config.js
module.exports = {
darkMode: 'class', // or 'media' for system preference
}
Implementing Dark Mode
<body class="bg-white dark:bg-gray-900 text-gray-900 dark:text-white">
<div class="bg-gray-50 dark:bg-gray-800 rounded-lg p-6">
<h2 class="text-2xl font-bold mb-4">Dark Mode Content</h2>
<p class="text-gray-600 dark:text-gray-300">
This text adapts to the color scheme.
</p>
</div>
</body>
Dark Mode Toggle
<button id="theme-toggle" class="p-2 rounded-lg bg-gray-200 dark:bg-gray-700">
<svg class="w-5 h-5 hidden dark:block" fill="currentColor" viewBox="0 0 20 20">
<!-- Sun icon -->
<path d="M10 2a1 1 0 011 1v1a1 1 0 11-2 0V3a1 1 0 011-1zm4 8a4 4 0 11-8 0 4 4 0 018 0zm-.464 4.95l.707.707a1 1 0 001.414-1.414l-.707-.707a1 1 0 00-1.414 1.414zm2.12-10.607a1 1 0 010 1.414l-.706.707a1 1 0 11-1.414-1.414l.707-.707a1 1 0 011.414 0zM17 11a1 1 0 100-2h-1a1 1 0 100 2h1zm-7 4a1 1 0 011 1v1a1 1 0 11-2 0v-1a1 1 0 011-1zM5.05 6.464A1 1 0 106.465 5.05l-.708-.707a1 1 0 00-1.414 1.414l.707.707zm1.414 8.486l-.707.707a1 1 0 01-1.414-1.414l.707-.707a1 1 0 011.414 1.414zM4 11a1 1 0 100-2H3a1 1 0 000 2h1z"/>
</svg>
<svg class="w-5 h-5 block dark:hidden" fill="currentColor" viewBox="0 0 20 20">
<!-- Moon icon -->
<path d="M17.293 13.293A8 8 0 016.707 2.707a8.001 8.001 0 1010.586 10.586z"/>
</svg>
</button>
<script>
document.getElementById('theme-toggle').addEventListener('click', () => {
document.documentElement.classList.toggle('dark')
})
</script>
Animations and Transitions
Custom Animations
// tailwind.config.js
module.exports = {
theme: {
extend: {
animation: {
'spin-slow': 'spin 3s linear infinite',
'bounce-slow': 'bounce 2s infinite',
'wiggle': 'wiggle 1s ease-in-out infinite',
'fade-in': 'fadeIn 0.5s ease-in-out',
},
keyframes: {
wiggle: {
'0%, 100%': { transform: 'rotate(-3deg)' },
'50%': { transform: 'rotate(3deg)' },
},
fadeIn: {
'0%': { opacity: '0' },
'100%': { opacity: '1' },
},
},
},
},
}
Transition Utilities
<!-- Fade in on hover -->
<div class="opacity-0 hover:opacity-100 transition-opacity duration-300">
Fade in content
</div>
<!-- Scale on hover -->
<div class="transform hover:scale-105 transition-transform duration-200">
Scaled content
</div>
<!-- Combined transitions -->
<button class="transform hover:scale-105 hover:-translate-y-1
transition-all duration-200 ease-out">
Complex transition
</button>
Gradients
Basic Gradients
<div class="bg-gradient-to-r from-purple-400 via-pink-500 to-red-500">
Gradient background
</div>
<div class="bg-gradient-to-br from-green-400 to-blue-500">
Diagonal gradient
</div>
Gradient Text
<h1 class="text-4xl font-bold bg-clip-text text-transparent
bg-gradient-to-r from-pink-500 to-violet-500">
Gradient Text
</h1>
Animated Gradient
<div class="bg-gradient-to-r from-purple-400 via-pink-500 to-purple-400
bg-[length:200%_auto] animate-gradient">
Animated gradient
</div>
<style>
@keyframes gradient {
0% { background-position: 0% 50%; }
50% { background-position: 100% 50%; }
100% { background-position: 0% 50%; }
}
.animate-gradient {
animation: gradient 3s ease infinite;
}
</style>
Responsive Container Queries (Tailwind 3.2+)
<div class="@container">
<div class="@sm:flex @lg:grid @lg:grid-cols-2">
<!-- Content adapts to container size, not viewport -->
<div class="@lg:bg-blue-100">Item 1</div>
<div class="@lg:bg-blue-200">Item 2</div>
</div>
</div>
Performance Optimization
Purge Configuration
// tailwind.config.js
module.exports = {
content: [
'./src/pages/**/*.{js,ts,jsx,tsx}',
'./src/components/**/*.{js,ts,jsx,tsx}',
'./src/layouts/**/*.{js,ts,jsx,tsx}',
],
// Safelist specific classes if needed
safelist: [
'bg-red-500',
'text-center',
{
pattern: /bg-(red|blue|green)-(100|200|300)/,
},
],
}
JIT Mode (Default in Tailwind 3)
<!-- Arbitrary values -->
<div class="w-[137px] h-[42rem] bg-[#1da1f2]">
Custom dimensions and colors
</div>
<!-- Arbitrary properties -->
<div class="[mask-type:luminance] [mask-image:url('mask.png')]">
Custom CSS properties
</div>
<!-- Complex selectors -->
<div class="[&>p]:mb-4 [&_a]:text-blue-500 hover:[&>p]:text-gray-700">
Paragraphs have margin, links are blue
</div>
Best Practices
1. Use Component Abstraction
// React component
function Card({ children, variant = 'default' }) {
const variants = {
default: 'bg-white shadow-md',
elevated: 'bg-white shadow-xl',
outline: 'border border-gray-200',
}
return (
<div className={`rounded-lg p-6 ${variants[variant]}`}>
{children}
</div>
)
}
2. Avoid Deep Nesting
<!-- Avoid -->
<div class="bg-white">
<div class="p-4">
<div class="rounded-lg">
<span class="text-gray-900">Content</span>
</div>
</div>
</div>
<!-- Prefer -->
<div class="bg-white p-4 rounded-lg">
<span class="text-gray-900">Content</span>
</div>
3. Use Consistent Spacing Scale
<!-- Stick to the spacing scale -->
<div class="p-4 space-y-4">
<div>Item with 4 spacing</div>
<div>Consistent spacing</div>
</div>
Conclusion
Tailwind CSS provides powerful utilities for building modern interfaces. By mastering these advanced techniques, you can create maintainable, performant, and beautiful user interfaces with minimal CSS overhead.
Start experimenting with these patterns in your next project!