PHP-CSS-Parser
PHP-CSS-Parser copied to clipboard
Bug in parsing CSS vars
Currently working on a project that uses PHP-CSS-Parser. We've defined some CSS vars in the following manner:
:root {
--theme-header--bg: 236,47%,46%;
}
And then using them throughout our CSS in the following way:
.header__navigation {
background-color: hsl(var(--theme-header--bg));
}
However, when :root { --theme-header--bg:236,47%,46%; }
is run through PHP-CSS-Parser
it is stripped and the our CSS declarations where we are using the --theme-header--bg
var is being dropped.
Original discussion: https://wordpress.org/support/topic/css-hsl-stripped-not-working/
It's actually the hsl(var(--theme-header--bg))
which is getting dropped.
So given:
:root {
--theme-header--bg: 236,47%,46%;
}
.header__navigation {
color: black;
background-color: hsl(var(--theme-header--bg));
border: solid 1px red;
}
The PHP-CSS-Parser is only able to parse this as:
:root {
--theme-header--bg:236,47%,46%;
}
.header__navigation {
color:black;
border:solid 1px red;
}
Notice how background-color: hsl(var(--theme-header--bg))
is dropped.
A workaround is to move the hsa()
function to the variable, like so:
:root {
--theme-header--bg: hsl(236,47%,46%);
}
.header__navigation {
color: black;
background-color: var(--theme-header--bg);
border: solid 1px red;
}
But since the browsers work either way, PHP-CSS-Parser should also work.
@sabberworm Any insights you might be able to provide here?
@EvanHerman Hm, I agree it’s a bug but I don’t currently have any time to look into this myself.
I’ll gladly accept PRs though…
According to the specs, “[t]he var() function can be used in place of any part of a value in any property on an element”. I think we currently expect it only as single value (as opposed to “any part of a value”).
I don’t know how we could reconcile this with the way the parsed content is structured currently. We obviously cannot resolve the value(s) since we don’t know the run-time cascade but we also can’t parse a reasonable representation of the hsl
function… In theory this would probably mean we can lex – but never fully parse – any expression if it contains var(…)
s.
I have an idea that might work. Please consider the following changes as a proposal, not something ready to use (although it works with the provided example many cases are not handled) https://github.com/NitroPack/PHP-CSS-Parser/commit/cfec151106666ec62fe31338d7bb60b1efb369ac
We can keep a list of defined vars with their corresponding values and use it to expand the text in the parser state when a known var is met. However unknown vars are still not handled.
Also, instead of expanding the main text, we can do stack of parser states or a stack of texts in the main parser state. We should also be able to print back the original var() statement in the output.
Should we agree on proceeding with this idea it should be relatively easy to make it work for all supported value types.
PS. Keeping the list with known vars is also going to be useful when traversing the tree after it is parsed. Although we will have to wrap all var values in Value\CssVar
objects.
@raxbg I've not had a chance to test, but it sounds like that would be an ideal solution. Is it something that you can help with a PR? I'm not all too familiar with the PHP-CSS-Parser code base or I'd try and help out.
It appears this bug is breaking Tailwind CSS v3.0: https://github.com/ampproject/amp-wp/issues/5023#issuecomment-1013277918
We have been postponing to update to Tailwind 3 for almost a year now because of this bug. Are there any updates on this? Or is there anything I can do to help? Thanks in advance!
@sboerrigter A pull request that fixes the bug (and covers it with a regression test) would be very helpful.