Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

improve styling of <details>/<summary> elements #9879

Open
dbaron opened this issue Jan 30, 2024 · 5 comments
Open

improve styling of <details>/<summary> elements #9879

dbaron opened this issue Jan 30, 2024 · 5 comments
Assignees
Labels
Agenda+ Async Resolution: Call For Consensus Resolution will be called after time limit expires

Comments

@dbaron
Copy link
Member

dbaron commented Jan 30, 2024

I'd like to discuss improvements to the styling of the <details> and <summary> elements.

At our face-to-face meeting in July 2023, I presented some thoughts on improvements, and we had a discussion (see minutes).

I'm hoping to have some updates to present during our face-to-face in February, though they're not ready yet.

@dbaron dbaron self-assigned this Jan 30, 2024
@dbaron
Copy link
Member Author

dbaron commented Feb 9, 2024

Based on the investigations we've done so far into styling of the <details> and <summary> elements, I can think of 6 separate technical pieces that are relevant to this issue (items 4 through 6 are relevant to animations of opening/closing the elements), in somewhat different states:

  1. Allowing general use of display on both <details> and <summary>
  2. Specifying the styles that create the disclosure triangle.
    • as discussed in https://github.com/dbaron/details-styling these differ between Chromium & Gecko on one side, and WebKit on the other side
    • having the underlying styles be consistent between implementations would allow authors to style more easily, and may also help with the previous point since WebKit's restrictions on summary { display: list-item } may be motivated by people writing styles to the Gecko/Chromium model
    • I think this is probably really an HTML issue rathen than a CSS one (need to get an issue filed!)
    • Proposed resolution: Express support for adopting the Gecko/Chromium styling model in which the summary is display: list-item and the disclosure triangle is its marker.
    • This is already mostly specified in the HTML spec (which Chromium and Gecko match).
  3. Add a pseudo-element for styling the anonymous container for all of the non-summary contents of a details element
    • I have currently prototyped this as ::details-content, but I'm open to a different name.
    • prototyped in Chromium behind "Experimental Web platform features"
    • Discussion topic: One thing that is awkward about using it is that it defaults to display: contents, which means that using it for anything requires changing it to display: block
    • Proposed resolution: Adopt the ::details-content pseudo-element.
  4. The transition-behavior property
  5. The @starting-style rule
  6. The ability to transition to/from auto heights.

There was another piece that I had prototyped (closely related to item 3 above), but removed from the prototype because it turned out to not be useful. This was the ::details-summary pseudo-element which styled the container for the <summary> element. Similar to ::details-content it was a little tricky to use because it defaulted to display: contents, and it didn't seem to add any value, only confusion about when to use it and when not to. (It's just a wrapper for a single element, the first summary child. It's potentially useful in the case where there is no summary child, but I think that's mostly an error case anyway.)

@astearns astearns added this to unsorted FTF in Feb 2024 Agenda Feb 11, 2024
@astearns astearns moved this from unsorted FTF to Tuesday afternoon in Feb 2024 Agenda Feb 11, 2024
@css-meeting-bot
Copy link
Member

The CSS Working Group just discussed improve styling of <details>/<summary> elements, and agreed to the following:

  • RESOLVED: Expose the <details> contents slot as either a pseudo or a ::part, as decided in a joint meeting with WHATWG
  • RESOLVED: We desire to have no restrictions on the stylability of the display of <details> and <summary>
