
Tailwind is known for utility classes in HTML or JSX, but it also provides CSS directives and functions for organizing custom styles. The important part is knowing when these tools improve maintainability and when they simply recreate a hard-to-track CSS abstraction layer.
@apply
@apply lets you reuse a group of utility classes inside CSS:
@layer components {
.btn {
@apply rounded-md bg-blue-600 px-4 py-2 font-medium text-white;
}
}
Then use:
<button class="btn">Save</button>
Use @apply when a stable style group is repeated and truly belongs in CSS. Do not use it to hide every class name just because the markup looks long.
For interactive states, prefer clear component APIs or direct classes. Be careful with variants and framework version differences.
@layer
@layer places custom CSS into Tailwind's layering model:
@layer base {
h1 {
@apply text-3xl font-bold;
}
}
@layer components {
.card {
@apply rounded-lg border p-6;
}
}
@layer utilities {
.text-shadow {
text-shadow: 0 1px 2px rgb(0 0 0 / 0.3);
}
}
Use layers to make custom CSS participate predictably in Tailwind's ordering. Without clear layering, you may get surprising overrides.
@config
Some setups let CSS reference a specific Tailwind config:
@config "./tailwind.config.js";
Most projects should keep configuration in the normal project setup and use @config only when they have a clear multi-config need.
theme()
theme() reads values from the Tailwind theme:
.btn {
padding: theme("spacing.6");
background-color: theme("colors.blue.600");
}
This keeps custom CSS aligned with your design scale. If you use custom CSS but hard-code unrelated values everywhere, Tailwind's consistency benefit weakens.
screen()
screen() can reference configured breakpoints:
@media screen(md) {
.container {
max-width: 768px;
}
}
In many component cases, responsive variants in class names are simpler:
<div class="grid grid-cols-1 md:grid-cols-2">
...
</div>
Use CSS functions when the custom CSS itself needs to understand the theme.
When not to use these tools
Avoid directives and functions when:
- A normal utility class is clearer at the call site.
- A React component API would express the variation better.
- You are hiding one-off styles behind vague class names.
- The team no longer knows where a visual rule comes from.
Long class strings are not automatically bad. Unnamed or misleading abstraction is worse.
Related FreeMac guides
- For setup and v4 basics, read Tailwind CSS 4 Guide: Setup, Theme, and Responsive Design.
- For spacing, read Tailwind CSS Spacing: How the Scale Works.
- For CSS reset keywords, read CSS initial, inherit, and unset: How to Choose.
Continue reading
Tailwind CSS 4 Guide: Setup, Theme, and Responsive Design
Start with Tailwind CSS 4 using the CLI, CSS import, utility classes, responsive variants, state variants, theme variables, class scanning, and component extraction.
9 min readCSS 3D: perspective and transform-style Explained
Understand CSS 3D transforms through perspective, transform-style: preserve-3d, translateZ, rotateY, flattening, and parent-child 3D scene setup.
7 min readReflow and Repaint: Why CSS Animations Get Janky
Understand browser rendering steps, reflow, repaint, compositing, and why transform and opacity are usually better animation targets than width, height, top, or left.
Subscribe to FreeMac
Weekly picks: free Mac software reviews, trusted source updates, alternatives, and low-friction guides.