Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[css-minifier]Merge the same rules #2552

Open
yisibl opened this issue Sep 16, 2022 · 4 comments
Open

[css-minifier]Merge the same rules #2552

yisibl opened this issue Sep 16, 2022 · 4 comments

Comments

@yisibl
Copy link
Contributor

yisibl commented Sep 16, 2022

Currently cssnano, lightningcss are all supported.

Input

a:not([href]) {
  color: inherit;
  text-decoration: none
}

a:not([href]):hover {
  color: inherit;
  text-decoration: none
}

Output

a:not([href]){color:inherit;text-decoration:none}a:not([href]):hover{color:inherit;text-decoration:none}

Expected

a:not([href]),a:not([href]):hover{color:inherit;text-decoration:none}
@evanw
Copy link
Owner

evanw commented Sep 18, 2022

Yeah I took a look at their benchmark when Lightning CSS was posted. It turns out that esbuild does this because merging rules outside of a very specific set of cases can break things for browsers that consider one rule valid but the other rule invalid. For context, these restrictions on esbuild's rule merging were added to fix #1776.

This issue is an edge case where it should be possible to merge these because one rule is a subset of the other rule and only additionally uses :hover, which is supported everywhere. That could be one approach to try to solve this. Another approach could be to create a dense feature compatibility matrix for various CSS selectors and then use the target setting to decide whether a given selector is supported (and therefore can be merged). Maybe that's what Lightning CSS is doing?

@yisibl
Copy link
Contributor Author

yisibl commented Sep 19, 2022

Yes, Lightning CSS has access to Caniuse.com and MDN data.

Another idea for selectors that are not recognized by browsers is to make the :is() selector, where is() keeps the entire selector valid. But the caveat is that it is still necessary to know which browsers support :is().

See: Forgiving Selector Parsing

Input (158 Bytes)

.form-input:-moz-placeholder-shown {
  color: black;
}
.form-input:-ms-input-placeholder {
  color: black;
}
.form-input:placeholder-shown {
  color: black;
}

Output (133 Bytes)

.form-input:-ms-input-placeholder {
  color: black;
}
.form-input:is(:-moz-placeholder-shown, :placeholder-shown) {
  color: black;
}

@devongovett
Copy link

Yes, lightningcss uses compatibility data for this. Logic here: https://github.com/parcel-bundler/lightningcss/blob/d03093aceb6bbacd92283f85dd790fd274939483/src/selector.rs#L1324

@kapouer
Copy link

kapouer commented Oct 6, 2023

Another example (using esbuild 0.19.4)
Input file1.css

body { font-size:16px; }

Input file2.css

body { color: red; }

Input entry.css

@import "file1.css";
@import "file2.css";

Output

body{font-size:16px}body{color:red}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants