tailwind-css
Skill1 starsChanged 8 months agoApache-2.0View on GitHub
Writes and reviews Tailwind CSS v4 code with the CSS-first setup (@import, @theme, @utility, @plugin, @source), the cn() class merge helper, mobile-first responsive design, class-based dark mode, built-in container queries, and variant-driven components. Also migrates v3 projects to v4. Use when styling with Tailwind, fixing classes that do not apply or conflict, setting up or upgrading Tailwind, adding design tokens or dark mode, or building reusable Tailwind components.
- Installs packages
We split this skill into the rules it gives an agent
12 rules. 0 are common, 2 are distinctive, and 10 are very specific to this project.
0
Common
Most of the 8 edited versions we read keep these.
2
Distinctive
This author's own choices. Worth a look.
10
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 110
Add or change breakpoints with --breakpoint-* in @theme (see Core Configuration).
- Very specific: line 130
Put or remove the dark class on <html> from a small script or a theme library, and add suppressHydrationWarning to <html> if the class is …
- Very specific: line 200
Always pair motion with motion-reduce: so users who ask for less motion get none.
- Very specific: line 272
Keep a visible focus indicator.
- Very specific: line 286
Check the version: read package.json and look for tailwind.config.* and @tailwind directives.
- Distinctive: line 293
Build: run the project build and check the CSS size.
- Very specific: line 300
If the file lives in an ignored path (node_modules, .gitignore), add @source.
- Distinctive: line 302
Check for specificity: a later or more specific rule can override the utility.
- Very specific: line 305
Use complete class strings in a lookup object, never text-${color}-500.
- Very specific: line 309
Default is prefers-color-scheme.
- Very specific: line 310
Check the <html> element actually gets the dark class.
- Very specific: line 311
Check the dark: variants sit on the affected elements.
“Common” is measured: kept by at least 6 in 10 of the 8 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Tailwind CSS Skill
This skill targets Tailwind CSS v4. In v4 the configuration lives in CSS, not in tailwind.config.ts. If the project still has a tailwind.config.* file, it is on v3 or it loads the file with @config. Check package.json before you choose syntax.
Longer examples: references/components.md (variant components and form inputs) and references/v3-to-v4.md (migration and renamed utilities).
Core Configuration (v4)
BAD: v3 directives and a JS config for tokens
/* styles/globals.css */
@tailwind base;
@tailwind components;
@tailwind utilities;// tailwind.config.ts
export default {
content: ['./src/**/*.{js,ts,jsx,tsx}'],
theme: { extend: { colors: { brand: { 500: '#3b82f6' } } } },
};GOOD: one CSS file, tokens in @theme
/* styles/globals.css */
@import "tailwindcss";
@theme {
--color-brand-50: oklch(0.97 0.02 240);
--color-brand-500: oklch(0.62 0.19 260);
--color-brand-900: oklch(0.3 0.1 265);
--font-display: "Inter", sans-serif;
--breakpoint-xs: 475px;
}Every @theme variable in a utility namespace becomes a utility (bg-brand-500, font-display, xs:flex) and a CSS variable (var(--color-brand-500)). Spacing needs no tokens: p-18 works because spacing is a multiple of one base unit. Do not mix inline style={{}} with Tailwind for values the tokens already cover.
Install (build tool plugin, no content array needed):
npm install tailwindcss @tailwindcss/vite # Vite
npm install tailwindcss @tailwindcss/postcss # Next.js and other PostCSS setupscn() Utility Pattern
BAD: string concatenation, conflicting classes are not resolved
export function Card({ className }: { className?: string }) {
// p-4 and p-8 both apply, and CSS source order decides the winner
return <div className={`p-4 rounded-lg bg-white ${className}`} />;
}
// <Card className="p-8 bg-blue-50" />GOOD: clsx plus tailwind-merge, the last class wins
// lib/cn.ts
import { clsx, type ClassValue } from 'clsx';
import { twMerge } from 'tailwind-merge';
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
}
// components/Card.tsx
import { cn } from '@/lib/cn';
interface CardProps {
className?: string;
variant?: 'default' | 'outlined';
}
export function Card({ className, variant = 'default' }: CardProps) {
return (
<div
className={cn(
'p-4 rounded-lg',
variant === 'default' && 'bg-white shadow-sm',
variant === 'outlined' && 'border border-gray-300',
className
)}
/>
);
}
// <Card className="p-8 bg-blue-50" /> => p-8 and bg-blue-50 override correctlyResponsive Design Patterns
Unprefixed classes are the mobile base. Each prefix (sm:, md:, lg:) means "from this width up".
BAD: desktop-first thinking, the base class is overridden by nothing
<div className="grid-cols-4 md:grid-cols-2 sm:grid-cols-1" />GOOD: mobile-first progressive enhancement
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4" />Add or change breakpoints with --breakpoint-* in @theme (see Core Configuration). Use max-md: only for a rule that must stop at a width.
Dark Mode Implementation
In v4 the dark: variant follows prefers-color-scheme by default. For a manual toggle, override the variant in CSS.
BAD: branching class strings in JS
<div className={isDark ? 'bg-gray-900 text-white' : 'bg-white text-gray-900'} />GOOD: dark: variants, with a class-based switch when you need a toggle
@import "tailwindcss";
@custom-variant dark (&:where(.dark, .dark *));<div className="bg-white text-gray-900 dark:bg-gray-900 dark:text-white">Content</div>Put or remove the dark class on <html> from a small script or a theme library, and add suppressHydrationWarning to <html> if the class is set before hydration. Do not hardcode className="dark" in the layout: that locks dark mode on.
Custom Utilities and Plugins
BAD: the same long class list copied across the code
<div className="backdrop-blur-md bg-white/10 border border-white/20 rounded-lg" />
// repeated in 20 placesGOOD: @utility for a reusable rule, @plugin for a package plugin
@import "tailwindcss";
@plugin "@tailwindcss/typography";
@plugin "@tailwindcss/forms";
@utility glass {
backdrop-filter: blur(12px);
background-color: rgb(255 255 255 / 0.1);
border: 1px solid rgb(255 255 255 / 0.2);
}<div className="glass rounded-lg shadow-xl">Content</div>A custom @utility works with every variant (hover:glass, md:glass). To keep an existing JS plugin or config, load it with @config "../tailwind.config.ts"; or @plugin "./my-plugin.js";.
Anti-Pattern: @apply Overuse
BAD: a CSS file full of @apply
.button { @apply px-4 py-2 bg-blue-500 text-white rounded-sm hover:bg-blue-600; }
.card { @apply p-6 bg-white rounded-lg shadow-md; }
.input { @apply w-full px-3 py-2 border border-gray-300 rounded-sm; }
/* Loses composability and duplicates what a component does better */GOOD: a component that owns its classes
Wrap the classes in a component and use cva for variants. The full Button and Input examples are in references/components.md. Use @apply only for styles you cannot put in markup, such as third-party HTML you do not control.
Animation Utilities
BAD: a loose keyframe and class that bypass the theme
@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
.fade-in { animation: fadeIn 0.5s ease-in; }GOOD: keyframes and the animation token inside @theme
@theme {
--animate-fade-in: fade-in 0.5s ease-out;
--animate-shimmer: shimmer 2s infinite linear;
@keyframes fade-in {
0% { opacity: 0; transform: translateY(10px); }
100% { opacity: 1; transform: translateY(0); }
}
@keyframes shimmer {
0% { background-position: -200% 0; }
100% { background-position: 200% 0; }
}
}<div className="animate-fade-in motion-reduce:animate-none">Content</div>Always pair motion with motion-reduce: so users who ask for less motion get none.
Performance: Content Detection and Dynamic Classes
v4 finds source files on its own. It respects .gitignore and skips node_modules and binary files. You do not write a content array.
BAD: building class names from fragments
// Tailwind scans text, so it never sees "bg-red-500" here
<div className={`bg-${color}-500`} />GOOD: complete class names in a lookup, and @source for extra paths
const colorMap = {
error: 'bg-red-500',
success: 'bg-green-500',
info: 'bg-blue-500',
} as const;
export function Alert({ type }: { type: keyof typeof colorMap }) {
return <div className={colorMap[type]}>Alert</div>;
}@import "tailwindcss";
@source "../node_modules/@my-company/ui"; /* a package that is ignored by default */
@source inline("bg-{red,green,blue}-{400,500,600}"); /* classes that only exist at runtime (v4.1+) */Container Queries
Container queries are built in to v4. No plugin is needed.
BAD: viewport breakpoints for a component that lives in a narrow sidebar
<div className="p-4 md:p-6 lg:p-8">
<h2 className="text-lg md:text-xl lg:text-2xl">Title</h2>
</div>GOOD: the component responds to its own container
<div className="@container">
<div className="p-4 @md:p-6 @lg:p-8">
<h2 className="text-lg @md:text-xl @lg:text-2xl">Title</h2>
</div>
</div>Arbitrary Values and CSS Variables
BAD: magic numbers in class names
<section className="h-[calc(100vh-64px)] pt-[72px]">Content</section>GOOD: named variables, referenced with the shorthand
@theme {
--header-height: 4rem;
--content-padding: 4.5rem;
}<section className="h-[calc(100vh-var(--header-height))] pt-(--content-padding)">Content</section>pt-(--content-padding) is the v4 shorthand for pt-[var(--content-padding)].
Focus States
Keep a visible focus indicator. In v4, outline-none removes the outline completely. Use outline-hidden when you replace it with a ring, and prefer focus-visible: so the ring shows for keyboard users.
BAD: focus removed and nothing replaces it
<input className="focus:outline-none" />GOOD: the ring replaces the outline
<input className="rounded-lg border px-3 py-2 focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-blue-500" />Workflow: Apply This Skill
- Check the version: read
package.jsonand look fortailwind.config.*and@tailwinddirectives. Use v3 syntax only when the project is on v3. - Audit className usage: find string concatenation that should use
cn(). - Check @apply usage: replace it with components or
@utility. - Verify tokens: colors, spacing and breakpoints live in
@theme, not in magic values. - Test dark mode: confirm
dark:variants work and the toggle (if any) sets thedarkclass. - Review responsive design: mobile-first, container queries for reusable components.
- Check dynamic classes: complete class names only, or
@source inline(...). - Build: run the project build and check the CSS size.
Common Fixes
Fix: Tailwind classes not applying
- Confirm the CSS file has
@import "tailwindcss";and is imported once by the app. - Confirm the build plugin (
@tailwindcss/viteor@tailwindcss/postcss) is installed and registered. - If the file lives in an ignored path (
node_modules,.gitignore), add@source. - Clear the framework cache, for example delete the
.nextfolder. - Check for specificity: a later or more specific rule can override the utility.
Fix: Dynamic classes not working
- Use complete class strings in a lookup object, never
text-${color}-500. - For classes that only exist at runtime, use
@source inline(...).
Fix: Dark mode not switching
- Default is
prefers-color-scheme. For a toggle, add the@custom-variant darkline. - Check the
<html>element actually gets thedarkclass. - Check the
dark:variants sit on the affected elements.
Other versions8 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 8
- cohen-liel/hivemind★ 108same name
- PaulRBerg/agent-skills★ 104same name
- sablier-labs/agent-skills★ 9same name
- PaulRBerg/dot-agents★ 6same name
- nek1987/auto-agent-harness★ 4same name
- TeddyAlbina/skills★ 2same name
- afk-agents/agentic-toolkit★ 1same name
- blakee-marcus/tailwindcss-skill★ 0same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository21 other files it gives its agents.
- accessibility-wcagSkill
- api-designSkill
- bugbounty-reportSkill
- ci-cd-pipelinesSkill
- codebase-analysisSkill
- database-designSkill
- design-docSkill
- docker-kubernetesSkill
- git-workflowSkill
- go-devSkill
- i18n-localizationSkill
- llm-integrationSkill
- nextjs-16Skill
- oauth-authSkill
- performance-optimizationSkill
- python-best-practicesSkill
- scraping-automationSkill
- security-reviewSkill
- seo-metaSkill
- testingSkill
- ts-devSkill
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
Reviews can't be read right now.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

