Tailwind CSS Pattern
Apply Tailwind CSS utility-first patterns for consistent, maintainable component styling
When to Use
- Styling React components without writing custom CSS files
- Building consistent UIs using a design system constraint
- Rapid prototyping with immediate visual feedback
- Maintaining styles that are co-located with component markup
Instructions
- Apply utilities directly on elements. Group by concern: layout, spacing, typography, color, effects.
- Extract repeated utility combinations into React components, not
@applydirectives. Components are the abstraction layer. - Use Tailwind's design tokens (spacing scale, color palette, typography scale) instead of arbitrary values.
- When arbitrary values are needed, use bracket notation:
w-[calc(100%-2rem)],bg-[#1a1a2e]. - Order utilities consistently: layout > positioning > sizing > spacing > typography > color > effects > responsive > state.
- Use
@applyonly in base layer styles (global resets, typography defaults), not in component styles.
// Good — utilities grouped by concern
function Card({ title, children }: { title: string; children: React.ReactNode }) {
return (
<div
className="
flex flex-col /* layout */
rounded-lg /* shape */
p-6 gap-4 /* spacing */
bg-white shadow-md /* visual */
border border-gray-200 /* border */
hover:shadow-lg /* interaction */
transition-shadow /* animation */
"
>
<h3 className="text-lg font-semibold text-gray-900">{title}</h3>
<div className="text-sm text-gray-600">{children}</div>
</div>
);
}
// Component is the abstraction — reuse Card, not @apply
function FeatureCard({ feature }: { feature: Feature }) {
return (
<Card title={feature.name}>
<p>{feature.description}</p>
<Badge variant={feature.status}>{feature.status}</Badge>
</Card>
);
}
// Using Tailwind's design tokens vs arbitrary values
// Prefer tokens
<div className="p-4 text-sm text-gray-700 rounded-md" />
// Use arbitrary only when tokens don't cover it
<div className="p-[18px] text-[13px] text-[#334155] rounded-[5px]" />
Details
Why utility-first works: Every utility maps to one CSS property. You never need to name things. You never wonder where a style comes from — it is right on the element. Dead code elimination is automatic (unused utilities are purged).
Tailwind v4 changes: Tailwind v4 uses CSS-first configuration instead of tailwind.config.js. Theme values are defined in CSS with @theme:
@import 'tailwindcss';
@theme {
--color-primary: #3b82f6;
--font-sans: 'Inter', sans-serif;
--breakpoint-3xl: 1920px;
}
Tailwind v3 config:
// tailwind.config.ts
import type { Config } from 'tailwindcss';
const config: Config = {
content: ['./src/**/*.{ts,tsx}'],
theme: {
extend: {
colors: {
primary: { 50: '#eff6ff', 500: '#3b82f6', 900: '#1e3a8a' },
},
spacing: { '18': '4.5rem' },
},
},
plugins: [],
};
export default config;
When to use @apply: Almost never in components. Use it for:
- Base styles on
body,h1-h6,atags in a global stylesheet - Third-party component overrides where you cannot add classes
- Prose/article content where utility classes are impractical
Performance: Tailwind's output is a single CSS file with only the utilities you use. Typical production size: 10-30 KB gzipped. No runtime cost.
Source
https://tailwindcss.com/docs/utility-first
Process
- Read the instructions and examples in this document.
- Apply the patterns to your implementation, adapting to your specific context.
- Verify your implementation against the details and edge cases listed above.
Harness Integration
- Type: knowledge — this skill is a reference document, not a procedural workflow.
- No tools or state — consumed as context by other skills and agents.
Success Criteria
- The patterns described in this document are applied correctly in the implementation.
- Edge cases and anti-patterns listed in this document are avoided.