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
base: next
Are you sure you want to change the base?
Conversation
Netlify deploy previewhttps://deploy-preview-42064--material-ui.netlify.app/ Bundle size reportDetails of bundle changes (Toolpad) |
a2b73f3
to
05a17a3
Compare
There was a problem hiding this 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)\)$/; |
There was a problem hiding this comment.
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:
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.
Seems this change is breaking something as is evident in the |
@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:
|
} else if (zeroMediaQueryRgx.test(key)) { | ||
const zeroMediaValues = acc[key]; | ||
delete acc[key]; | ||
Object.entries(zeroMediaValues).forEach(([styleKey, styleValue]) => { |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
05a17a3
to
2af53cc
Compare
from the generated css. These don't have any higher specificity than direct css. Fixes mui#42025
6333fe6
to
13096fa
Compare
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
cc: @siriwatknp |
@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. |
It is definitely possible. But in that case, the only gain I see that we are saving this much string ( |
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. |
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') |
@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. |
from the generated css. These don't have any higher specificity than direct css.
Fixes #42025