You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[css-images-4] Allow gradients with a single color stop and 0-1 positions #10092
This came up in #10077 but I’m opening a new issue since I proposed a different path but then the change qualifies as substantive.
So currently, CSS Images 4 has prose and grammar that disallows single color stop gradients. However, all UAs have implemented a syntax that allows a gradient with a single color stop as long as it has two positions, e.g. linear-gradient(red 0% 100%).
What purpose does this restriction serve? You get a single color anyway and the positions are meaningless, they could be anything at all and as long as they parse, they produce the same result. E.g. linear-gradient(red 50% 50%), linear-gradient(red -100% -200%), linear-gradient(red 50% 50%), linear-gradient(red 300% 1000%) all produce the same result. So what's the harm in simply allowing a single color stop, even if it has one position — or even none? You get a single color anyway!
The benefits of that are small, but not inconsequential:
Clearer intent (the current syntax is misleading, because the numbers don't actually do anything).
It means that color stops can be independently valid or invalid, they don't depend on the presence of other color stops, which means they can be manipulated more easily in script
While the restriction is implemented, so adopting that would involve less eng effort, dropping the restriction is actually easier to implement so it would allow UAs to clean up their implementations.
The only argument against this is that implementations seem to agree on the current state (of requiring two stops) so we may as well adopt that in the spec. However, given the spec already differs from implementations, I see no harm in changing it in a way that makes it more permissive than implementations. Having it be less permissive (the current situation) is a much bigger issue.
Yeah, the restriction was just because you're defining a gradient, and by definition that requires two colors to interpolate between. But there's nothing wrong with allowing a single color, certainly. And if browsers are already allowing a single stop when it has two positions, contrary to the spec grammar (probably because they expand that at parse-time into two stops in their internal representation, and then just check that the internal list is at least 2 items), then I really don't see an issue.
The CSSWG will automatically accept this resolution one week from now if no objections are raised here. Anyone can add an emoji to this comment to express support. If you do not support this resolution, please add a new comment.
Proposed Resolution: Relax gradient syntax to allow a single color stop with 0-1 positions
Reacted by Romain Menke, Chris Lilley and Rossen Atanassov
This sounds reasonable as long as we're reasonably confident it's not going to add too much complexity to any future gradient interpolation rules. (I also thought about the object model, but I don't see any ways that it would add complexity to the object model that existing gradient features don't already require. However, the current interpolation rules draft isn't clear on how it handles stops without positions.)
If the first color stop does not have a position, set its position to 0%. If the last color stop does not have a position, set its position to 100%.
So does the first allocated position win, giving 0%? Because by the second clause, it does have a position?
As I said earlier, a position of 50% for a single color stop gradient is preferable. As currently described, if a new stop is inserted at the start, which wins? And what is the intended result? 50% gives a more natural meaning when stops are added.
So does the first allocated position win, giving 0%? Because by the second clause, it does have a position?
Note the ad21e29 edit, which separates the first/last assignment into separate steps, so the "in order" requirement handles this clearly.
a position of 50% for a single color stop gradient is preferable.
Putting the single stop literally anywhere has the exact same effect, per spec. I'd prefer not to add special-case text for single-stop gradients just to give them a special position; letting their position fall out of the existing fixup is preferable to me.
As currently described, if a new stop is inserted at the start, which wins? And what is the intended result? 50% gives a more natural meaning when stops are added.
I'm not sure what you mean here. When/how are you "inserting a new stop", and how are you trying to observe the result? If you just edit your stylesheet to now have two stops, you get the fixed-up result of two stops (0% and 100%). If you, say, swap to a two-stop gradient on hover or something, you'll be changing the gradient length and thus won't get any animation, so it's not observable where the original stop was positioned.
UAs normalize any color stop defined with two positions, to two color stops with a single position, which is the main reason they accepted a single color stop: it represents two.
Now that this is relaxed, should they still be normalized? This goes against the shortest serialization principle, is not defined in the spec, and I cannot find related tests on WPT.
So does the first allocated position win, giving 0%? Because by the second clause, it does have a position?
Note the ad21e29 edit, which separates the first/last assignment into separate steps, so the "in order" requirement handles this clearly.
@tabatkins I see this edit was applied to css-images-3, but it looks like an equivalent change also needs to be applied to css-images-4 for consistency/clarity.
The test color-stops-parsing.html needs to be updated to take into account these changes. In particular, it currently tests that a gradient with a single stop is invalid.
@tabatkins I see this edit was applied to css-images-3, but it looks like an equivalent change also needs to be applied to css-images-4 for consistency/clarity.
Activity
svgeesus commentedon Apr 26, 2024
Requiring two meaningless positions does seem like a waste of time. This seems a lot cleaner.
tabatkins commentedon Apr 26, 2024
Yeah, the restriction was just because you're defining a gradient, and by definition that requires two colors to interpolate between. But there's nothing wrong with allowing a single color, certainly. And if browsers are already allowing a single stop when it has two positions, contrary to the spec grammar (probably because they expand that at parse-time into two stops in their internal representation, and then just check that the internal list is at least 2 items), then I really don't see an issue.
svgeesus commentedon May 23, 2024
So far no-one is arguing against this change and everyone who has commented agrees that this is reasonable, desirable, and easily implementable.
@astearns this seems like a candidate for async resolution, therefore.
astearns commentedon May 28, 2024
The CSSWG will automatically accept this resolution one week from now if no objections are raised here. Anyone can add an emoji to this comment to express support. If you do not support this resolution, please add a new comment.
Proposed Resolution: Relax gradient syntax to allow a single color stop with 0-1 positions
dbaron commentedon May 28, 2024
This sounds reasonable as long as we're reasonably confident it's not going to add too much complexity to any future gradient interpolation rules. (I also thought about the object model, but I don't see any ways that it would add complexity to the object model that existing gradient features don't already require. However, the current interpolation rules draft isn't clear on how it handles stops without positions.)
tabatkins commentedon May 29, 2024
It shouldn't, no; the interpolation rules work just as well for a single stop as infinity stops.
I've filed the position-less stop issue as #10374.
astearns commentedon Jun 3, 2024
RESOLVED: Relax gradient syntax to allow a single color stop with 0-1 positions
10 remaining items
svgeesus commentedon Jul 19, 2024
So does the first allocated position win, giving 0%? Because by the second clause, it does have a position?
As I said earlier, a position of 50% for a single color stop gradient is preferable. As currently described, if a new stop is inserted at the start, which wins? And what is the intended result? 50% gives a more natural meaning when stops are added.
tabatkins commentedon Jul 19, 2024
Note the ad21e29 edit, which separates the first/last assignment into separate steps, so the "in order" requirement handles this clearly.
Putting the single stop literally anywhere has the exact same effect, per spec. I'd prefer not to add special-case text for single-stop gradients just to give them a special position; letting their position fall out of the existing fixup is preferable to me.
I'm not sure what you mean here. When/how are you "inserting a new stop", and how are you trying to observe the result? If you just edit your stylesheet to now have two stops, you get the fixed-up result of two stops (0% and 100%). If you, say, swap to a two-stop gradient on hover or something, you'll be changing the gradient length and thus won't get any animation, so it's not observable where the original stop was positioned.
cdoublev commentedon Jul 20, 2024
About serialization...
UAs normalize any color stop defined with two positions, to two color stops with a single position, which is the main reason they accepted a single color stop: it represents two.
Now that this is relaxed, should they still be normalized? This goes against the shortest serialization principle, is not defined in the spec, and I cannot find related tests on WPT.
Let me know if I should open a separate issue.
Fix parsing `<color-stop-list>`
jfkthame commentedon Dec 24, 2024
@tabatkins I see this edit was applied to css-images-3, but it looks like an equivalent change also needs to be applied to css-images-4 for consistency/clarity.
yisibl commentedon Jan 23, 2025
Firefox 136 has been implemented. Thanks @jfkthame
This technique is often needed in CSS masks:
Now you can use individual colors in gradients, and the following syntax will work.
svgeesus commentedon Jan 23, 2025
I see that wpt is now updated to allow single stops and that Firefox 136 passes them.
[css-images-4] Separate first and last stop fixing into separate step…
svgeesus commentedon Jan 23, 2025
Fixed in ed4f651
Allow gradient to have one single stop