- From: CSS Meeting Bot via GitHub <noreply@w3.org>
- Date: Wed, 20 Aug 2025 08:02:34 +0000
- To: public-css-archive@w3.org
The CSS Working Group just discussed `[css-mixins-1] Are @mixin rules valid within other at-rules?`, and agreed to the following: * `RESOLVED: @layer is invalid inside mixins (for level 1)` * `RESOLVED: Mixins have to be defined before use` * `RESOLVED: Custom media queries need to be defined before use` * `RESOLVED: @mixin is valid wherever @keyframes is valid` * `SUMMARY: Still open question of whether @mixin declarations are layered -- either way is acceptable implementation-wise` * `ACTION: TabAtkins to file issue on whether global name-defining things should be invalid inside contextual conditionsl such as @container or @scope` <details><summary>The full IRC log of that discussion</summary> <fantasai> andruud: Question of @mixin within e.g. @container -- are they allowed? are they conditional?<br> <fantasai> andruud: My thought was surely these are not not affected by the @container rule<br> <fantasai> andruud: Other than @media and @supports<br> <fantasai> andruud: This issue evolved into discussing @layer<br> <fantasai> andruud: We have to support layered mixins because @import can be layered<br> <emilio> q+<br> <fantasai> andruud: Proposal that we landed on is allowing mixins inside @layer, but, not letting the mixin name be affected by the layer<br> <miriam> q+<br> <fantasai> andruud: still have to do multi-stage resolution because if you have @apply before mixin<br> <fantasai> andruud: We didn't want multiple layer orders, because you could get one layer order while looking for mixin, and then different layer order if you mix in a mixin with layers inside?<br> <fantasai> TabAtkins: If your mixin has @layer inside, that can theoretically add to the layer list<br> <fantasai> TabAtkins: we want to allow you to put layer rules in the mixin body<br> <fantasai> TabAtkins: but then we either have to do one layer order to figure out how mixins resolve, and then do another to do styles, and that seems not great?<br> <astearns> ack fantasai<br> <emilio> fantasai: the first q I have is about putting @mixin in @container<br> <emilio> ... if they're not responding to @container which won't make any sense<br> <emilio> ... they should not be allowed<br> <emilio> ... because that'd be confusing<br> <emilio> ... should just be invalid<br> <emilio> ... I think what makes sense is that @layer inside mixing is ignored until substitution<br> <miriam> (on the que to suggest we rethink layers inside mixins)<br> <emilio> andruud: the question is what happens if you define the same mixin name inside an `@layer`<br> <emilio> TabAtkins: right it'd be possible to change the layer order post-application<br> <lea> q?<br> <SebastianZ> q+<br> <emilio> ... because @apply would be able to change the layer order<br> <lea> q+<br> <emilio> fantasai: I think we probably want that<br> <emilio> TabAtkins: disagreed<br> <astearns> ack miriam<br> <fantasai> miriam: I'm skeptical if we want to allow layers inside of mixins<br> <emilio> miriam: I'm skeptical about layers _inside_ mixins<br> <emilio> ... I understand why it feels useful<br> <fantasai> miriam: I understand why it feels useful<br> <fantasai> miriam: I think it will be confusing if layers inside of mixins interact with layers outside of mixins<br> <fantasai> miriam: I don't mean at the definition site, but at the call site<br> <andruud> +1<br> <lea> q-<br> <fantasai> miriam: I have a feeling that layers inside of mixins should be contained to the mixin in some way, or not visible, not interacting with outside layers<br> <fantasai> miriam: you would think of them as inside of their own anonymous layer<br> <fantasai> miriam: say I create a mixin with 3 layer names inside of it, default states and overrides<br> <fantasai> miriam: I'm hoping they would interact with my globla states and overrides<br> <fantasai> miriam: but when I use them they'll be states.states and override.override<br> <fantasai> miriam: They won't interact correctly<br> <SebastianZ> q-<br> <fantasai> miriam: so layers inside of mixins should be contained by anonymous and not otherswise interact with stuff<br> <fantasai> TabAtkins: I think that would remove any reason to use layers inside mixins<br> <fantasai> TabAtkins: at which point we should just disallow layers inside mixins entirely<br> <bramus> Was thinking the same as Tab there<br> <fantasai> miriam: OK with that. Could relax it later if needed<br> <fantasai> miriam: Yeah, might not need it<br> <lea> +1 to make layers a v2 thing. Even if useful, it's clearly not MVP and would slow down shipping the MVP<br> <fantasai> TabAtkins: contents of your rule could use layers, but at that point could just use specificity hacks<br> <fantasai> miriam: Interaction of inside out and outside in ...<br> <ydaniv> +1 to lea<br> <astearns> ack emilio<br> <fantasai> TabAtkins: I am disappointed they won't be purely transparent, but this is something we could do in v2 so OK with it<br> <lea> q+ to say the same thing<br> <fantasai> emilio: That still doesn't change the complexity of allowing them to be affected by the layer order<br> <fantasai> emilio: if you allow mixin definition to depend on layers, you still need to perform the whole layer traversal<br> <fantasai> emilio: which is annoying<br> <fantasai> TabAtkins: propose to not do that<br> <fantasai> andruud: You would need to do that if you want to cascade the mixin rules<br> <fantasai> andruud: at least the new layers are stable, and can reason about them<br> <fantasai> andruud: As we implemented it, we saw would solve everything, except the pass you don't like<br> <fantasai> TabAtkins: you're assuming we need to use layers to resolve names<br> <fantasai> emilio: We need to decide whether global or not, and I think they should be global<br> <fantasai> emilio: regarding @container etc, there's precedent to make some of these rules unconditionally valid. E.g. @layer does this.<br> <fantasai> emilio: I'm fine allowing inside @container ... but I guess you can have nested mixins<br> <fantasai> emilio: But we have precedent for unconditionally apply these contextual rules, might be easier<br> <fantasai> emilio: In terms of keeping conditional rules syntax consistent and interchangeable with @media<br> <fantasai> andruud: Could move the @container inside the mixin<br> <fantasai> emilio: Then you have to pull in the whole stack of conditional context<br> <fantasai> TabAtkins: Should purely based on body of mixin<br> <fantasai> emilio: Arguably could have said @layer inside @container is invalid<br> <astearns> ack lea<br> <Zakim> lea, you wanted to say the same thing<br> <TabAtkins> TabAtkins: @mixins can't "carry in" their external context, any conditionality needs to be purely based on the body of the mixin, and where it's @apply'd.<br> <fantasai> lea: It's very clear to me that, even if there are use cases for layers inside mixins, it's hairy, and we're not sure it's useful, so moving it to next level unblocks shipping, I would vote for that, because this is a really important feature that authors want a long time<br> <fantasai> lea: even if very simple version now<br> <fantasai> lea: we can add it later<br> <fantasai> lea: so let's defer any complicated things to later<br> <astearns> ack fantasai<br> <emilio> fantasai: support what lea said<br> <emilio> ... but strongly disagree that we should pretend @container doesn't exist<br> <lea> +1 we need to be able to add them later, so they should be *invalid* now<br> <emilio> ... if we put an @mixing inside @container it'd be really confusing if it's unconditionally existing<br> <emilio> ... @layer is a bit different, the layer existence is a side effect<br> <miriam> +1 fantasai<br> <emilio> ... but that's not what they're thinking of when writing @layer inside @container<br> <TabAtkins> I'm fine with that, too<br> <emilio> ... the only thing that'd make sense is to shift the conditionals inside if we wanted to do that<br> <matthieud> q+<br> <emilio> ... making it an unconditional declaration is a no go<br> <TabAtkins> Strong, strong disagree on "shifting the conditional into the @mixin"<br> <emilio> ... wrt to layers, making them invalid at first is fine. Another option might be that layer inside mixing can interact with existing layers but can't create it<br> <lea> +1 to everything fantasai just said<br> <astearns> ack matthieud<br> <TabAtkins> Yeah, that's a reasonable possibility<br> <fantasai> matthieud: example: @scope inside ??, we don't provide a scope<br> <fantasai> s/??/@feature-value<br> <fantasai> matthieud: we ignore the @scope<br> <fantasai> emilio: same for @font-face<br> <emilio> matthieud: re. the outer / inner at rules, if you have @font-face inside @scope the scope is already ignored<br> <fantasai> emilio: We do the ignoring for @scope etc for virtually every other global at-rule<br> <fantasai> emilio: It would be weird if this worked different from @keyframes<br> <fantasai> emilio: Maybe we shouldn't have allowed @keyframes inside @scope etc, but doesn't seem worth changing<br> <fantasai> andruud: We could try. Maybe no one is doing it<br> <fantasai> emilio: Yeah, seems uncommon. Fix is easy, too.<br> <fantasai> andruud: Suggest resolve that, for now, @layer is invalid inside mixins<br> <fantasai> andruud: Less sure about other one, @mixin is invalid inside @rules other than @media or @supports<br> <fantasai> TabAtkins: could have it inside @layer, but not act as if it's layered<br> <fantasai> emilio: That would be preferable<br> <fantasai> TabAtkins: Given elika's suggestion to allow @layer inside mixin by allowing it to work if already exists, but otherwise drop the block<br> <fantasai> TabAtkins: that would mean that mixin application cannot change layer order<br> <miriam> I don't like that idea much<br> <fantasai> TabAtkins: so it would be safe to allow them to care for name resolution<br> <fantasai> TabAtkins: that would be a consistent model, I'd be happy with that<br> <fantasai> TabAtkins: let's go through the first resolutions<br> <fantasai> astearns: So for now, @layer is invalid inside mixins<br> <fantasai> RESOLVED: @layer is invalid inside mixins (for level 1)<br> <fantasai> astearns: Should @mixin be invalid outside of @media / @supports, or discuss @layer?<br> <fantasai> emilio: I think consistent thing to do would be to allow them inside @container etc. but ignore the outer condition, like we're doing for @keyframes, @keyframes, @feature-values, etc.<br> <fantasai> emilio: but maybe more aggressive thing to do here, which is not allow mixins to be conditional at all<br> <fantasai> emilio: it mitigates the 2-pass thing<br> <fantasai> emilio: not sure how we feel about that<br> <fantasai> andruud: not even subject to media queries?<br> <fantasai> TabAtkins: Invalid inside @media?<br> <fantasai> TabAtkins: Then you cannot do a media-conditioned stylesheet include<br> <fantasai> TabAtkins: those are super common, so want to avoid if possible<br> <fantasai> emilio: sad we'd need to walk the rules twice. Gets worse and worse<br> <fantasai> andruud: and maybe more for custom media<br> <fantasai> andruud: we can come back to that point ...<br> <fantasai> andruud: need to decide if they are ordered by layer when inside @layer<br> <fantasai> andruud: Is that something we want? if layer is not allowed inside, can we do it?<br> <fantasai> emilio: No precedent for this, but similar thing for custom media stuff<br> <lea> Q: these rules that are ignored inside @scope, are they only ignored inside literal @scope, or also @import ... scope() ?<br> <fantasai> emilio: these parse-time kind of things would be more reasonable to implement and less weird if we made them more like a traditional programming language, where if it's not declared before use it's not declared, and is invalid<br> <fantasai> emilio: That would mitigate the perf concerns while allowing stuff to be conditional<br> <fantasai> emilio: so you could have the current mixin set while processing the stylesheet, and you add to that set as you progress through the stylesheet<br> <fantasai> TabAtkins: we have precedent -- layers work like that<br> <fantasai> emilio: That means we don't want to make them depend on layer order, but could maybe make it work<br> <fantasai> emilio: I think that mitigates the interactions among parse-time thingies<br> <fantasai> emilio: you can conceptually define a custom media query after applying a mixin and it would kinda work<br> <astearns> ack fantasai<br> <emilio> fantasai: I think making it order dependent is probably fine because people are going to declare it before use<br> <miriam> +1<br> <emilio> ... whether we allow it inside media / layer, we need to handle @import<br> <emilio> ... so you'd still need to handle the import level but not the rest<br> <emilio> ... that might be a way to start with something a bit simpler<br> <emilio> ... but disallowing inside conditional rules for L1 seems fine<br> <TabAtkins> emilio: I htink if we do declaration order thing, no problem making them conditional<br> <fantasai> emilio: I think if we do the parse-order thing, then no issue with making them conditional<br> <fantasai> emilio: With disallowing inside conditional rules, want to avoid having to figure out which mixins apply and which don't<br> <fantasai> emilio: if we do order thing, then can process everything in a single pass<br> <fantasai> emilio: it allows you to do conditional application just like you do layers<br> <fantasai> emilio: I think that's preferable<br> <fantasai> emilio: Mixins would be effectively a state in this pass where we compute the applicable rules<br> <fantasai> emilio: WebKit called it ruleset building, Gecko has something too<br> <fantasai> andruud: Are the mixin names affected by layer order?<br> <fantasai> emilio: that's a question to answer. I'd rather not<br> <fantasai> TabAtkins: I think it's independent at this point, could go either way<br> <fantasai> emilio: The layer where the mixin is define dalready exists, and you can compare them<br> <fantasai> emilio: So you can keep around the later mixin and layer order<br> <fantasai> andruud: At that point you can already figure out which is stronger<br> <fantasai> emilio: Yeah, you can calculate it on the fly<br> <fantasai> emilio: On one hand I'd like to think of mixins as independent of layers, as a "parse-time" feature, where you define things to apply<br> <fantasai> emilio: but if we're making conditional on MQ, can make it depend on layers<br> <fantasai> emilio: but either way it's non-problematic<br> <fantasai> TabAtkins: I propose you can put them inside the layer, and defer question of whether they respond to the layer strength<br> <fantasai> TabAtkins: only options are purely global, or if layered<br> <fantasai> TabAtkins: only matters if you have the same mixin name declared multiple times<br> <fantasai> andruud: we go with order-dependent, that way they can be valid in @media and @supports<br> <fantasai> emilio: we have to decide if valid inside @container and @scope<br> <fantasai> TabAtkins: Existing precedent of ignoring the conditional seems fine<br> <fantasai> emilio: we could file an issue to reconsider that, see if we could make these invalid at parse time rather than unconditionally applying<br> <fantasai> emilio: but I'd argue that we should be consistent with existing precedent<br> <fantasai> [several nodding]<br> <fantasai> emilio: and change all if we think it's worth the pain of changing<br> <fantasai> miriam: I agree<br> <fantasai> miriam: other precedent I note is that name-defining @rules are affected by layers<br> <fantasai> emilio: but @mixin is different, it's more like layers<br> <fantasai> fantasai: that's also affected by layering!<br> <fantasai> emilio: If we go with approach of, must declare before use, then not problematic either way<br> <fantasai> emilio: might be a bit weird but seems fine<br> <fantasai> astearns: So should we need resolution that mixins must be defined before use<br> <fantasai> astearns: any objections?<br> <fantasai> RESOLVED: Mixins have to be defined before use<br> <fantasai> fantasai: Do we want a similar resolution for custom MQ<br> <fantasai> astearns: any objections?<br> <fantasai> RESOLVED: Custom media queries need to be defined before use<br> <TabAtkins> (My only other approach I think could have worked for these resolutions would be to use pure lexical scoping, so they didn't leak outside of stylesheets. But that's pretty limiting.)<br> <fantasai> emilio: Let's make consistent with @keyframes etc. and file issue to change if we don't like it<br> <fantasai> astearns: objections to being consistent with @keyframes wrt where valid?<br> <fantasai> RESOLVED: @mixin is valid wherever @keyframes is valid<br> <fantasai> SUMMARY: Still open question of whether @mixin declarations are layered -- either way is acceptable implementation-wise<br> <fantasai> ACTION: TabAtkins to file issue on whether global name-defining things should be invalid inside contextual conditionsl such as @container or @scope<br> </details> -- GitHub Notification of comment by css-meeting-bot Please view or discuss this issue at https://github.com/w3c/csswg-drafts/issues/12417#issuecomment-3204738440 using your GitHub account -- Sent via github-notify-ml as configured in https://github.com/w3c/github-notify-ml-config
Received on Wednesday, 20 August 2025 08:02:35 UTC