[Feature Request] Add unused css var removal (postcss-unused-var) to discardUnused or a new transform
Is your feature request related to a problem? Please describe.
I sometimes include "libraries" declaring a bunch of css variables in the :root. When compiling with css nano, they end up in the bundle even though they are not used.
Describe the solution you'd like
I see two solutions to this issue:
- extend
discardUnusedto take care of those var(--my-var) not found in the rest of the file - add a separate
discardUnusedVariablesoptimisation with defaultunsafe
It is an unsafe transform because un-used variables from :root can be used in other stylesheets on a website but if you only have one stylesheet and you know this is a problem, you'd definetely want to get rid of these extra lines of code.
Additional context
Some prior work seems to be done here: https://github.com/Plugin-contrib/postcss-unused-var
Not sure why it has been archived and if there are concern using this approach.
Are you willing to work on this ?
I could but it looks like it is a matter of moving postcss-unused-var here and modifying it to allow removing the un-used variables from :root as well?
Removing CSS variables is not safe, we try to avoid all unsafe actions
Thanks for the issue.
As mentioned by @evilebottnawi , CSS variables are hoisted across CSS files as well.
and those which are declared in declaration like h1{--var1: red}, this var1 can be used outside as well.
That was the reason for archiving postcss-unused-var cause it can lead to un-safe transformation.
I don't know what is exactly cssnano policy re unsafe transform but I see there are currently 4 available: discardunused, mergeidents, reduceidents and zindex. Assuming users that opt in for unsafe transforms know what they are doing, would this behaviour still be too unsafe for cssnano?
Removal of css variables can be un-safe as they are hoisted.
postcss-unused-vars was doing the following thing
Input
a {
--var1: red;
--var2: green;
color: var(--var1);
}
⬇️
Output
a {
--var1: red;
color: var(--var1);
}
But var2 could be used like this as well
a {
--var1: red;
--var2: green;
color: var(--var1);
}
p{
color: var(--var2);
}
This will be transformed to
a {
--var1: red;
color: var(--var1);
}
p{
color: var(--var2);
}
This is un-safe.
I only have one output CSS file. There is not going to be more CSS files.
I want to remove all --properties that are not accessed by a single var() in the whole CSS file. This is completely safe, and I should be able to do this if I know what I'm doing.
Use case: I have theme colors generator that creates a lot of properties in case they're going to be needed, such as:
--primary-100: ...
--primary-150: ...
...
most of which are not going to be used anywhere, and I'd like to prune them.
Is my only option to write my own plugin? I can't find any alternative to the deprecated postcss-unused-var, which I couldn't use anyway because it ignores :root.
Is my only option to write my own plugin? I can't find any alternative to the deprecated postcss-unused-var, which I couldn't use anyway because it ignores :root.
Currently, cssnano applies separate PostCSS plugins one after another. The plugins act independently, so there's no difference between adding the functionality to cssnano and writing a new PostCSS plugin. I am not aware of PostCSS plugins that remove CSS variables, probably because the transform is unsafe and the various parsers in the PostCSS world (PostCSS itself, postcss-value-parser) don't track CSS variables.
I understood the comment above as wontfix, so if anyone would also find removing variables that are not used anywhere in the file useful, I've published my solution here:
npm: postcss-prune-var github: tomasklaen/postcss-prune-var
Just in case, I've tried all three, postcss-css-variables, postcss-prune-var and postcss-unused-var, none of them works perfectly, because you know why. Tried with a single and complete stylesheet.