- From: Steinar H. Gunderson via GitHub <noreply@w3.org>
- Date: Tue, 12 Aug 2025 13:31:42 +0000
- To: public-css-archive@w3.org
sesse has just created a new issue for https://github.com/w3c/csswg-drafts:
== [css-mixins-1] How are cycles broken? ==
Imagine a mixin A that includes an A/B loop:
```css
@mixin a() {
--last-processed: a;
@apply b();
}
@mixin b() {
--last-processed: b;
@apply c();
}
@mixin c() {
--last-processed: c;
@apply b();
}
```
Now suppose someone applies a() within a rule. What is the value of `--last-processed`; a, b, c or even unset? (You could ask similar questions about declarations after the `@apply` rules.)
If we're breaking cycles at the last possible moment, then the value is c. This is a fairly simple model; you just keep a stack of everything that is in the process of being applied, and when you see an `@apply` against something already in your stack, you ignore it.
However, CSS custom properties don't work that way; they declare the entire cycle as illegal, so `@apply b();` has no effect and the result is a. (Similarly, you could argue that including a cycle is illegal and the value should not even be set, but I don't think that matches CSS custom properties. In any case, they're not quite the same because they have explicit fallbacks.) The problem with this is that we cannot easily rollback already-applied declarations, so before every mixin that we try to apply, we would need a separate cycle-finding step. (We cannot easily do this parse-time, since the mixins may come from different style sheets and/or tree scopes.)
So I'd argue that it should be either a or c, but it's not really obvious which one. c is much easier for a performant implementation, though.
Please view or discuss this issue at https://github.com/w3c/csswg-drafts/issues/12595 using your GitHub account
--
Sent via github-notify-ml as configured in https://github.com/w3c/github-notify-ml-config
Received on Tuesday, 12 August 2025 13:31:43 UTC