postcss-js
postcss-js copied to clipboard
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.