Bug
nitro build's CSS minifier strips whitespace inside quoted url() string values, including raw SVG data URIs. This silently breaks any inline SVG used in CSS (e.g. mask: url("data:image/svg+xml;utf8,<svg ...>...</svg>")), turning every icon based on this technique invisible in production. nitro dev does not minify, so the bug doesn't show up locally — only after deploy.
Reproduction
src/styles/main.css:
.icon {
width: 16px;
height: 16px;
display: inline-block;
background: currentColor;
-webkit-mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><circle cx='12' cy='12' r='10'/></svg>") center / contain no-repeat;
mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><circle cx='12' cy='12' r='10'/></svg>") center / contain no-repeat;
}
Then:
nitro build --no-fingerprint
Inspect the emitted CSS in build/assets/styles/main.css:
Expected (whitespace inside the quoted URL preserved):
.icon{...mask:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><circle cx='12' cy='12' r='10'/></svg>") center / contain no-repeat}
Actual (whitespace inside the quoted URL collapsed):
.icon{...mask:url("data:image/svg+xml;utf8,<svgxmlns='http://www.w3.org/2000/svg'viewBox='002424'fill='none'stroke='currentColor'stroke-width='2'stroke-linecap='round'stroke-linejoin='round'><circlecx='12'cy='12'r='10'/></svg>") center / contain no-repeat}
Note: <svg xmlns= → <svgxmlns= (broken element), viewBox='0 0 24 24' → viewBox='002424' (broken attribute), <circle cx= → <circlecx= (broken element). The browser cannot parse this SVG, so the mask is empty and the icon doesn't render. No console error.
Real impact
I hit this on a production deploy (fridaynight.wiki). Eight different icons across the site were invisible after deploy, including a "Buy me a coffee" button, the search-input magnifier, type-chip icons on every card, and the prev/next pager arrows. All were perfectly visible in nitro dev.
The failure mode is silent: no warning, no error, no broken layout — just missing icons that pass every test except a visual one.
Workaround
URL-encode the SVG payload so the troublesome characters (spaces, <, >) become %20/%3C/%3E. The minifier won't touch them after that:
mask: url("data:image/svg+xml;utf8,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'...%3E");
Or use base64:
mask: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0...");
Both work, both are uglier than raw inline SVG.
Suggested fix
The CSS minifier must not touch string contents. The CSS spec is clear: the value inside the quotes of url("...") is a string token — it is opaque, and minifiers should preserve it byte-for-byte. The same goes for any other quoted string in CSS (content:, font-family, --var: "...", etc.).
A simple guard: when tokenizing CSS, recognize url( followed by a quote, scan to the matching close-quote, and emit those bytes verbatim — never collapse whitespace inside them.
If switching minifiers, libraries that get this right include lightningcss, cssnano (with default config), and csso. Whatever's currently in nitro build is collapsing inside strings, which is incorrect.
Environment
- nitro-cli (current as of 2026-04-19)
- macOS, Python 3.12
- Triggered by both local
nitro build --no-fingerprint and the same command run in GitHub Actions deploying to Cloudflare Pages.
Bug
nitro build's CSS minifier strips whitespace inside quotedurl()string values, including raw SVG data URIs. This silently breaks any inline SVG used in CSS (e.g.mask: url("data:image/svg+xml;utf8,<svg ...>...</svg>")), turning every icon based on this technique invisible in production.nitro devdoes not minify, so the bug doesn't show up locally — only after deploy.Reproduction
src/styles/main.css:Then:
Inspect the emitted CSS in
build/assets/styles/main.css:Expected (whitespace inside the quoted URL preserved):
Actual (whitespace inside the quoted URL collapsed):
Note:
<svg xmlns=→<svgxmlns=(broken element),viewBox='0 0 24 24'→viewBox='002424'(broken attribute),<circle cx=→<circlecx=(broken element). The browser cannot parse this SVG, so the mask is empty and the icon doesn't render. No console error.Real impact
I hit this on a production deploy (
fridaynight.wiki). Eight different icons across the site were invisible after deploy, including a "Buy me a coffee" button, the search-input magnifier, type-chip icons on every card, and the prev/next pager arrows. All were perfectly visible innitro dev.The failure mode is silent: no warning, no error, no broken layout — just missing icons that pass every test except a visual one.
Workaround
URL-encode the SVG payload so the troublesome characters (spaces,
<,>) become%20/%3C/%3E. The minifier won't touch them after that:Or use base64:
Both work, both are uglier than raw inline SVG.
Suggested fix
The CSS minifier must not touch string contents. The CSS spec is clear: the value inside the quotes of
url("...")is a string token — it is opaque, and minifiers should preserve it byte-for-byte. The same goes for any other quoted string in CSS (content:,font-family,--var: "...", etc.).A simple guard: when tokenizing CSS, recognize
url(followed by a quote, scan to the matching close-quote, and emit those bytes verbatim — never collapse whitespace inside them.If switching minifiers, libraries that get this right include
lightningcss,cssnano(with default config), andcsso. Whatever's currently innitro buildis collapsing inside strings, which is incorrect.Environment
nitro build --no-fingerprintand the same command run in GitHub Actions deploying to Cloudflare Pages.