Re: [csswg-drafts] [css-mixins-1] Auto-wrap mixin body in `@result` if omitted? (#13524)

@tabatkins 

> (Miriam's interview with Chris Coyier, where as Miriam showed off the basic syntax, Chris literally said something like "oh like the 'result' property, makes sense".)

Thanks for the video link @mirisuzanne. It's a little after [51:25](https://www.youtube.com/live/T-X641Qn-Rc?si=Jw-Fk4_igwB7yzY1&t=3085). Though note that he also thought the first `result` property wins in functions (55:30), which may indicate a broader mental model disconnect.

Also I’ve observed that authors tend to express enthusiasm for features that solve their pain points (and mixins solve a HUGE pain point) and try to justify their design to themselves, regardless of what it is (unless it's egregiously bad, which is not the case here).

> I explained my design choices over in [the issue containing the resolution](https://github.com/w3c/csswg-drafts/issues/12927#issuecomment-4000841671).
> 
> As far as I can tell, there's no way to give macros arguments. Like, at all. It's just impossible without a _radically_ different execution model where the arguments are interpolated into the result in a purely tokenish fashion, incompatible with `var()`. (aka, like how Sass actually does its Mixins)

Fair. That makes sense for #12927, but it does mean that `@macro` does not completely address the issue discussed here.

Going back to your original comment…

> FWIW, I'm strongly **for** the `@result` rule, in the standard Mixin here. We already have existence proof that authors find the syntax parallel with `@function/result` to make sense. 

The question isn't whether the parallel makes sense, but whether its lack would _not_ make sense. Functions and mixins have fundamentally different characteristics around their usage: 
- In a function *all* declarations other than `result` are going to be local variables, so it would make no sense to require additional syntax for that. In a mixin, it's not clear that this will be the case. If you have data that most author mixins have local variables, it would be useful to share them!
- The "cost" of a `@result` rule is much higher than that of a `result` property. It's one extra level of nesting, and forces you to separate computation from result, which is not natural. It works in functions because the result is only one line, so nothing is separated. It gets even worse for nested rules, where the distance between computations and usage is even larger. We *could* address this with multiple `@result` rules that get merged, but that increases the noise even more.

Thinking about it some more, ultimately, we have a conflict between two models: One where declarations are local by default (functions, mixins with `@result`) and one where declarations are public by default (auto-wrapped mixins, other syntaxes like `@local` above, etc). I think the reason we are struggling to decide is a disconnect around what the relative proportions are of use cases where explicit locals / implicit result would produce better syntax vs use cases where implicit locals / explicit result would produce better syntax. I wonder if there's any way we could estimate this better. Or even if there's a reasonable design where authors declare what type of mixin they have, without complicating the mental model further. 🤔 

> I think we should _really_ value that sort of mental-model consistency when we can, because Mixins and Functions have _enormous_ functional and behavioral parallels and keeping their syntax and concepts as parallel as possible is a _huge_ win I think.

Is the worry that if `@result` exists, then something like this will be confusing?

```css
@mixin --button-container(--hue) {
 background: var(ident(--color- var(--hue) "-" 90));
 color: var(ident(--color- var(--hue) "-" 30));
 border-color: var(ident(--color- var(--hue) "-" 80));
}

@mixin --wa-button-style (--primary) {
 @apply --button-container(if(style(--primary): var(--hue-primary); var(--hue-neutral)));
}
```

whereas this will not be?

```css
@mixin --container-button(--hue) {
 @result {
   background: var(ident(--color- var(--hue) "-" 90));
   color: var(ident(--color- var(--hue) "-" 30));
   border-color: var(ident(--color- var(--hue) "-" 80));
 }
}

@mixin --wa-button-style (--primary) {
 @result {
  @apply --button-container(if(style(--primary): var(--hue-primary): var(--hue-neutral)));
 }
}
```

Because to me, the former seems pretty self-explanatory, and much closer to how preprocessor mixins behave. It’s the latter that needs to be learned…


-- 
GitHub Notification of comment by LeaVerou
Please view or discuss this issue at https://github.com/w3c/csswg-drafts/issues/13524#issuecomment-4008663110 using your GitHub account


-- 
Sent via github-notify-ml as configured in https://github.com/w3c/github-notify-ml-config

Received on Friday, 6 March 2026 00:24:16 UTC