The full IRC log of that discussion <dbaron> https://github.com//issues/9879#issuecomment-1936179742
<fantasai> dbaron: Most of what I'll say here is in that comment ^
<fantasai> dbaron: We discussed in Cupertino, and I did some prototyping since then.
<fantasai> dbaron: Seemed people were more comfortable with pseudo-element approach than others
<fantasai> dbaron: I prototyped that, also prototyped changes that allow more flexibility in what the display value of details and summary can be
<fantasai> dbaron: one of the major problems is that brosers restrict the display values of one or both
<fantasai> dbaron: restrictions on details are in the HTML spec actually
<fantasai> dbaron: Bramus took some passes building demos, various ways that design systems use for disclosure widgets, so that you can do those with details + CSS
<fantasai> dbaron: The pieces that were important to the demos were these six things
<fantasai> dbaron: some we've already resolved on, but not yet shipping in all engines
<fantasai> dbaron: 1. Changing display on details and summary
<fantasai> dbaron: that's technically an HTML spec problem, maybe we can record an agreement on changing
<fantasai> dbaron: 2. Specifying the styles that create the disclosure triangle
<fantasai> dbaron: this is not interoperable: chrome and firefox do one thing, and webkit does something different
<fantasai> dbaron: 3. Styling pieces of the widget that weren't addressable
<fantasai> dbaron: I prototyped 2 pseudo-elements, ::details-summary and ::details-content
<fantasai> dbaron: these address pieces already described in HTML spec
<fantasai> dbaron: I removed ::details-summary, because it wasn't useful and was just confusing
<fantasai> dbaron: since there's already an element there
<fantasai> dbaron: ::details-content wraps the rest of the content
<fantasai> dbaron: I hope we can resolve to add
<emilio> q+
<fantasai> dbaron: Next is 3 pieces related to animation, super common
<fantasai> dbaron: When Bramus built demos, two features from Transitions L2 and Interop 2024 are well on the path of shipping
<fantasai> dbaron: transition-behavior property
<fantasai> dbaron: Last piece resolved to draft into Values 5, transition to/from `auto` heights
<fantasai> dbaron: was hoping to show a prototype, but not quite done
<fantasai> dbaron: People have wanted this in many contexts for over a decade
<fantasai> dbaron: separate problem that's large, not in Bramus's demos, but important piece of the puzzle
<astearns> ack emilio
<fantasai> emilio: Is ::details-content pseudo-element just the <slot> ?
<Rossen_> q?
<nicole> q+
<fantasai> emilio: alternative would be that the author wraps a bunch of stuff
<fantasai> dbaron: yes, and ability to write generic styles, I think it's better if author doesn't have to write extra markup
<fantasai> emilio: given spec uses shadow DOM, maybe use ::part
<fantasai> dbaron: that's the discussion from Cupertion
<astearns> ack nicole
<fantasai> s/tion/tino/
<fantasai> nicole: Do other engines have a good way to do transitions to/from auto?
<fantasai> dbaron: of the 6 things on the list, that's the proposal in the earliest stage
<fantasai> dbaron: we drafted into the ED last Friday, and prototyping now
<fantasai> dbaron: There are a bunch of things that we need to experiment with as part of prototyping
<oriol> q+
<fantasai> dbaron: Don't want to discourage other implementations trying, but currently just trying to figure things out with the prototype now
<fantasai> iank_: probably doable but slightly more work in other engines, but not 10x factor, maybe 2-3x factor
<fantasai> dbaron: layout side requires some refactoring of existing height calculation code
<fantasai> dbaron: Chromium's engine was recently written, so maybe other engines need more refactoring
<fantasai> nicole: ...
<fantasai> emilio: Everything is doable...
<fantasai> emilio: Whatever people do for disclosure widgets now to transition to/from `auto`, I guess you can do with JS as well
<fantasai> emilio: so open the thing, measure it, then close it and animate to what you measured
<fantasai> nicole: or slide it down so it looks like growing but not
<fantasai> emilio: can do it now with JS
<fantasai> dbaron: make it easier to do
<fantasai> emilio: The first 3 things are not possible even without JS, so those are more important to me in terms of relative priority
<fantasai> nicole: a lot of developers won't use a thing that can't be animated
<fantasai> emilio: but already can animate as well as you can animate other things
<fantasai> dbaron: these things are somewhat separable, they are pieces of the puzzle to make styling these better
<fantasai> dbaron: some more necessary than others
<fantasai> emilio: first 3 things give you the static styling that you want
<fantasai> emilio: 4-5-6 allow declarative animations, but even now could use JS
<fantasai> emilio: 1-2-3 gives you what you can build right now by yourself, but with better a11y and interaction behavior
<fantasai> emilio: 4-5-6 just makes it easier to do animations
<astearns> ack oriol
<fantasai> oriol: Wrt ::details-summary, you thought it wasn't useful, but the <summary> element can be eliminated
<fantasai> oriol: and then automatically generated
<bkardell_> q+
<fantasai> oriol: then might need it?
<astearns> zakim, close queue
<Zakim> ok, astearns, the speaker queue is closed
<fantasai> dbaron: Yes, but I can't convince myself that omitting <summary> is a good practice that we should design around.
<fantasai> bramus: If you add some padding onto ::details-summary, doesn't work because display: contents
<fantasai> bramus: depending on what you do, have to target ::details-summary or summary
<astearns> ack bkardell_
<fantasai> fantasai: I think I agree with dbaron that this isn't necessary, so if we all agree, let's not go into the details.
<fantasai> bkardell_: The ::details-content pseudo-element, wondering if you could use it to force it open in certain layouts
<fantasai> dbaron: you could
<fantasai> dbaron: need ::details-content { display: block; content-visibility: initial; } but can force it open that way
<bkardell_> 🔥
<astearns> zakim, open queue
<Zakim> ok, astearns, the speaker queue is open
<fantasai> bramus: I used 1,3,4,6 for my demos
<fantasai> bramus: wrt disclosure triange, I think authors would want to be able to pick the content that they want for that triangle
<fantasai> emilio: couldn't you use list-style: <image>
<fantasai> dbaron: in Gecko/Blink yes; not WebKit
<fantasai> emilio: I think per spec you're supposed to have `display: list-item` so you can style the marker
<fantasai> emilio: webKit has it's own weird pseudo
<fantasai> +1
<fantasai> bramus: I haven't explored that part, I explored can we animate the details when it opens and closes
<fantasai> bramus: wrt basics, I tried changing layout, e.g. using flex/grid
<fantasai> bramus: [shows off some flexbox styles]
<fantasai> bramus: [shows off demo of a rectangle like [ * I am the summary | ... blank ... ] which then grows taller and fills in sevreal paragraphs in the right half
<fantasai> florian: if line-clamp worked, you could make it visible and clamp it
<fantasai> emilio: I think this should be possible to do without fixed height
<fantasai> bramus: Also tried grid, using grid templates
<fantasai> bramus: it was really nice to use
<fantasai> bramus: Then I added animation, and things go tinteresting
<fantasai> bramus: First styling and animating the pseudo element
<fantasai> bramus: gave it some transition of the border between the summary and details, as well as expanding and contracting the content
<fantasai> bramus: might need step-end/step-start
<fantasai> bramus: Then I needed to transition `content-visibility`, needed allow-discrete
<fantasai> bramus: I wanted padding around the content as 1em, but can only add that when the element is open
<fantasai> dbaron: This is the difference between content-visibity and display
<fantasai> emilio: WebKit and Gecko use display to hide the details content, and blink uses content-visibility (which is what the spec says)
<fantasai> emilio: seems to me that we should get interop there relatively soon
<fantasai> fantasai: why content-visiblity?
<fantasai> emilio: so you can search its contents
<dholbert> scribe+
<dholbert> fantasai (IRC): content-visibility naming is not great for this
<dholbert> fantasai (IRC): ideally this would use content-visibility:collapse or something, if that existed
<fantasai> s/visibility/display/
<fantasai> bramus shows the jump when the intervening border gets removed
<fantasai> bramus: Also tried animating with a div instead of the pseudo
<fantasai> bramus: but there was a glitch towards the end
<fantasai> bramus: because content-visibility, I needed to force it to be visible when it's open to change the padding/height
<fantasai> emilio: isn't that just ecause you're using box-sizing: content-box
<fantasai> dbaron: even then, you still can't set it so that the content-box height is smaller than zero
<fantasai> bramus: another approach I styled the div, and animated the pseudo, so the pseudo acts like a curtain over the DIV
<fantasai> bramus: this gives the desired effect
<fantasai> bramus: [shows off UIKit style demo]
<fantasai> bramus: I was able to do this by styling the DIV and animating the pseudo on top of it
<fantasai> bramus: essentially same animation code throughout all the demos
<fantasai> bramus: [shows off horizontal accordion]
<fantasai> bramus: Demo for half-opened disclosure widget for "read more" / "read less"
<fantasai> bramus: To summarize this, setting different display modes on display/summary allows us to build out a lot of use cases
<fantasai> bramus: the ::details-content pseudo is necessary to make the animations, but it's kind weird
<fantasai> bramus: I also found it necessary to add an extra DIV to make it work
<fantasai> bramus: transition-behavior works nicely, and transitions to/from auto would help
<bramus> Links
<bramus> https://goo.gle/styling-details-exploration
<Rossen_> q?
<bramus> https://goo.gle/styling-details-demos
<fantasai> dbaron: If no one on the queue, then I will propose some resolutions!
<fantasai> dbaron: Propose to add ::details-content pseudo-element. No opinion about the name, but seemed reasonable
<emilio> q+
<fantasai> dbaron: In some ways I think pseudo-elements are different from pseudo-classes, because with pseudo-classes there is more value in having things common across multiple features
<fantasai> dbaron: but for pseudo-elements, we will want more specific names for the things we're introducing
<fantasai> dbaron: that's what led to the proposed name
<fantasai> dbaron: it's something specific to <details>
<astearns> ack emilio
<fantasai> nicole_: harder to be meaningful if too generic of a name
<fantasai> emilio: can we resolve on pseudo-element vs ::part?
<fantasai> emilio: seems clear that HTML spec is using shadow DOM, and if you use ::part can just do ::part(content) and don't need to be too specific
<fantasai> emilio: less special-casing
<nicole> q+
<fantasai> emilio: idk if we had that discussion
<fantasai> dbaron: we didn't resolve in Cupertino, but seemed Apple was against using ::part
<fantasai> dbaron: my memory was also the HTML spec editors weren't happy either
<fantasai> nicole: Yes, that discussion happened. There was a sense of exposing an implementation detail.
<fantasai> TabAtkins: we already expose that there's a shadow DOM because it has one already from the UA
<fantasai> dbaron: The idea was using ::part() for author-controlled shadow DOM, not for UA stuff
<emilio> chrishtr: html editors said that ::part() is for authors
<TabAtkins> chrishtr: I think the HTML editor's concern was about ::part() being an author namespace that we didn't want to get into
<fantasai> nicole: We would support the proposal of pseudo-elements, but not ::part()
<fantasai> matthieud: we don't want to expose the shadow DOM
<TabAtkins> TabAtkins: But there's no namespace collision issues here. Each individual shadow is its own namespace; the UA controls that shadow, so they control the parts too.
<fantasai> emilio: you're already exposing that information, e.g. you need to override `content-visibility` which is set on the slotp
<fantasai> nicole: It is unusual though. Form controls might use web components, but they don't expose their parts that way
<TabAtkins> TabAtkins: Plus if it's a ::part(), you can export it to your own component. Like `<my-widget><::shadow><details exportparts=content>...`, then `my-widget::part(content)` works
<fantasai> chrishtr: Consistency with the other parts of the platform is also reasonable to have
<fantasai> emilio: My understanding from OpenUI was the idea of exposing components
<TabAtkins> (But with a custom pseudo-element, `my-widget::part(details)::details-content` does not work.)
<fantasai> chrishtr: OpenUI did go in that direction, and WHATWG editors didn't like it
<fantasai> chrishtr: to distinguish pseudo-elements provided by UA vs author
<fantasai> TabAtkins: We need to push back on that idea
<fantasai> astearns: [missed]
<TabAtkins> TabAtkins: If that is an accurate summary of their position, then they were making decisions based on some incorrect assumptions.
<fantasai> emilio: part attribute needs to be set by the engine, because it's a closed shadow tree
<fantasai> emilio: It's not available to authors, but it's defined in HTML spec
<fantasai> dbaron: I didn't try it because the discussion in Cupertino seemed so strongly against
<fantasai> emilio: Can we resolve to add some syntax for it, and bring ::part vs pseudo to the HTML editors/
<fantasai> chrishtr: We need to align on a design pattern, but how do we come to an agremeent?
<astearns> ack nicole
<fantasai> emilio: ::part is superior here in complexity and functionality
<fantasai> emilio: I understand being reluctant on form controls, because those left more undefined
<fantasai> [general confusion how to make decisions]
<TabAtkins> fantasai: I think I agree with Chris that it's nice to be consistent about these sorts of features.
<dbaron> [how to make decisions where WHATWG HTML, CSS, and OpenUI CG disagree]
<astearns> ack fantasai
<TabAtkins> fantasai: It's clear that form controls won't use ::part(), so I think it makes sense from consistency to provide a ccustom pseudo-element here too, even if you could have expressed it with ::part()
<emilio> q+
<astearns> ack dbaron
<TabAtkins> dbaron: I think the assumption taht form controls won't do it iwth ::part() isn't necessarily true
<fantasai> dbaron: Assumption that form controls don't do that isn't necessarily true, ongoing work in Open UI to build interoperable styleable form controls
<fantasai> dbaron: which might end up exposing ::part
<fantasai> dbaron: most advanced discussions are on <select>, which has evolved a lot in the last 6 months
<astearns> ack emilio
<fantasai> emilio: fact that form controls don't use ::part is because we didn't have ::part when form controls were implemented
<fantasai> emilio: in fact, WebKit implementation itself uses a different attribute to do what part does
<dbaron> s/last 6 months/last 6 months, although maybe in a direction where that one in particular doesn't depend on this decision/
<fantasai> nicole: Fundamentally, how web developers are meant to interact with creating web content, and is there difference in built-in controls vs those created by authors
<fantasai> nicole: Seems clear to me that built-in controls should have simple interface, and not expose things under the shadow surface
<fantasai> emilio: if we do ::part, needs to be in HTML spec, so we should bring it up and get consensus there
<fantasai> chrishtr: So should we say that we defer to WHATWG?
<fantasai> astearns: We need consensus among all the implementers
<fantasai> emilio: We can agree on exposing the slot as either a pseudo or ::part
<fantasai> emilio: I don't get the argument Nicole makes, because you need to be aware of the styling of the shadow DOM in order to style these widgets
<fantasai> astearns: Let's resolve on exposing this as a pseudo or a ::part depending on the WHATWG discussion
<fantasai> emilio: it would be great to have both groups aligned
<fantasai> TabAtkins: I'll open an issue to centralize this discussion
<fantasai> emilio: Especially since this may impact future decisions as well, so we need to be clear why we're doing X rather than Y
<fantasai> PROPOSED: Expose the slot as either a pseudo or a ::part, depending on the WHATWG discussions
<fantasai> chrishtr: Let's make it clear that we'll decide in that group, and invite anyone who wants to participate
<fantasai> florian: Are we deferring or having a joint session?
<fantasai> PROPOSED: Expose the details slot as either a pseudo or a ::part, as decided in a joint meeting with WHATWG
<fantasai> s/slot/contents slot/
<fantasai> RESOLVED: Expose the <details> contents slot as either a pseudo or a ::part, as decided in a joint meeting with WHATWG
<fantasai> dbaron: We would like display of details and summary to be as styleable as possible
<fantasai> Various: Yes, please.
<emilio> q+
<fantasai> chrishtr: As far as you see, there should be no restriction?
<fantasai> dbaron: I don't see any reason for restrictions. We might find Web-compat reasons.
<astearns> ack emilio
<fantasai> dbaron: I don't think any technical reasons other than compat
<fantasai> emilio: Ironically, the reason for this restriction was because not all implementations were not using shadow DOM
<emilio> TabAtkins: yeah, flex would expose the number of child elements of the details and so on
<emilio> PROPOSED: We desire to have no restrictions on the stylability of the display of <details> and <summary>
<emilio> RESOLVED: We desire to have no restrictions on the stylability of the display of <details> and <summary>
<fantasai> dbaron: A few things to note about the demos, that we might want to solve
<fantasai> dbaron: One thing that was awkward was always needing to add `display: block` to the slot
<fantasai> dbaron: it is possible that we might want to make it the default
<emilio> q+
<fantasai> dbaron: yes, <slot> is display: contents; but maybe for <details> element maybe we make it `display: block`
<astearns> ack emilio
<fantasai> emilio: I think we should decide on this soon
<fantasai> emilio: if you had a flex details, that changes the number of flex items
<fantasai> emilio: so we should go one way or the other before we ship unrestricted display
<fantasai> emilio: would be ironic if it's needed for compat
<fantasai> emilio: I'm not opposed, might be use cases for turning back to `display: contents`
<fantasai> chrishtr: he's not proposing to require, just change the default
<fantasai> bramus: for authors it'll be less surprising
<fantasai> emilio: we need to ship content-visibility details first
<fantasai> dbaron: I think all engines do it in terms of shadow DOM, and <slot> defaults to `display: contents`
<fantasai> emilio: ...
<fantasai> dbaron: I should look into whether this is changeable
<fantasai> dbaron: Another issue was border and padding messing up the animation. I don't have an answer, but it seemed annoying repeatedly

dbaron added a commit to dbaron/html that referenced this issue Apr 9, 2024
This makes a number of related changes to specify the rendering of the
<details> element:

* It specifies the structure of the user agent shadow tree.  This
  appears largely interoperable between implementations with the
  exception of the style or link element for the default summary styles:
  Gecko uses a link element as the first child, Chromium uses a style
  element as the last child, and WebKit does not use a style element
  (see below).  This specifies a style or link as the first child.
* It specifies the existence of the default summary and the presence of
  UA dependent text inside of it.  This is present in all of Chromium,
  Gecko, and WebKit.
* It specifies the styles needed for the default summary.  These match
  Chromium and Gecko.  (These are not present in WebKit because WebKit's
  mechanism for styling the marker does not match the existing spec.)
* It removes the restriction that <details> is a block and cannot be
  changed.  This is prototyped in Chromium and Gecko.  This fixes whatwg#9830.
* It specifies that the summary element is display: block by default.
  This matches all of Chromium, Gecko, and WebKit.
* It specifies which element matches the ::details-content
  pseudo-element.  (TODO: This needs to be specified in CSS)  This is
  prototyped in Chromium.

See w3c/csswg-drafts#9879 and
w3c/csswg-drafts#9951 for more background.
@dbaron
Copy link
Member Author

dbaron commented May 9, 2024

At this point the discussion in #9951 and the edits for #10083 have resolved on many of the issues that were blocking resolution here. The one point that I don't think we resolved on (unless I missed it) was the name of the pseudo-element. I'd like to resolve to use ::details-content as the name for the pseudo-element for the part of the <details> that opens and closes. I'm adding Agenda+ for that, although it's possible we could also do it as an asynchronous resolution given that it's already been discussed a bit.

@dbaron dbaron added the Agenda+ label May 9, 2024
@astearns astearns added the Async Resolution: Proposed Candidate for auto-resolve with stated time limit label May 10, 2024
@astearns
Copy link
Member

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: Use ::details-content as the name for the pseudo-element for the part of <details> that opens and closes

@astearns astearns added Async Resolution: Call For Consensus Resolution will be called after time limit expires and removed Async Resolution: Proposed Candidate for auto-resolve with stated time limit labels May 13, 2024
@kbabbitt
Copy link

No objection to the proposal. The previous resolution called for a joint meeting with WHATWG; for anyone like me who was looking for the outcome of that discussion, it's in the minutes here: whatwg/html#10200 (comment)

RESOLUTION: We will use pseudo-elements for exposing styling of pieces of built-in controls. We would like these pseudo-elements to be as close to ::part() as possible (for example, in terms of what selectors work and how inheritance works) and intend to further explore the details of how to do this. (9 votes in favor, none opposed)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Agenda+ Async Resolution: Call For Consensus Resolution will be called after time limit expires
Projects
Feb 2024 Agenda
Tuesday afternoon
Development

No branches or pull requests

4 participants