Media query ordering changes when converting to object
I have a problem where a given rule's default definition (.leoButton.isSecondary) gets placed after the media query, which changes the behavior of the rendering. As such, the default overrides the media query, and the media query never takes effect.
Is this a known bug? Is there any known fix for this?
Input
.button.isPrimary {
--bg: var(--color-secondary-light-mode-70);
--bg-hover: var(--color-secondary-light-mode-80);
--bg-active: var(--color-secondary-light-mode-90);
--bg-focus: var(--color-secondary-light-mode-70);
--bg-loading: var(--color-secondary-light-mode-50);
--bg-disabled: var(--color-gray-70);
--color: white;
}
@media (prefers-color-scheme: dark) {
.button.isPrimary {
--bg: var(--color-secondary-dark-mode-50);
--bg-hover: var(--color-secondary-dark-mode-60);
--bg-active: var(--color-secondary-dark-mode-70);
--bg-loading: var(--color-secondary-dark-mode-60);
}
}
.button.isSecondary {
--bg: white;
--bg-active: --color-gray-20;
--color: var(--color-gray-90);
--color-hover: var(--color-secondary-light-mode-70);
--color-loading: var(--color-gray-70);
--border-width: 1px;
--border-color: var(--color-gray-30);
}
@media (prefers-color-scheme: dark) {
.button.isSecondary {
--bg: black;
--color-hover: var(--color-secondary-dark-mode-80);
}
}
Output
{
".button.isPrimary": {
"--bg": "var(--color-secondary-light-mode-70)",
"--bg-hover": "var(--color-secondary-light-mode-80)",
"--bg-active": "var(--color-secondary-light-mode-90)",
"--bg-focus": "var(--color-secondary-light-mode-70)",
"--bg-loading": "var(--color-secondary-light-mode-50)",
"--bg-disabled": "var(--color-gray-70)",
"--color": "white"
},
"@media (prefers-color-scheme: dark)": [
{
".button.isPrimary": {
"--bg": "var(--color-secondary-dark-mode-50)",
"--bg-hover": "var(--color-secondary-dark-mode-60)",
"--bg-active": "var(--color-secondary-dark-mode-70)",
"--bg-loading": "var(--color-secondary-dark-mode-60)"
}
},
{
".button.isSecondary": {
"--bg": "black",
"--color-hover": "var(--color-secondary-dark-mode-80)"
}
}
],
".button.isSecondary": {
"--bg": "white",
"--bg-active": "--color-gray-20",
"--color": "var(--color-gray-90)",
"--color-hover": "var(--color-secondary-light-mode-70)",
"--color-loading": "var(--color-gray-70)",
"--border-width": "1px",
"--border-color": "var(--color-gray-30)"
}
}
Can you create a smaller example to understand what is happening?
Sure thing. I've edited my original issue to include the bare minimum to reproduce.
I got the problem, it happens because you have 2 media queries. JS object doesn’t allow having 2 properties with the same key, so we try to collapse them.
There will not be a proper solution for this limit.
Here is what we can do:
- If you can, avoid object format for CSS. It is just not a production ready solution and a hack.
- You can use another PostCSS plugin to combine at-media in the end of the file. It still will be dangerous and could create another issue.
The third option is to change objectifier.js to keep merged at-rule at the position of the latest merging at-rule. Again, it is not a solution, but a hack, since we can create another conflict.
But maybe this strategy will create less issue.
If you want to you try to help me creating a PR.
Could a possible fourth option be to output an array of objects instead of an object? I know that Tailwind (which is my use case) accepts this syntax (see very end of that page for example). I'm not sure how widely acceptable that would be, though.
Could a possible fourth option be to output an array of objects instead of an object?
We can generate array in case when we have different media with the same params.
- You can use another PostCSS plugin to combine at-media in the end of the file. It still will be dangerous and could create another issue.
The sort-media-queries worked quite nicely.