.agents/skills/tailwind-css-rules/SKILL.md
@apply - Use CSS variables, the --spacing() function, or framework components insteadnpx @tailwindcss/upgrade@latest for both major and minor updates| ❌ Deprecated | ✅ Replacement |
|---|---|
bg-opacity-* | Use opacity modifiers like bg-black/50 |
text-opacity-* | Use opacity modifiers like text-black/50 |
border-opacity-* | Use opacity modifiers like border-black/50 |
divide-opacity-* | Use opacity modifiers like divide-black/50 |
ring-opacity-* | Use opacity modifiers like ring-black/50 |
placeholder-opacity-* | Use opacity modifiers like placeholder-black/50 |
flex-shrink-* | shrink-* |
flex-grow-* | grow-* |
overflow-ellipsis | text-ellipsis |
decoration-slice | box-decoration-slice |
decoration-clone | box-decoration-clone |
Use the v4 name when migrating code that still carries Tailwind v3 semantics. Do not blanket-replace existing v4 classes: classes such as rounded-sm, shadow-sm, ring-1, and ring-2 are valid in this codebase when they intentionally represent the current design scale.
| ❌ v3 pattern | ✅ v4 pattern |
|---|---|
bg-gradient-* | bg-linear-* |
| old shadow scale | verify against the current Tailwind/design scale |
| old blur scale | verify against the current Tailwind/design scale |
| old radius scale | use the Dify radius token mapping when applicable |
outline-none | outline-hidden |
bare ring utility | use an explicit ring width such as ring-1/ring-2/ring-3 |
For Figma radius tokens, follow packages/dify-ui/AGENTS.md. For example, --radius/xs maps to rounded-sm; do not rewrite it to rounded-xs.
Gap provides consistent spacing without edge cases (no extra space on last items). It's cleaner and more maintainable than margins on children.
<!-- ❌ Don't do this -->
<div class="flex">
<div class="mr-4">Item 1</div>
<div class="mr-4">Item 2</div>
<div>Item 3</div>
<!-- No margin on last -->
</div>
<!-- ✅ Do this instead -->
<div class="flex gap-4">
<div>Item 1</div>
<div>Item 2</div>
<div>Item 3</div>
</div>
space-x-* or space-y-* in flex/grid layouts - always use gap<!-- ❌ Avoid space utilities in flex containers -->
<div class="flex flex-wrap space-x-4">
<!-- Space utilities break with wrapped items -->
</div>
<!-- ✅ Use gap for consistent spacing -->
<div class="flex flex-wrap gap-4">
<!-- Gap works perfectly with wrapping -->
</div>
min-h-dvh instead of min-h-screen - min-h-screen is buggy on mobile Safarisize-* utilities over separate w-* and h-* when setting equal dimensionsmax-w-2xs over max-w-72)leading-* classes - Always use line height modifiers with text size<!-- ❌ Don't do this -->
<p class="text-base leading-7">Text with separate line height</p>
<p class="text-lg leading-relaxed">Text with named line height</p>
<!-- ✅ Do this instead -->
<p class="text-base/7">Text with line height modifier</p>
<p class="text-lg/8">Text with specific line height</p>
Be precise with font sizes - know the actual pixel values:
text-xs = 12pxtext-sm = 14pxtext-base = 16pxtext-lg = 18pxtext-xl = 20pxNever use bg-opacity-*, text-opacity-*, etc. - use the opacity modifier syntax:
<!-- ❌ Don't do this -->
<div class="bg-red-500 bg-opacity-60">Old opacity syntax</div>
<!-- ✅ Do this instead -->
<div class="bg-red-500/60">Modern opacity syntax</div>
<!-- ❌ Redundant breakpoint classes -->
<div class="px-4 md:px-4 lg:px-4">
<!-- md:px-4 and lg:px-4 are redundant -->
</div>
<!-- ✅ Efficient breakpoint usage -->
<div class="px-4 lg:px-8">
<!-- Only specify when value changes -->
</div>
dark: variant patterndark: variant comes before other variants<!-- ✅ Correct dark mode pattern -->
<div class="bg-white text-black dark:bg-black dark:text-white">
<button class="hover:bg-gray-100 dark:hover:bg-gray-800">Click me</button>
</div>
bg-linear-* instead of bg-gradient-* utilities - The gradient utilities were renamed in v4bg-radial or bg-radial-[<position>] to create radial gradientsbg-conic or bg-conic-* to create conic gradients<!-- ✅ Use the new gradient utilities -->
<div class="h-14 bg-linear-to-br from-violet-500 to-fuchsia-500"></div>
<div
class="size-18 bg-radial-[at_50%_75%] from-sky-200 via-blue-400 to-indigo-900 to-90%"
></div>
<div
class="size-24 bg-conic-180 from-indigo-600 via-indigo-50 to-indigo-600"
></div>
<!-- ❌ Do not use bg-gradient-* utilities -->
<div class="h-14 bg-gradient-to-br from-violet-500 to-fuchsia-500"></div>
Tailwind CSS v4 exposes all theme values as CSS variables:
/* Access colors, and other theme values */
.custom-element {
background: var(--color-red-500);
border-radius: var(--radius-lg);
}
--spacing() FunctionUse the dedicated --spacing() function for spacing calculations:
.custom-class {
margin-top: calc(100vh - --spacing(16));
}
Use CSS to extend theme values:
@import "tailwindcss";
@theme {
--color-mint-500: oklch(0.72 0.11 178);
}
<div class="bg-mint-500">
<!-- ... -->
</div>
Use the @container class and size variants:
<article class="@container">
<div class="flex flex-col @md:flex-row @lg:gap-8">
<div class="mt-4 @md:mt-0">
<!-- Content adapts to container size -->
</div>
</div>
</article>
Use container-based units like cqw for responsive sizing:
<div class="@container">
<h1 class="text-[50cqw]">Responsive to container width</h1>
</div>
Use text-shadow-* utilities from text-shadow-2xs to text-shadow-lg:
<!-- ✅ Text shadow examples -->
<h1 class="text-shadow-lg">Large shadow</h1>
<p class="text-shadow-sm/50">Small shadow with opacity</p>
Use the new composable mask utilities for image and gradient masks:
<!-- ✅ Linear gradient masks on specific sides -->
<div class="mask-t-from-50%">Top fade</div>
<div class="mask-b-from-20% mask-b-to-80%">Bottom gradient</div>
<div class="mask-linear-from-white mask-linear-to-black/60">
Fade from white to black
</div>
<!-- ✅ Radial gradient masks -->
<div class="mask-radial-[100%_100%] mask-radial-from-75% mask-radial-at-left">
Radial mask
</div>
Don't add utilities to parents that you override in children:
<!-- ❌ Avoid this pattern -->
<div class="text-center">
<h1>Centered Heading</h1>
<div class="text-left">Left-aligned content</div>
</div>
<!-- ✅ Better approach -->
<div>
<h1 class="text-center">Centered Heading</h1>
<div>Left-aligned content</div>
</div>
/* ✅ Good nesting - parent has styles */
.card {
padding: --spacing(4);
> .card-title {
font-weight: bold;
}
}
/* ❌ Avoid empty parents */
ul {
> li {
/* Parent has no styles */
}
}
/opacity syntax like bg-red-500/60text-sm/6ml-4 over ml-[16px])