lightningcss icon indicating copy to clipboard operation
lightningcss copied to clipboard

Only adjacent rules are merged

Open binyamin opened this issue 2 years ago • 12 comments

Summary

Rules which target the same selector, or include the same declaration, are only merged when they are adjacent.

Example

The following code has three rules for body, and one rule for h1 in between them. When I run parcel bundle style.css, only two body rules are merged.

Input

body {
    color: red;
}

body {
    background-color: blue;
}

h1 {
    font-weight: normal;
}

body {
    margin: 0;
}

Output

body{color:red;background-color:#00f}h1{font-weight:400}body{margin:0}

binyamin avatar Jul 14 '22 20:07 binyamin

See #50.

In general, merging non-adjacent selectors is not safe due to specificity. For example:

<div class="a b">hi</div>
<style>
.a { color: green; }
.b { color: aqua; }
.a { color: red; }
</style>

In this example, the div should have red text. But if the .a selectors were merged, it would be aqua.

devongovett avatar Jul 14 '22 20:07 devongovett

@devongovett Understood. However, Parcel has extensive knowledge of the CSS. I specifically chose a case where the declarations have different property names.

binyamin avatar Jul 14 '22 23:07 binyamin

That definitely limits the usefulness of this though. It means for any rule, you'd have to walk backwards through all previous rules, and none of them can have any overlap between any of their properties. Doesn't seem like it would happen often in practice.

devongovett avatar Jul 15 '22 00:07 devongovett

It means for any rule, you'd have to walk backwards through all previous rules, and none of them can have any overlap between any of their properties.

Yeah, I can see that really slowing stuff down. Theoretically, it could be an option which is disabled by default.

I wonder if it would be performant to keep a running tally of the selectors, while ParcelCSS traverses the rules initially. Tallying the properties seems bad in-terms of speed. Then, you could find each selector which is mentioned more than once, without walking backwards.

Doesn't seem like it would happen often in practice.

Use case: A user includes a CSS reset in a previous build step. It's easy to run into this problem with Sass.

binyamin avatar Jul 15 '22 17:07 binyamin

I think there are a lot of projects out there hat uses Tailwind, and then add few more defaults on html or body

ArnaudBarre avatar Aug 21 '22 15:08 ArnaudBarre

@devongovett Can we add new configuration option to declare that "these selectors will never be used in the same element"? It will be basically the same as csso's "scopes" feature. This feature will be useful to aggressively merge styles generated by things like zero-runtime CSS-in-JS like the following:

.css-xyzabc {
  color: red;
}

.css-o3z7bc {
  color: blue;
}

.css-kyzkcc {
  color: red;
}

Should become:

.css-xyzabc,.css-kyzkcc  {
  color: red;
}

.css-o3z7bc {
  color: blue;
}

We (human) know that these classes will never overlap on the same element but there is no way to tell this fact to lightningcss. I see this as "dual" form of atomic CSS ("atomic selector"?)

naruaway avatar Jan 25 '23 12:01 naruaway

@devongovett can we make this optional? it's not safe but useful sometime lot of people may set property atomic and well control over duplication

y0zong avatar Feb 12 '23 16:02 y0zong

In aa083a72a2de4fef55f9105c904591e86250b9b8 I implemented a feature that removes duplicate rules with the same selectors and properties. That might help with some atomic CSS cases. See https://github.com/parcel-bundler/lightningcss/issues/456#issuecomment-1501198606 for more info.

devongovett avatar Apr 09 '23 19:04 devongovett

It would be awesome if we had an option to do "unsafe" optimizations like this.

nicksrandall avatar Sep 24 '23 03:09 nicksrandall

yes

On Sun, Feb 12, 2023, 10:51 AM Yaozong Wang @.***> wrote:

@devongovett https://github.com/devongovett can we make this optional? it's not safe but useful sometime lot of people may set property atomic and well control over duplication

— Reply to this email directly, view it on GitHub https://github.com/parcel-bundler/lightningcss/issues/225#issuecomment-1427078320, or unsubscribe https://github.com/notifications/unsubscribe-auth/AX26CFF65GAJEGOXPRFL62TWXEIKZANCNFSM53TP6L7A . You are receiving this because you are subscribed to this thread.Message ID: @.***>

Oriblish avatar Sep 25 '23 13:09 Oriblish

yes

On Wed, Jan 25, 2023, 6:49 AM Naru @.***> wrote:

@devongovett https://github.com/devongovett Can we add new configuration option to declare that "these selectors will never be used in the same element"? It will be basically the same as csso's "scopes" feature https://github.com/css/csso#scopes. This feature will be useful to aggressively merge styles generated by things like zero-runtime CSS-in-JS like the following:

.css-xyzabc { color: red; }

.css-o3z7bc { color: blue; }

.css-kyzkcc { color: red; }

Should become:

.css-xyzabc,.css-kyzkcc { color: red; }

.css-o3z7bc { color: blue; }

We (human) know that these classes will never overlap on the same element but there is no way to tell this fact to lightningcss. I see this as "dual" form of atomic CSS ("atomic selector"?)

— Reply to this email directly, view it on GitHub https://github.com/parcel-bundler/lightningcss/issues/225#issuecomment-1403557019, or unsubscribe https://github.com/notifications/unsubscribe-auth/AX26CFDUE4SH2EBIOHWEWBDWUEOORANCNFSM53TP6L7A . You are receiving this because you are subscribed to this thread.Message ID: @.***>

Oriblish avatar Sep 25 '23 13:09 Oriblish

https://github.com/jellyfin/jellyfin-vue/actions/runs/5882072278/job/15951827659#step:9:480

On Mon, Sep 25, 2023, 8:48 AM Renee Brutcher @.***> wrote:

yes

On Wed, Jan 25, 2023, 6:49 AM Naru @.***> wrote:

@devongovett https://github.com/devongovett Can we add new configuration option to declare that "these selectors will never be used in the same element"? It will be basically the same as csso's "scopes" feature https://github.com/css/csso#scopes. This feature will be useful to aggressively merge styles generated by things like zero-runtime CSS-in-JS like the following:

.css-xyzabc { color: red; }

.css-o3z7bc { color: blue; }

.css-kyzkcc { color: red; }

Should become:

.css-xyzabc,.css-kyzkcc { color: red; }

.css-o3z7bc { color: blue; }

We (human) know that these classes will never overlap on the same element but there is no way to tell this fact to lightningcss. I see this as "dual" form of atomic CSS ("atomic selector"?)

— Reply to this email directly, view it on GitHub https://github.com/parcel-bundler/lightningcss/issues/225#issuecomment-1403557019, or unsubscribe https://github.com/notifications/unsubscribe-auth/AX26CFDUE4SH2EBIOHWEWBDWUEOORANCNFSM53TP6L7A . You are receiving this because you are subscribed to this thread.Message ID: @.***>

Oriblish avatar Sep 25 '23 14:09 Oriblish