-
-
Notifications
You must be signed in to change notification settings - Fork 4.9k
Description
What version of Tailwind CSS are you using?
v4.1.18
What build tool (or framework if it abstracts the build tool) are you using?
@tailwindcss/cli 4.1.18
What version of Node.js are you using?
v22.x
What browser are you using?
N/A (build-time issue)
What operating system are you using?
macOS
Reproduction URL
Minimal reproduction:
input.css:
@import "tailwindcss";
@utility ui/button {
display: inline-flex;
background: blue;
}
@utility ui/button/sm {
display: inline-flex;
background: blue;
font-size: 12px;
}index.html:
<!DOCTYPE html>
<html>
<body>
<!-- Custom utility with single slash - WORKS -->
<button class="ui/button">Single Slash</button>
<!-- Custom utility with double slash - DOES NOT WORK -->
<button class="ui/button/sm">Double Slash</button>
</body>
</html>Build:
npx @tailwindcss/cli -i input.css -o output.cssDescribe your issue
Custom utilities defined with @utility containing multiple forward slashes (e.g., ui/button/sm) are not detected by the content scanner, even though the CSS definition is valid and works correctly in Tailwind Play.
Note: This does NOT affect Tailwind's built-in variant/modifier syntax. For example, group-hover/item:bg-red-500/20 works correctly because the variant machine handles group-hover/item: separately from the utility bg-red-500/20.
Expected behavior:
Both utilities should be present in output.css:
.ui\/button✓.ui\/button\/sm✓
Actual behavior:
Only single-slash utility is present:
.ui\/button✓.ui\/button\/sm✗ MISSING
Note
Such utility definitions do work in play.tailwindcss.com, likely because the playground processes CSS and HTML together in-browser without the file scanner. The compiler already knows about all @utility definitions when it processes the HTML.
In contrast, the CLI/Vite plugin uses the oxide scanner to extract candidates from source files before knowing what utilities exist. The UtilityMachine in @tailwindcss/oxide interprets / as a modifier separator (for opacity modifiers like bg-red-500/20). When it encounters a second / in a utility name, it treats this as "modifier followed by modifier" which is invalid, and rejects the entire candidate.