npx skills add ...
npx skills add ofershap/tailwind-best-practices --skill tailwind-best-practices
Stop your AI agent from generating Tailwind CSS v3 code. Rules for v4 syntax, CSS-first config, modern utility patterns, and common anti-patterns.
npx skills add ofershap/tailwind-best-practices --skill tailwind-best-practices
Use this skill when working with Tailwind CSS code. AI agents are trained on Tailwind v3 data and consistently generate outdated patterns - wrong config files, deprecated directives, removed utilities, and verbose class lists. This skill enforces Tailwind CSS v4 patterns.
Wrong (agents do this):
Correct:
Why: Tailwind v4 removed @tailwind directives entirely. Use a standard CSS @import
statement.
Wrong (agents do this):
Correct:
Why: Tailwind v4 uses CSS-first configuration with the @theme directive. No
tailwind.config.js needed for most projects.
Wrong (agents do this):
Correct:
Why: In v4, postcss-import and autoprefixer are handled automatically. The plugin is
@tailwindcss/postcss, not tailwindcss.
Wrong (agents do this):
Correct:
Why: The bg-opacity-*, text-opacity-*, border-opacity-*, and placeholder-opacity-*
utilities were removed in v4. Use the slash modifier syntax.
Wrong (agents do this):
Correct:
Why: Arbitrary values (bg-[#3b82f6]) should be rare. Define custom colors in @theme so
they're reusable and consistent.
Wrong (agents do this):
Correct (when sizing should be based on parent, not viewport):
Why: Tailwind v4 has built-in container query support. Use @container on the parent and
@sm:, @md:, @lg: variants on children for component-level responsive design.
Wrong (agents do this):
Correct:
Why: Tailwind v4 uses @utility directive instead of @layer utilities for custom utilities.
Wrong (agents do this):
Correct:
Why: The important option moved from config to the CSS import statement in v4.
Wrong (agents do this):
Correct:
Why: In v4, shadow-sm was renamed to shadow-xs, shadow to shadow-sm, blur-sm to
blur-xs, rounded-sm to rounded-xs, etc. The old -sm values now map to what was previously
the default.
Wrong (agents do this):
Correct:
Why: Tailwind v4 renamed bg-gradient-to-* to bg-linear-to-* and added support for other
gradient types like bg-conic-* and bg-radial-*.
Wrong (agents do this):
Correct:
Why: Tailwind v4 added the not-* variant for styling elements that do NOT match a condition.
Wrong (agents do this):
Correct:
Why: Tailwind v4 supports @starting-style via the starting: variant for CSS-only entry
animations without JavaScript.
@theme blocks@import "tailwindcss" as the single entry point@container + @md:) for component-level responsive designbg-blue-500/50, text-gray-900/75@utility for custom utilities, @variant for custom variantsbg-linear-to-* for gradients (not bg-gradient-to-*)tailwind.config.js unless you need JavaScript-based dynamic config@tailwind base/components/utilities - use @import "tailwindcss"bg-opacity-*, text-opacity-* - use slash modifier syntax@layer utilities for custom utilities - use @utilitybg-gradient-to-* - use bg-linear-to-*postcss-import or autoprefixer with v4 - they're built inshadow-sm when you mean the smallest shadow - it's now shadow-xs@import "tailwindcss";
@theme {
--color-brand: #3b82f6;
--spacing-18: 4.5rem;
}// postcss.config.mjs
export default {
plugins: {
"postcss-import": {},
tailwindcss: {},
autoprefixer: {},
},
};// postcss.config.mjs
export default {
plugins: {
"@tailwindcss/postcss": {},
},
};<div class="bg-red-500 bg-opacity-50">
<div class="text-blue-600 text-opacity-75"></div>
</div><div class="bg-red-500/50">
<div class="text-blue-600/75"></div>
</div><div class="bg-[#3b82f6]"></div>@theme {
--color-brand: #3b82f6;
}<div class="bg-brand"></div><div class="md:flex-row flex-col"></div><div class="@container">
<div class="flex flex-col @md:flex-row">
<!-- Responds to container width, not viewport -->
</div>
</div>@layer utilities {
.content-auto {
content-visibility: auto;
}
}@utility content-auto {
content-visibility: auto;
}// tailwind.config.js
module.exports = {
important: true,
};@import "tailwindcss" important;<div class="shadow-sm ring-1 ring-gray-900/5">
<div class="blur-sm">
<div class="rounded-sm"></div>
</div>
</div><div class="shadow-xs ring-1 ring-gray-900/5">
<div class="blur-xs">
<div class="rounded-xs"></div>
</div>
</div><div class="bg-gradient-to-r from-blue-500 to-purple-500"></div><div class="bg-linear-to-r from-blue-500 to-purple-500"></div><div class="hover:bg-blue-500">
<!-- No way to style non-hovered state specifically -->
</div><div class="not-hover:opacity-75 hover:opacity-100"></div>.modal {
opacity: 0;
transition: opacity 0.3s;
}
.modal.open {
opacity: 1;
}<div class="starting:opacity-0 opacity-100 transition-opacity duration-300"></div>