css / csso

CSS minifier with structural optimizations
https://css.github.io/csso/csso.html
MIT License
3.74k stars 189 forks source link

Merging declaration doesn't work as expected #435

Open nabtron opened 3 years ago

nabtron commented 3 years ago

Hi. The merging / redeclaring doesn't work with multiple css class names if they are not next to each other (see the last one that works). For example, see the input and output (does the same with csso webpack and cli)

% echo '.a1{color:red}.a2{color:green}.b1{color:red}' | csso                
.a1{color:red}.a2{color:green}.b1{color:red}
% echo '.a1{color:red}.b1{color:red}' | csso 
.a1,.b1{color:red}

So it doesn't work when we add the .a2, however it works if we remove it. However it works if all three has same color

% echo '.a1{color:red}.a2{color:red}.b1{color:red}' | csso
.a1,.a2,.b1{color:red}

And if we do this:

% echo '.a1{color:green}.a2{color:red}.b1{color:red}.b2{color:green}' | csso
.a1{color:green}.a2,.b1{color:red}.b2{color:green}
lahmatiy commented 3 years ago

@nabtron That's correct behaviour. Suppose we have a markup:

<div class="a1 a2">text</div>

Ans styles from your example:

.a1 { color: red }
.a2 { color: green }
.b1 { color: red }

Since selectors has the same specificity, the order of rules makes sense – last rule wins. In this example, text become green because a2 comes last.

However, if we change styles this way:

.a2 { color: green }
.a1, .b1 { color: red }

The text become red, since .a1 comes last now. That's incorrect.

In general, we can't change order of rules with the same specificity of selectors, because we may change a semantics (result) of styles.

nabtron commented 3 years ago

is there an option to override this check? in cases where the user wants this to be the intended behavior?