Skip to content

Fix 0px being converted to unitless 0 and breaking calc calculations#121

Open
philwolstenholme wants to merge 2 commits into
cuth:masterfrom
philwolstenholme:claude/friendly-knuth-HA01Z
Open

Fix 0px being converted to unitless 0 and breaking calc calculations#121
philwolstenholme wants to merge 2 commits into
cuth:masterfrom
philwolstenholme:claude/friendly-knuth-HA01Z

Conversation

@philwolstenholme
Copy link
Copy Markdown

@philwolstenholme philwolstenholme commented May 25, 2026

This MR preserves 0px values instead of converting to unitless 0.

Sorry for the extra noise on the diff, I wanted to only commit my change and the new test, but Husky ran lint-staged which ran Prettier, which made quite a few unrelated formatting changes.

Possibly related: I noticed this test was failing on master without any changes having been made:

Failures:

  1) pxtorem should remain unitless if 0
   Message:
     Expected '.rule { font-size: 0rem; font-size: 0; }' to be '.rule { font-size: 0px; font-size: 0; }'.
   Stacktrace:
     Error: Expected '.rule { font-size: 0rem; font-size: 0; }' to be '.rule { font-size: 0px; font-size: 0; }'.
    at jasmine.Spec.<anonymous> (/Users/phil/Sites/postcss-pxtorem/spec/pxtorem-spec.js:85:23)

Finished in 0.007 seconds
44 tests, 45 assertions, 1 failure, 0 skipped

Why

When a CSS custom property with a 0px value was processed — for example from Tailwind CSS:

:root { --tw-ring-offset-width: 0px; }

the plugin was rewriting it to:

:root { --tw-ring-offset-width: 0; }

This breaks any downstream calc() expression that uses the variable, such as:

box-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);

CSS calc() requires all operands to have compatible types. A unitless 0 is a <number>, not a <length>, so calc(1px + 0) is invalid and browsers will discard the entire declaration. calc(1px + 0px) is valid.

Fix

Skip conversion entirely when the pixel value is zero. Converting 0px to 0rem provides no benefit, and converting it to a bare 0 is incorrect for the reason above.

 const pixels = parseFloat($1);
+if (pixels === 0) return m;
 if (pixels < minPixelValue) return m;

Workaround if this isn't merged

For anyone else with this issue, a workaround is to use the existing minPixelValue config option to make the plugin avoid converting values less than 1:

minPixelValue: 1,

Tests

Added a regression test covering the CSS custom property case. This test might be a bit too specific but it is based on a real world test case I suppose.

All tests are green:

❯ npm run test

> postcss-pxtorem@6.1.0 test
> jasmine-node spec

.............................................

Finished in 0.005 seconds
45 tests, 46 assertions, 0 failures, 0 skipped

AI disclaimer

This code comes from a Claude Code session.

Zero pixel values (0px) are semantically equivalent to 0rem and 0
in CSS, so converting them provides no benefit. More importantly,
converting 0px to a unitless 0 breaks CSS custom properties such as
Tailwind's --tw-ring-offset-width when they are used in contexts
that require units.

https://claude.ai/code/session_01RNkSDiLSYfS94qrFXguRF2
@philwolstenholme philwolstenholme changed the title Fix 0px being converted to unitless 0 or 0rem Fix 0px being converted to unitless 0 and breaking calc calculations May 25, 2026
More precise than * since the test is specifically about CSS custom
properties being processed and zero pixel values being preserved.

https://claude.ai/code/session_01RNkSDiLSYfS94qrFXguRF2
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants