[CSSWG] Minutes Telecon 2024-04-17 [css-cascade][css-nesting]

=========================================
  These are the official CSSWG minutes.
  Unless you're correcting the minutes,
 Please respond by starting a new thread
   with an appropriate subject line.
=========================================


CSS Cascade & Nesting
---------------------

  - TabAtkins introduced the proposal for issue #8738 (Figure out
      whether we're fine with "shifting up" bare declarations after
      rules) and proposed moving serialization into a separate issue
  - There were some concerns raised about author confusion given that
      it's easy to make a small change that would alter behavior.
  - The proposal was viewed as an improvement over the current spec
      text and there was a desire to make a change now before the
      current spec text becomes relied upon by authors.
  - The group discussed the likelihood of this being used by authors
      and the value of having it as something an author (especially in
      a tooling use case) could access vs the value of having
      well-defined and predictable magic.
  - Though there was some pushback to magic, the principle of taking
      the least user-facing approach had wide agreement.

  - RESOLVED: Tab specs @nest, with a note about @nest rules as a
              usable syntactic construct being something we might want
              to get rid of (Issue #8738)

===== FULL MEETING MINUTES ======

Agenda: https://lists.w3.org/Archives/Public/www-style/2024Apr/0003.html

Present:
  Rachel Andrew
  David Baron
  Kevin Babbitt
  Oriol Brufau
  Stephen Chenney
  Keith Cirkel
  Emilio Cobos Álvarez
  Yehonatan Daniv
  Matthieu Dubet
  Elika Etemad
  Paul Grenier
  Robert Flack
  Chris Harrelson
  Daniel Holbert
  Brian Kardell
  Brad Kemper
  Jonathan Kew
  David Leininger
  Vladimir Levin
  Alison Maher
  Romain Menke
  Miriam Suzanne
  Bramus Van Damme
  Lea Verou

Chair: astearns

Scribe: emilio
Scribe's scribes: TabAtkins & dholbert

CSS Cascade & Nesting
=====================

Figure out whether we're fine with "shifting up" bare declarations
    after rules
------------------------------------------------------------------
  github: https://github.com/w3c/csswg-drafts/issues/8738#issuecomment-2057868087

  TabAtkins: So, background... current spec for nesting allows you to
             interleave declarations with rules
  TabAtkins: The way it's handled in the syntax spec is that all the
             declarations get collected together
  TabAtkins: losing the order information relative to the rules
  TabAtkins: This appears to cause author confusion
  TabAtkins: particularly if you repeat the same declaration a few
             times between things
  TabAtkins: It also means that whenever we introduce mixins, the
             ability to make it work with nesting doesn't work well
  TabAtkins: so thought was, can we instead interpret declarations in
             between rules as if they were wrapped in another rule
  TabAtkins: it interacts nicely with cssRules etc
  TabAtkins: andruud added use counters and it seems it can probably be
             made

  TabAtkins: I proposed the change in the comment from the agenda
  TabAtkins: Basically collect declarations into a new type of atrule
             (tentative name `@nest`)
  TabAtkins: `@nest` doesn't do anything other than grouping the
             declarations
  TabAtkins: This is slightly different to wrapping the parent selector
  TabAtkins: So it improves our behavior when nesting declarations
             inside media queries
  TabAtkins: Everyone seemed happy with it, only question was about
             serialization which we'd move to a different issue
  TabAtkins: Authors can write it but it's not particularly useful for
             them to do so

  astearns: Before going to the queue, wanna say that we only need to
            resolve on the approach

  kbabbitt: A little uncertain about how this interact with the OM
  kbabbitt: was playing with an example
  <kbabbitt> .rule1 { font-family: serif; color: blue; }
  <kbabbitt> .rule2 { font-family: serif; @media (...) { ... } color:
             blue; }
  kbabbitt: If I do setProperty("color", "red")
  kbabbitt: does it know how to dig inside @nest?
  kbabbitt: or ends up not having an effect
  TabAtkins: The latter
  kbabbitt: That's a bit concerning
  kbabbitt: In this world setProperty I added an @media and suddenly
            that doesn't work anymore
  TabAtkins: I agree you can run into potentially confusing situations
             with this
  TabAtkins: but it's not incompatible with current usage

  emilio: It is unfortunate that that would stop working, but it's also
          a tradeoff that seems hard to avoid
  emilio: In the same example, if you set color in both locations, and
          you wanted to *keep* both color declarations (which is what
          needs to happen here), it becomes...
  emilio: Like, maybe you can discard the previous somehow. But if you
          want to keep the latter declaration you need a place to store
          it.
  emilio: So it seems hard to avoid unless we do even more invasive
          changes to the OM, like letting you represent both
          declarations and rules directly
  emilio: Not convinced that's worth it
  emilio: I also think we generally discourage mutations in CSSOM when
          they affect stylesheets.
  emilio: Doing so has pretty bad perf implications, it dedups shared/
          cached stylesheets.
  emilio: So not sure it's worth rejiggering to "fix" this case
  emilio: If you wrapped the decl in a *different* rule, it would also
          not be changed by setProperty()
  kbabbitt: To be clear, in my example the decl isn't in the @media
  emilio: Right, just saying that it's in an @nest, and if it were any
          other rule it wouldn't be surprising
  kbabbitt: Just concerned that adding an @media in the middle of a
            rule causes the behavior to change
  matthieud: In the issue we discussed using cssstyledeclaration, and
             that would avoid the issue
  emilio: That wouldn't fix this, you'd need the exact same logic to
          find the "correct" cssstyledeclaration to mutate

  lea: What if we have the property there but it's not enumerable
  lea: Like a property that gives you all the decls, and a
       non-enumerable getter that gives you non-interleaved properties
  lea: So normally you'd get the first set, but if you want to read a
       specific property you'd just all of them from @nests
  emilio: What if you have multiple?
  emilio: I agree that this setProperty() breakage is somewhat
          surprising/unfortunate. I don't see a great way of
          avoiding it.
  lea: I think we could design it to minimize the surprise
  lea: but we can't do this during the call
  lea: reading properties should work, and there's an unambiguous value
       for each property, reading them should give you correct
  emilio: I don't think it's worth complicating the OM substantially.
          The implicit rule is already magic, I don't want more.
  emilio: This is pretty fundamental to what we're discussing. If we
          want the latter rules to act like rules...
  lea: +1 for the proposed solution in general. Even though I do feel
       pretty strongly about the serialization issue, I think it's far
       better than the current situation _regardless_ of how
       serialization ends up working, so I think we should try to
       implement it asap before the current behavior starts being
       depended on. Far easier to change the serialization than how
       interleaved rules and declarations behave.
  <lea> To summarize the serialization issue, these rules are added
        magically to author code, so I think when serialized they
        should also be removed magically, so that author code can
        roundtrip better. This would mean somewhat surprising behavior
        in the extremely rare cases where authors actually wrote an
        @nest rule, but far less surprising in the huge majority of
        cases where authors did not actually write it.
  <lea> But perhaps more fundamental to the design of this feature, if
        authors have no reason to write it, should they even be able
        to? If not, that entirely solves the serialization issue, since
        we never need to handle it and it becomes a CSS OM detail
        rather than an actual CSS syntax feature.
  <lea> We may also want to consider adding a new CSS OM property to
        get *all* declarations, including the interleaved ones.
  emilio: You'd still need to come up with something to return from
          CSSNestRule.cssText or what not
  emilio: I think I'd rather avoid trying to hide the fact that we
          implicitly add this rule
  emilio: otherwise this kind of complexity proliferates and causes
          tons of edge cases everywhere that are bad for both authors
          end browser developers

  <dbaron> Is the behavior either with or without this change bad
           enough that CSS style guides will generally say not to use
           the interleaving feature (i.e., say to put all the
           declarations first)?
  <lea> dbaron, I don't think so, especially if we design the CSS OM so
        that it works in the largest possible set of cases

  matthieud: In general I don't think we need @nest
  matthieud: because we don't want authors to actually use it
  matthieud: it's just an implementation detail
  matthieud: all these serialization questions would go away if we
             didn't put it on the spec
  matthieud: One solution would be to be able to use multiple
             CSSStyleDeclarations
  matthieud: I think modifying CSSOM is a better solution
  matthieud: Adding a new at-rule that we don't want authors to be
             using is a good solution
  matthieud: I think it's pretty fundamental to this approach
  matthieud: I think the question is do we add a new at-rule or not
  matthieud: the setProperty issue is less of an issue
  emilio: Multiple CSSStyleDeclarations don't fix any of the weirdness
          that @nest introduces
  emilio: I think the at-rule is the most obvious path forward to fix
          this
  emilio: I think it's weird but it's the most obvious weirdness that
          we don't have to propagate to everywhere else
  emilio: I don't see how a different approach fixes the annoyances
          it'd introduce, without massive redesign work
  <lea> emilio you said an @rule can be implemented quickly. Would a
        CSS OM rule type that doesn't correspond to an actual syntactic
        rule take longer to implement?
  emilio: lea, somewhat? I don't think we have a precedent for anything
          like that

  TabAtkins: What's being brought up is about what's more convenient or
             predictable when reading and modifying the OM
  TabAtkins: when is that done, compared to writing CSS
  TabAtkins: tool writers do
  TabAtkins: but for anything that's not doing that specific thing, the
             most I've seen anybody do is copying stylesheets around
  TabAtkins: so actually modifying the OM is really rare
  TabAtkins: so any complexity we introduce there needs to be weighted
             against the relatively small audience
  TabAtkins: also, when I do this kind of thing I value more
             consistency / predictability
  TabAtkins: vs. convenient APIs
  TabAtkins: I think the @nest proposal keeps consistency for CSSOM
  TabAtkins: Anyways, let's resolve on keeping styles where they are
  TabAtkins: I need to write _something_
  TabAtkins: can't go "do this in an unspecified way"
  TabAtkins: unless anybody has a strong objection right now my plan is
             to put the proposal on the spec, open to change
  <dbaron> (does writing of polyfills tend to touch the OM, or just
           reparse everything from scratch?)
  <lea> dbaron, depends on the polyfill and how closely it tries to
        follow the actual syntax
  Lea: Tab, it's true that tool writers are a tiny minority of authors,
       but breaking tools has huge impact on authors, since a lot more
       authors _use_ tools than _write_ tools.

  Lea: To reply to Emilio’s earlier point, I think there is an
       underlying design principles issue. I don't think avoiding magic
       at all costs should be a goal; the right magic can make a huge
       usability difference, at the cost of implementation complexity.
       Magic becomes a problem when it's unpredictable for users, and/
       or when users cannot opt-out of it. Neither seems to be the case
       here (at least if we design this right).
  Lea: There one thing that is crucial to understand, emilio you said
       an @rule can be implemented quickly. Would a CSS OM rule type
       that doesn't correspond to an actual syntactic rule take longer
       to implement? Cause I agree we should contain the weirdness, not
       making this part of CSS syntax is a way to do that. Cause if
       authors _can_ write it, they will.
  emilio: Replying directly to that... then, you need to figure out all
          the APIs that are on CSSRule that... people expect to be able
          to call Stylesheet.insertRule, rule.cssText
  emilio: If that rule can't be written by authors, what does that do?
  lea: What is the reason to do insertRule in that case?
  emilio: If you're writing a tool that wants to move rules around.
          that's the consistency argument that TabAtkins was talking
          about
  <TabAtkins> Yup, having *one* object that acts differently from
              everything else inside of .cssRules is generally bad (and
              needs a fairly significant justification to break)
  emilio: If I want to filter the set of rules on a stylesheet and put
          them on another stylesheet, it seems reasonable that you'd be
          able to call insertRule with the cssText of every stylesheet
          you care about, but that doesn't work
  lea: Why does that need @nest { ...declarations...}?
  emilio: That's not a rule
  TabAtkins: That today would fail to parse. Would be a potential
             compat impact if we were to make that suddenly valid
  matthieud: Why would we use insertRule to insert declarations anyway?
  emilio: You'd use it to insert a nested rule
  lea: We do want to be able to use CSSOM to insert interleaved rules,
       so that does seem like a problem

  matthieud: I agree CSSOM is a very small audience
  matthieud: We should not introduce new complexity in the CSS spec
  matthieud: for that
  matthieud: only modifying CSSOM is less invasive
  matthieud: If you create new @-rules, then we need to explain it to
             all authors

  <lea> To summarize my position: 1. Ideally, @nest should only exist
        in the CSS OM, and insertRule() should accept raw decls 2. If
        that's not possible, then serialization should strip @nest 3.
        But even if @nest has to be serialized, that's still better
        than hoisting.

  fantasai: Wondering if it'd make sense to use the nesting at-rule
            concept in CSSOM but only in the OM, and stripping it out
            for serialization, and also have the first rule be
            represented in the same manner?
  fantasai: so it'd be in .style and .cssRules[0].style
  TabAtkins: Duplicating them would be inconsistent
  TabAtkins: @page does have declarations and rules
  matthieud: font-feature-values could take various at-rules and then a
             nested declaration

  emilio: The other option, a bit less weird perhaps, is:
  emilio: so right now, we're using this trick of a style rule with the
          & selector
  emilio: the idea behind @nest or whatever the name ends up being,
          would effectively be wrapping it in a style rule with a magic
          selector that represents the parent
  emilio: @nest is conceptually a style rule with a magic selector that
          doesn't get wrapped
  emilio: we could define such magic selector somehow
  emilio: Would that make people less worried about the OM shenanigans?
  TabAtkins: That wouldn't fix the problems that were brought up
  emilio: It would behave like @nest, and like bare declarations in
          @media. So less breaking change than what we've been
          discussing
  TabAtkins: Every issue discussed has been from being in a rule of
             *any* kind
  emilio: It doesn't happen if it's a style rule... I guess we need to
          explain the new selector
  TabAtkins: That sounds even more magical
  emilio: Just wondering if it would be more amenable. But I think
          @nest is the best solution, given the constraints. Just
          curious if people would prefer putting the magic in the
          selector list rather than the at-rule. But I don't mind
          either way

  Lea: Do note that this does not need to be set in stone, we can
       implement it as a hidden CSS OM rule type to minimize API
       surface and fix the immediate problem, and figure out how things
       like insertRule() would work later — and if we can't, we just
       promote it to a regular rule. But it's much harder to go the
       other way
  <astearns> +1 to start with the least user-facing change
  kbabbitt: I do agree that we need some kind of a solution, and I
            think @nest is better than the status quo
  kbabbitt: IIUC what emilio was proposing was making @nest explicitly
            with some sort of selector, it feels less magical
  kbabbitt: It doesn't solve the setProperty issue but it makes it so
            that if you have to confront that it becomes obvious
  <fantasai> +1 to lea
  <lea> +1 to astearns
  <ydaniv> +1 to both
  astearns: Does it sound reasonable to make @nest {} as a magic thing
            that authors can't write for now?
  lea: Wasn't it what matthieud proposed?
  matthieud: I was proposing using CSSStyleDeclaration
  matthieud: but this sounds a bit in the middle
  TabAtkins: If we make @nest parse invalid we can't round-trip
  TabAtkins: Anything we do here has significant complexity that makes
             corners of stuff behave weirdly
  astearns: Your point was that this wasn't affecting authors much
  TabAtkins: It does because we need to define @nest to not serialize
  lea: Yes, the idea was there would be no @nest in serialization
       for now

  emilio: I agree with TabAtkins for what it's worth
  emilio: if we settle on @nest then we switch to serialize it
  <lea> straw poll?
  <oriol> +1 to Tab and emilio
  emilio: doing this in two steps that can break code seems unnecessary
  TabAtkins: Really strongly against extra magic other than in parsing
  TabAtkins: unless there's a great argument for that, but I haven't
             heard one
  TabAtkins: the more changes we make here the more potential there is
             for compat risk
  TabAtkins: I'm close to objecting to things that put lots of magic in
             the CSSOM
  TabAtkins: the less magic is CSSStyleDeclaration
  lea: I think it's great, we have that object already
  emilio: I disagree. how can you make CSS Rules return something that
          isn't a CSS Rule?
  lea: cssstyledeclaration is the least surprising option. it already
       exists and fits this perfectly
  emilio: I disagree. Every time we introduce an @ rule, it causes
          things that [...]

  lea: Can we resolve that TabAtkins can write whatever makes him
       happy, and prioritize resolving on the additional issues ASAP,
       next week if possible?
  TabAtkins: sounds good to me
  fantasai: We'd like not to introduce @nest as an author-facing
            constructs
  fantasai: if this is a temporary step towards that then fine but...
  <lea> might be useful to do the straw poll anyway to get a sense of
        what people think, even if it doesn't guide the resolution

  astearns: Proposed: Let tab spec whatever, but note that user-facing
            @nest is something we want to get rid of
  astearns: Objections?

  RESOLVED: Tab specs @nest, with a note about @nest rules as a usable
            syntactic construct being something we might want to get
            rid of

  <lea> TabAtkins please mention the unresolved issues in the draft?

Received on Wednesday, 17 April 2024 23:42:20 UTC