Tailwind CSS Tips I Wish I Knew Earlier
Tailwind CSS has a reputation for being easy to pick up but hard to master. After using it across multiple projects — from landing pages to full SaaS dashboards — here are the tips that genuinely changed how I write CSS.
1. Use @apply Sparingly — But Do Use It
The point of Tailwind is utility classes in your HTML. But when you have a pattern you repeat constantly (a button style, a card, a badge), @apply is the right tool:
/* resources/css/app.css */
@layer components {
.btn-primary {
@apply inline-flex items-center px-4 py-2 bg-indigo-600 text-white
text-sm font-medium rounded-lg hover:bg-indigo-700
focus:outline-none focus:ring-2 focus:ring-indigo-500
transition-colors duration-200;
}
.badge {
@apply inline-flex items-center px-2.5 py-0.5 rounded-full
text-xs font-medium;
}
}
The rule: if you’re copy-pasting the same 8+ classes more than 3 times, extract to a component class.
2. group and peer Are Underused
These two classes let you style elements based on the state of a parent or sibling — without a single line of JavaScript.
group — style children based on parent state:
<div class="group cursor-pointer">
<img class="group-hover:scale-105 transition-transform duration-300" src="..." />
<p class="group-hover:text-indigo-600 transition-colors">Read more →</p>
</div>
peer — style siblings based on input state:
<input type="checkbox" class="peer hidden" id="toggle" />
<label for="toggle" class="peer-checked:bg-indigo-600 peer-checked:text-white
border rounded-lg px-4 py-2 cursor-pointer transition-all">
Enable notifications
</label>
No JavaScript toggle needed. Just CSS.
3. The divide- Utilities Replace Most Border Hacks
Instead of adding border-b to every item except the last, use divide-y:
<!-- Before: messy -->
<div>
<div class="border-b pb-4">Item 1</div>
<div class="border-b pb-4">Item 2</div>
<div class="pb-4">Item 3</div> <!-- no border on last -->
</div>
<!-- After: clean -->
<div class="divide-y divide-gray-200">
<div class="py-4">Item 1</div>
<div class="py-4">Item 2</div>
<div class="py-4">Item 3</div>
</div>
Works horizontally too with divide-x.
4. Arbitrary Values Are More Powerful Than You Think
When the default scale doesn’t fit, use square bracket notation:
<!-- Exact pixel values -->
<div class="w-[340px] h-[480px]">
<!-- CSS variables -->
<div class="text-[var(--brand-color)]">
<!-- Calc -->
<div class="w-[calc(100%-2rem)]">
<!-- Complex gradients -->
<div class="bg-[linear-gradient(135deg,#667eea_0%,#764ba2_100%)]">
This is especially useful for matching a design spec exactly without overriding the config.
5. aspect-ratio Solves Responsive Media Forever
Forget the old padding-bottom hack for responsive videos and images:
<!-- 16:9 video embed -->
<div class="aspect-video">
<iframe class="w-full h-full" src="..."></iframe>
</div>
<!-- Square image -->
<div class="aspect-square overflow-hidden rounded-xl">
<img class="w-full h-full object-cover" src="..." />
</div>
<!-- Custom ratio -->
<div class="aspect-[4/3]">...</div>
6. Dark Mode With class Strategy
Switch to class-based dark mode in your config:
// tailwind.config.js
module.exports = {
darkMode: 'class',
}
Then toggle the dark class on your <html> element:
// Toggle dark mode
document.documentElement.classList.toggle('dark');
<!-- In your templates -->
<div class="bg-white dark:bg-gray-900 text-gray-900 dark:text-gray-100">
<p class="text-gray-600 dark:text-gray-400">Content</p>
</div>
In Alpine.js:
<html x-data="{ dark: false }" :class="{ 'dark': dark }">
<button @click="dark = !dark">Toggle</button>
7. container + Custom Max-Width
The default container class centers your layout but doesn’t add padding. Add it globally:
// tailwind.config.js
module.exports = {
theme: {
container: {
center: true,
padding: {
DEFAULT: '1rem',
sm: '2rem',
lg: '4rem',
xl: '5rem',
},
},
},
}
Now <div class="container"> is perfectly centered with responsive padding on every page.
8. Use ring Instead of Custom Focus Styles
Browser default focus outlines are ugly. Tailwind’s ring utilities give you beautiful, accessible focus styles:
<button class="focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2
px-4 py-2 bg-indigo-600 text-white rounded-lg">
Click me
</button>
Combine with focus-visible: to only show the ring for keyboard navigation (not mouse clicks):
<button class="focus:outline-none focus-visible:ring-2 focus-visible:ring-indigo-500">
Quick Reference
| Tip | When to use |
|---|---|
| @apply | Repeated 8+ class patterns |
| group / peer | Parent/sibling state styling without JS |
| divide-y / divide-x | Lists with separators |
| Arbitrary values [] | Exact design spec values |
| aspect-video / aspect-square | Responsive media embeds |
| dark: classes | Dark mode theming |
| Container config | Consistent page layout |
| focus-visible:ring | Accessible focus styles |
Tailwind rewards you for learning its full API. The utilities above are rarely shown in beginner tutorials but used constantly in production codebases. Start applying them one at a time and you’ll find yourself writing less CSS — and better interfaces — faster than before.