Skip to content

fix(colormin,minify-gradients): replace colord with @colordx/core, fix lossy color minification (#1515)#1755

Merged
ludofischer merged 4 commits intocssnano:masterfrom
dkryaklin:fix/replace-colord-with-colordx
Mar 30, 2026
Merged

fix(colormin,minify-gradients): replace colord with @colordx/core, fix lossy color minification (#1515)#1755
ludofischer merged 4 commits intocssnano:masterfrom
dkryaklin:fix/replace-colord-with-colordx

Conversation

@dkryaklin
Copy link
Copy Markdown
Contributor

@dkryaklin dkryaklin commented Mar 25, 2026

Problem

postcss-colormin used colord to minify CSS color values. colord rounds color values to integers at parse time, so HSL conversions accumulate rounding error — making some RGB → HSL round-trips lossy:

rgba(221, 221, 221, 0.5) → hsla(0,0%,87%,.5)
# round-trip back: rgb(222, 222, 222) ≠ rgb(221, 221, 221) ❌

This caused visible color seams at image/UI boundaries.

Real-world impact:

colord also returns isValid: false for oklch(), oklab(), hwb(), and other modern CSS color formats, so gradient color stops using these formats were not recognised by postcss-minify-gradients.

colord has not received any updates since August 2022.

Solution

Replace colord with @colordx/core, its actively maintained successor with an intentionally compatible API.

colordx stores color values as floats internally — no rounding at parse time. This preserves exact precision through conversions so the minifier always picks the shortest truly lossless representation:

/* With colord (integer rounding): */
rgba(221, 221, 221, 0.5) → hsla(0,0%,87%,.5)        /* shorter but lossy ❌ */

/* With colordx (float storage): */
rgba(221, 221, 221, 0.5) → hsla(0,0%,86.7%,.5)      /* shorter and lossless ✅ */
rgba(50%, 50%, 50%, 0.5) → hsla(0,0%,50%,.5)        /* shorter and lossless ✅ */

With this fix, Next.js could re-enable colormin and recover the minification savings they gave up.

Changes

  • postcss-colormin: swap colord@colordx/core@^2.0.1
  • postcss-minify-gradients: swap colord@colordx/core@^2.0.1

Additional improvements

  • oklch(), oklab(), and hwb() values within the sRGB gamut are now correctly minified by postcss-colormin (previously passed through unchanged)
  • Modern CSS color formats are now correctly recognised as valid gradient color stops in postcss-minify-gradients

Testing

Fixes #1515

@ludofischer
Copy link
Copy Markdown
Collaborator

Seems TypeScript cannot see the types from colordx

@ludofischer
Copy link
Copy Markdown
Collaborator

I've updated to the latest TypeScript and changed module and moduleResolution to nodenext as the error message says, but there is still a typing error. Could someone else take a look?

@dkryaklin
Copy link
Copy Markdown
Contributor Author

Seems TypeScript cannot see the types from colordx

I'll check on my side

@dkryaklin dkryaklin force-pushed the fix/replace-colord-with-colordx branch 3 times, most recently from 650f084 to e6f0594 Compare March 26, 2026 23:17
@dkryaklin dkryaklin force-pushed the fix/replace-colord-with-colordx branch from e6f0594 to cbac5e6 Compare March 26, 2026 23:20
@ludofischer
Copy link
Copy Markdown
Collaborator

Now the test is probably failing because the color minification output is different in the integration tests.

@dkryaklin
Copy link
Copy Markdown
Contributor Author

Now the test is probably failing because the color minification output is different in the integration tests.

Thanks. I've updated snapshots and added more tests to make sure there is no regression

ludofischer
ludofischer previously approved these changes Mar 29, 2026
"repository": "cssnano/cssnano",
"dependencies": {
"colord": "^2.9.3",
"@colordx/core": "^2.0.1",
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we upgrade to 4.x before merging?

@ludofischer
Copy link
Copy Markdown
Collaborator

If I upgrade to @colordx/core@4.1.1 two tests fail:

should minify hwb to hex
hould recognise all valid CSS color formats as color stops

@dkryaklin
Copy link
Copy Markdown
Contributor Author

If I upgrade to @colordx/core@4.1.1 two tests fail:

should minify hwb to hex
hould recognise all valid CSS color formats as color stops

Yes, I've pushed new commit. Basically, I moved some code in plugin to improve bundle size

@dkryaklin dkryaklin requested a review from ludofischer March 30, 2026 09:23
@codecov
Copy link
Copy Markdown

codecov bot commented Mar 30, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 98.82%. Comparing base (367f946) to head (b3a0e63).
⚠️ Report is 18 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #1755      +/-   ##
==========================================
- Coverage   98.83%   98.82%   -0.02%     
==========================================
  Files         124      124              
  Lines       10592    10776     +184     
  Branches       15       15              
==========================================
+ Hits        10469    10649     +180     
- Misses        123      127       +4     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@ludofischer ludofischer merged commit 5f64972 into cssnano:master Mar 30, 2026
14 of 15 checks passed
@dkryaklin dkryaklin deleted the fix/replace-colord-with-colordx branch March 30, 2026 10:05
@dkryaklin
Copy link
Copy Markdown
Contributor Author

@ludofischer thanks! When do you plan to release a new version?

@ludofischer
Copy link
Copy Markdown
Collaborator

@dkryaklin should be up at any moment now on npm

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.

[Bug]: colormin is lossy, colors in minified builds don't match development

3 participants