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

[system][enhancement] Dedupe zero min width media queries #42064

Open
wants to merge 1 commit into
base: next
Choose a base branch
from

Conversation

brijeshb42
Copy link
Contributor

from the generated css. These don't have any higher specificity than direct css.

Fixes #42025

@brijeshb42 brijeshb42 added package: system Specific to @mui/system enhancement This is not a bug, nor a new feature labels Apr 30, 2024
@mui-bot
Copy link

mui-bot commented Apr 30, 2024

Netlify deploy preview

https://deploy-preview-42064--material-ui.netlify.app/

Bundle size report

Details of bundle changes (Toolpad)
Details of bundle changes

Generated by 🚫 dangerJS against 13096fa

@brijeshb42 brijeshb42 force-pushed the system/zero-media-query branch 3 times, most recently from a2b73f3 to 05a17a3 Compare April 30, 2024 10:28
Copy link
Member

@aarongarciah aarongarciah left a comment

Choose a reason for hiding this comment

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

Thanks! Pigment CSS bundle sizes will thank you 😄

@@ -121,10 +121,19 @@ export function createEmptyBreakpointObject(breakpointsInput = {}) {

export function removeUnusedBreakpoints(breakpointKeys, style) {
return breakpointKeys.reduce((acc, key) => {
const zeroMediaQueryRgx = /^@media\s\(min-width:\s?[0](px|rem|em)\)$/;
Copy link
Member

Choose a reason for hiding this comment

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

We could make this work for any arbitrary unit since the unit is configurable by consumers. Not sure it's worth it though. Something like this:

Suggested change
const zeroMediaQueryRgx = /^@media\s\(min-width:\s?[0](px|rem|em)\)$/;
const zeroMediaQueryRgx = /^@media\s\(min-width:\s?[0][a-zA-Z]*?\)$/;

It caters for uppercase units because we don't convert units to lowercase and consumers can input any arbitrary value AFAIK.

@brijeshb42
Copy link
Contributor Author

Seems this change is breaking something as is evident in the argos screenshot. I'll investigate and see if we need a deeper level of testing before merging it.

@aarongarciah
Copy link
Member

@brijeshb42 margins for Stack's children elements in the smallest breakpoint seem to be injected last, so they win. This is from the Responsive values example in System's docs:

before after
Screenshot 2024-05-01 at 09 51 04 Screenshot 2024-05-01 at 09 51 19

image

} else if (zeroMediaQueryRgx.test(key)) {
const zeroMediaValues = acc[key];
delete acc[key];
Object.entries(zeroMediaValues).forEach(([styleKey, styleValue]) => {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This breaks the current UI because it inserts the keys in the zero media query at the end. Instead, it should insert the keys at the same place as the zero media query.
I'll need to find a performant way to do that without using spread operator.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've tried spread operator for now to see if the site still breaks or not.

@github-actions github-actions bot added the PR: out-of-date The pull request has merge conflicts and can't be merged label May 6, 2024
from the generated css. These don't have any higher specificity than
direct css.

Fixes mui#42025
@github-actions github-actions bot removed the PR: out-of-date The pull request has merge conflicts and can't be merged label May 6, 2024
@brijeshb42
Copy link
Contributor Author

brijeshb42 commented May 6, 2024

After testing the change, I feel that although this is the correct change to have and will benefit us in Pigment CSS to generate relatively smaller bundle sizes, I'm afraid that we might be breaking sites for a lot of our users who might have unknowingly started to rely on this behaviour. Here's an example from one of our own templates that got captured through argos -

Before After
https://next.mui.com/material-ui/getting-started/templates/dashboard/ https://deploy-preview-42064--material-ui.netlify.app/material-ui/getting-started/templates/dashboard/
Screenshot 2024-05-06 at 2 37 06 PM Screenshot 2024-05-06 at 2 37 31 PM

cc: @siriwatknp

@aarongarciah
Copy link
Member

aarongarciah commented May 6, 2024

@brijeshb42 I see the problem now. Before this change, users' overrides always came after the component code.

The original code does this (in a minimal pseudo-code representation):

.Toolbar {
  padding-left: 16px;
}

@media (min-width: 600px) {
  .Toolbar {
    padding-left: 24px;
  }
}

/* User code 👇 */
@media (min-width: 0px) {
  .Toolbar {
    padding-left: 8px; /* 🏆 this declaration wins 🟢 */
  }
}

With the new changes, the generated code looks like this:

.Toolbar {
  padding-left: 16px;
  
  /* User code is mixed with the component's CSS 👇 */
  padding-left: 8px;
}

@media (min-width: 600px) {
  .Toolbar {
    padding-left: 24px; /* 🏆 this declaration wins 🔴 */
  }
}

I'm wondering if the solution is to follow the same approach as the original code by appending a new ruleset at the end but without the media query:

.Toolbar {
  padding-left: 16px;
}

@media (min-width: 600px) {
  .Toolbar {
    padding-left: 24px;
  }
}

/* User code 👇 */
.Toolbar {
  padding-left: 8px; /* 🏆 this declaration would win 🟢 */
}

I'm unaware if this is possible or not, I'm just wondering if this could lead to a potential solution.

@brijeshb42
Copy link
Contributor Author

It is definitely possible. But in that case, the only gain I see that we are saving this much string (@media (min-width: 0px) {}) from being added which isn't a lot I'd say.

@aarongarciah
Copy link
Member

the only gain I see that we are saving this much string (@media (min-width: 0px) {}) from being added which isn't a lot I'd say.

Yeah, although how many times it's repeated in the generated CSS bundle depends on consumers' code. Which may not be so bad when compression enters the equation. But if we think about the big picture (thousands of CSS files being generated by Pigment CSS in the future), may be worth saving some bytes if the added complexity and risk is low.

@brijeshb42
Copy link
Contributor Author

I did a basic gzipped size check for this template

First one with zero media query -

fs = require('fs');

a = '';
for (let i=0;i<10000;i++) {
 a += `@media (min-width: 0px){.class${i}{padding:10px;}}` + `@media (min-width: ${i}px){.cls${i}{margin: ${i}px;}}`
}

fs.writeFileSync('a1.css', a, 'utf-8')

And second one without media query -

fs = require('fs');

a = '';
for (let i=0;i<10000;i++) {
 a += `.class${i}{padding:10px;}` + `@media (min-width: ${i}px){.cls${i}{margin: ${i}px;}}`
}

fs.writeFileSync('a2.css', a, 'utf-8')

There's definitely reduced size without it (~7.4%)
Before:
Screenshot 2024-05-06 at 6 07 51 PM

After:
Screenshot 2024-05-06 at 6 10 26 PM

@brijeshb42
Copy link
Contributor Author

@aarongarciah I spoke too soon. I tried to implement what you suggested -

.Toolbar {
  padding-left: 16px;
}

@media (min-width: 600px) {
  .Toolbar {
    padding-left: 24px;
  }
}

/* User code 👇 */
.Toolbar {
  padding-left: 8px; /* 🏆 this declaration would win 🟢 */
}

but there doesn't seem to be a straightforward way to do this as the modification will need to be down outside of the media queries object.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement This is not a bug, nor a new feature package: system Specific to @mui/system
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[system] Unnecessary media query with 0px breakpoints
3 participants