Skip to main content
Blog/September 18, 2026

Yumma CSS 4.0

New colon syntax. Layered output, codemod & more.

Yumma CSS 4.0

Every class name changes in this release. A utility now separates its property from its value the way CSS does, with a colon.

Use Colon Syntax

Here's an example of the new colon syntax:

<div className="d-f jc-c ai-c"></div><div className="d:f jc:c ai:c"></div>

Colons separate a property from its value, while the minus sign (-) divides a value. If you're using a shade like red-5, for example, it keeps its dash because red-5 is one value with a step, not two levels of nesting.

<div className="bg:gray-1 c:blue-4"></div>

Variants keep their prefix position, so a condition still reads before the thing it conditions & h: stays greppable.

<div className="@sm:h:bg:gray-1"></div>

Negative Values

m--4 was a parser artifact leaking into the API. The double dash meant nothing to a reader; it was there so the parser could tell a sign from a separator.

<div className="m--4"></div><div className="m:-4"></div>

A negative is also refused where the property cannot take one. m:-4 is a margin, w:-1 is not a class.

When a Variant & a Utility Share a Prefix

Giving both the same separator makes ten variant prefixes collide with a utility prefix. h: is :hover, & it is also height.

A variant is peeled only when what remains is not itself a utility, so all three of these read the way you would expect.

<div className="h:4"></div>
<div className="h:m:4"></div>
<div className="h:h:4"></div>

A height, a margin under :hover, & a height under :hover. One splitter in @yummacss/core decides this, & every package that reads a class name reads that splitter.

Migrating

There is no compatibility mode. 3.x class names stop working, so the codemod is NOT optional.

pnpm dlx yummacss migrate --dry-run

It reads your yumma.config.mjs, so custom colors, custom breakpoints & a configured prefix all migrate with everything else. What it cannot rewrite is a class built at runtime, so it names every one it left alone & why.

Scanned 345 files and rewrote 3081 classes in 111 files.

Left alone (2):
 "bg-${tone}-5" - built at runtime
 "docs-card" - not a known utility

Those are yours. A class assembled from a variable was never visible to the scanner either, so if it rendered before, it was in your safelist, & the safelist entry needs the same rewrite.

Where a class is simply wrong, the unknown-utility warning folds both separators before it measures distance, so a class typed the old way still gets its new answer.

"gap-4" - did you mean "g:4"?

New Variants

@xs: is a breakpoint at 32rem. Every t-shirt width alias now names a query that exists, rather than starting at @sm: with nothing below it.

<div className="d:b @xs:d:f"></div>

@prm: applies a utility under prefers-reduced-motion, so an animation is switched off in a class rather than in a stylesheet sitting beside it.

<div className="tp:c tdu:200 @prm:tp:none"></div>

Spelled-Out Values

none & auto are never abbreviated, which two utilities did not follow. tt-n read as nothing at all. This is now amended.

<p className="tt-n"></p><p className="tt:none"></p><table className="tl-a"></table><table className="tl:auto"></table>

Every other value on both utilities is unchanged, & the codemod rewrites these two.

Renamed to @yummacss/lint

@yummacss/canon is now @yummacss/lint, & its binary is yummacss-lint. Nothing about the API changed.

pnpm dlx @yummacss/canonpnpm dlx @yummacss/lint

Smaller Changes

tp:c now transitions outline-color along with the other colors, so a focus outline fades with the rest of the treatment.

merge reads the new syntax. It split the variant at the last colon & cut the prefix at a dash, which made it a no-op on every 4.0 class.

The full list is in the changelog.