Skip to content

Content Scanner ignores classes with 2 slashes (e.g. ui/button/sm) #19505

@fractaledmind

Description

@fractaledmind

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.css

Describe 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\/smMISSING

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.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions