w3c / csswg-drafts

CSS Working Group Editor Drafts
https://drafts.csswg.org/
Other
4.5k stars 665 forks source link

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

Open dbaron opened 9 months ago

dbaron commented 9 months ago

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 commented 9 months ago

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>
    • covered by whatwg/html#9830; technically an HTML issue rather than a CSS one
    • prototyped in Chromium behind "Experimental Web platform features"
    • Proposed resolution: express support for changing HTML to allow details and summary to be more styleable
  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.)

css-meeting-bot commented 9 months ago

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

The full IRC log of that discussion <dbaron> https://github.com/w3c/csswg-drafts/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 commented 6 months ago

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.

astearns commented 6 months ago

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

kbabbitt commented 6 months ago

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: https://github.com/whatwg/html/issues/10200#issuecomment-1998676547

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)

yisibl commented 6 months ago

I don't quite understand why there are only a limited number of CSS properties that can be used in ::marker, which severely restricts details from being a truly customizable styled component. The previous ::-webkit-details-marker did not have these restrictions.

A very common use case is when arrows need to be animated using the rotate property.

https://github.com/w3c/csswg-drafts/assets/2784308/add5858a-25b7-40cb-b2cb-9d3111920c58

image

yisibl commented 6 months ago

Here is a collection of requests to support more properties in ::marker.

dbaron commented 6 months ago

Yeah, I agree that we should probably make marker styling more flexible. I haven't yet dug in to propose an exact set of changes...

astearns commented 5 months ago

RESOLVED: Use ::details-content as the name for the pseudo-element for the part of <details> that opens and closes

annevk commented 5 months ago

Is it problematic that it's display: contents but details-content? I guess there's already "content" usage elsewhere that will be similarly hard to remember.

bkardell commented 5 months ago

Is it problematic that it's display: contents but details-content? I guess there's already "content" usage elsewhere that will be similarly hard to remember.

Imo, no.