├── LICENSE.md ├── README.md ├── examples └── opacity-animation.html ├── phase-1.md └── tests-of-existing-behavior ├── no-triangle-display-block.html ├── no-triangle-webkit-details-marker.html ├── shadow-mode-open.html └── styling-attribute-selector-open.html /LICENSE.md: -------------------------------------------------------------------------------- 1 | All Reports in this Repository are licensed by Contributors 2 | under the 3 | [W3C Software and Document License](https://www.w3.org/Consortium/Legal/2023/software-license). 4 | 5 | Contributions to Specifications are made under the 6 | [W3C CLA](https://www.w3.org/community/about/agreements/cla/). 7 | 8 | Contributions to Test Suites are made under the 9 | [W3C 3-clause BSD License](https://www.w3.org/Consortium/Legal/2008/03-bsd-license.html) 10 | 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Improvements to `
` styling 2 | 3 | L. David Baron, , April-May 2023 4 | 5 | * Feedback: https://github.com/openui/open-ui/issues/744 6 | * [Explainer for work happening in phase 1](phase-1.md) 7 | 8 | ## Goals 9 | 10 | The HTML `details` element represents a 11 | [disclosure](https://open-ui.org/components/disclosure.research) widget. 12 | It can also be used as a part of an 13 | [accordion](https://open-ui.org/components/accordion.research) widget. 14 | However, there are many disclosure widgets on the web 15 | that do not use the `details` element. 16 | In many cases, the styling of these disclosure widgets 17 | is not achievable using the `details` element. 18 | 19 | We should instead be in a situation where stylability 20 | is not an obstacle to the use of the `details` element 21 | for the vast majority of disclosure widgets on the Web. 22 | 23 | ## User needs 24 | 25 | Developers regularly use disclosure and accordion widgets on the Web. 26 | Today, that often means that they build their own widget 27 | rather than using a widget provided by the platform. 28 | 29 | This proposal is suggesting that we add features that would enable 30 | developers to use the platform's widget in more cases 31 | (hopefully the vast majority of cases). 32 | Doing so would help users because 33 | it would make (or at least would enable making) 34 | the user experience 35 | more consistent, and generally better, in a number of areas: 36 | * keyboard shortcuts and focus handling, 37 | * exposure via ARIA to assistive technology, and 38 | * integration with browser features such as find-in-page. 39 | 40 | Reducing the need for developers to build their own widgets 41 | should also reduce the size of pages that use such widgets, 42 | which reduces the time and bandwidth needed 43 | for users to load those pages. 44 | 45 | ## Current implementation behavior 46 | 47 | Implementations in Chromium, Gecko, and WebKit all use Shadow DOM 48 | to implement the `details` element. However, it is not possible for 49 | pages to use this to override the behavior of the `details` element 50 | because: 51 | 52 | * `Element.attachShadow()` is 53 | [not allowed](https://dom.spec.whatwg.org/#dom-element-attachshadow) 54 | on the details element. 55 | This appears to be interoperably implemented 56 | ([Chromium](https://searchfox.org/mozilla-central/search?q=symbol:_ZNK7mozilla3dom7Element18CanAttachShadowDOMEv), 57 | [Gecko](https://source.chromium.org/search?q=%22Element::CanAttachShadowRoot%22&ss=chromium), 58 | [WebKit](https://github.com/WebKit/WebKit/blob/main/Source/WebCore/dom/Element.cpp#L2844)). 59 | * The user-agent shadow DOM used to implement `
` in 60 | all of Chromium, Gecko, and WebKit 61 | is closed (`Element.shadowRoot` is `null`) 62 | (see [test](tests-of-existing-behavior/shadow-mode-open.html)). 63 | 64 | In all three implementations, 65 | it is possible to completely remove the disclosure triangle 66 | as long as there is a `summary` element. 67 | However, it currently requires 68 | [using `display: block` on the summary in Chromium and Gecko](tests-of-existing-behavior/no-triangle-display-block.html) 69 | and 70 | [using `display: none` on a pseudo-element](tests-of-existing-behavior/no-triangle-webkit-details-marker.html) 71 | in WebKit. 72 | Neither technique works for the summary 73 | that is generated when no `summary` element is present. 74 | 75 | In all three implementations, 76 | attribute selectors (such as with `details[open]`) 77 | can be used to change styles based on whether a `details` is open 78 | (see [test](tests-of-existing-behavior/styling-attribute-selector-open.html)). 79 | 80 | ### Chromium and Gecko (common) 81 | 82 | Chromium ([source](https://source.chromium.org/search?q=%22details%20%3E%20summary:first-of-type%22&ss=chromium)) and 83 | Gecko ([source](https://searchfox.org/mozilla-central/search?q=details+%3E+summary%3Afirst-of-type&path=&case=false®exp=false)) 84 | treat the `summary` as a `list-item`, 85 | with the following styles: 86 | 87 | ```css 88 | details > summary:first-of-type { 89 | display: list-item; 90 | counter-increment: list-item 0; 91 | list-style: disclosure-closed inside; 92 | } 93 | details[open] > summary:first-of-type { 94 | list-style-type: disclosure-open; 95 | } 96 | ``` 97 | 98 | Pages can override these styles (except for the internal default summary, 99 | which in both engines has the same styles duplicated in the shadow DOM; 100 | Gecko using a linked stylesheet and Chromium using a style attribute). 101 | 102 | ### Chromium 103 | 104 | The `details` element [uses shadow DOM internally](https://source.chromium.org/search?q=%22HTMLDetailsElement::DidAddUserAgentShadowRoot%22&ss=chromium), 105 | containing a slot for the main summary (with a default summary child), 106 | and a slot for the remaining content. 107 | The assignment of the main summary to the slot for the main summary 108 | uses [custom C++ code](https://source.chromium.org/search?q=%22HTMLDetailsElement::ManuallyAssignSlots%22&ss=chromium) 109 | that calls the 110 | [imperative slotting API](https://html.spec.whatwg.org/multipage/scripting.html#dom-slot-assign). 111 | 112 | TODO: Check how usable `::marker` is 113 | 114 | ### Gecko 115 | 116 | The [`details` element](https://searchfox.org/mozilla-central/source/dom/html/HTMLDetailsElement.cpp) uses shadow DOM internally, 117 | containing a style sheet, 118 | a slot for the main summary (with a default summary child), 119 | and a slot for the remaining content. 120 | The assignment of the main summary to the slot for the main summary 121 | uses [custom C++ code](https://searchfox.org/mozilla-central/search?q=ShadowRoot%3A%3AGetSlotNameFor&path=&case=false®exp=false) that handles details specially, 122 | and assigns the main summary to the magic `internal-main-summary` slot name. 123 | 124 | TODO: Check how usable `::marker` is 125 | 126 | ### WebKit 127 | 128 | WebKit uses the [following styles](https://github.com/WebKit/WebKit/blob/main/Source/WebCore/css/html.css): 129 | 130 | ```css 131 | summary::-webkit-details-marker { 132 | display: inline-block; 133 | width: 0.66em; 134 | height: 0.66em; 135 | margin-inline-end: 0.4em; 136 | } 137 | ``` 138 | 139 | The [`details` element](https://github.com/WebKit/WebKit/blob/main/Source/WebCore/html/HTMLDetailsElement.cpp) uses shadow DOM internally, 140 | containing a slot for the main summary (with a default summary child), 141 | and a slot for the remaining content. 142 | The assignment of the main summary to the slot for the main summary 143 | uses [custom C++ code](https://github.com/WebKit/WebKit/blob/82faeb56882ce53ee0f979087645c0cbfa5db2bf/Source/WebCore/html/HTMLDetailsElement.cpp#L70) 144 | that overrides the named slotting mechanism, 145 | slotting the main summary into a slot named `summarySlot`. 146 | 147 | TODO: Check how usable `::-webkit-details-marker` is 148 | 149 | ## Requirements 150 | 151 | ### Replacement of disclosure triangle 152 | 153 | Most disclosure widgets want their own appearance for the open/closed indicator 154 | which by default is a disclosure triangle. 155 | It should be possible to customize its appearance based on open/closed state 156 | and also pseudo-classes like `:hover` and `:active`. 157 | 158 | ### Layout of parts of disclosure widget 159 | 160 | It should be possible to make arbitrary or nearly-arbitrary layouts 161 | of the disclosure triangle (or open/closed indicator), the summary, 162 | and the contents of the collapsable area of the widget. 163 | For example, it should be possible to position the open/closed indicator 164 | in different positions relative to the other parts (such as on the right side), 165 | and it should be possible to use these pieces 166 | as part of a flex or a grid layout. 167 | 168 | ### Animation 169 | 170 | It should be possible 171 | to have the opening/closing of the details widget animate, 172 | and for that animation to be styled with CSS transitions or animations. 173 | This includes both animation of the height (with appropriate clipping 174 | and maybe opacity) of the contents of the details, and possibly also 175 | animation of the marker (e.g., rotation of a marker triangle). 176 | 177 | ## Options 178 | 179 | The following are options we have for solving various parts of the 180 | above requirements. 181 | Many of them do not address the entire problem, 182 | so more than one of them is likely to be needed. 183 | 184 | ### Proposal #1: Hiding and replacing disclosure widget 185 | 186 | Hiding and rebuilding parts of a widget is a common approach 187 | for solving widget styling issues on the Web. 188 | It is [doable today](https://www.scottohara.me/blog/2022/09/12/details-summary.html#:~:text=Styling%20a%20disclosure%20widget) 189 | given the default styles for these elements. 190 | (Having standard styles across browser engines 191 | would slightly reduce the complexity of doing this.) 192 | 193 | This has the advantage of being a rather well-worn path, 194 | and also of allowing developers to replace the marker 195 | with whatever they want. 196 | It has the disadvantage that 197 | any keyboard behavior, focus behavior, and ARIA 198 | associated with the default marker is lost. 199 | However, if that behavior is common to the marker and the `summary` element 200 | then this less of a problem. 201 | 202 | ### Proposal #2: Pseudo-elements (new ones or `::part()`) 203 | 204 | We could have pseudo-elements to address 205 | the three pieces of the disclosure widget: 206 | the summary's container, the open/closed marker, 207 | and the container for the collapsable contents. 208 | These pseudo-elements could potentially address pieces that have 209 | a defined relationship with each other in user-agent shadow DOM content. 210 | 211 | The pseudo-elements themselves could be newly-defined CSS pseudo-elements. 212 | However, if this is defined in terms of user-agent shadow DOM, 213 | we also have the option of exposing `::part()` pseudo-elements 214 | from the defined user-agent shadow DOM, 215 | rather than minting new pseudo-elements. 216 | (This hasn't been done before, 217 | but does seem like something we could reasonably do. 218 | However, it was rejected in 219 | [CSS Working Group discussion](https://logs.csswg.org/irc.w3.org/css/2023-07-20/#e1555355) 220 | and in https://github.com/openui/open-ui/issues/702 .) 221 | 222 | The pseudo-element for the open/closed marker should probably be `::marker`, 223 | given the existing use of that pseudo-element, 224 | and that the main summary is currently specified as a `list-item`. 225 | 226 | Note that if we take this approach, the rules that 227 | [are currently specified in HTML as a `style` attribute](https://html.spec.whatwg.org/multipage/rendering.html#the-details-and-summary-elements) 228 | for the container of the collapsible contents 229 | should be respecified as UA style sheet rules using this pseudo-element, 230 | so that is at the UA sheet level of the cascade 231 | rather than the style attribute level. 232 | 233 | ### Proposal #3: Improved `::marker` styling 234 | 235 | Currently a 236 | [limited set](https://drafts.csswg.org/css-lists-3/#marker-properties) 237 | of properties apply to the `::marker` pseudo-element. 238 | 239 | It probably makes sense that many properties like position and float are 240 | not supported on `::marker` 241 | (see [test](tests-of-existing-behavior/marker-movement.html)). 242 | However, in the context of `details`/`summary`, 243 | it probably makes more sense than it does for lists 244 | to allow for repositioning of the marker. 245 | 246 | (The [CSS2.0 `marker-offset` property](https://www.w3.org/TR/2008/REC-CSS2-20080411/generate.html#markers) 247 | does not appear to be implemented 248 | [in Chromium](https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/core/css/css_properties.json5) 249 | or [in Gecko](https://searchfox.org/mozilla-central/search?q=marker-offset&path=&case=false®exp=false) 250 | or [in WebKit](https://github.com/WebKit/WebKit/blob/main/Source/WebCore/css/CSSProperties.json).) 251 | 252 | A number of use cases probably could be addressed by supporting 253 | additional properties on `::marker`, such as: 254 | * box model properties, 255 | * a property to say which side the marker goes on (though 256 | this would have similar questions regarding AT and focus order 257 | as those that exist for 258 | flex and grid properties that do visual reordering), 259 | 260 | ### Proposal #4: Shadow tree replacement 261 | 262 | [ This option was rejected during 263 | [CSS Working Group discussion](https://logs.csswg.org/irc.w3.org/css/2023-07-20/#e1555355). 264 | ] 265 | 266 | Given that major browser engine implementations all 267 | implement `details` using user-agent shadow DOM, 268 | it seems like one option for improving stylability of `details` 269 | would be to allow the replacement of the shadow DOM 270 | so that developers could arrange the relationship of the parts as they need. 271 | 272 | This faces the obstacle that of the DOM spec's restrictions 273 | on replacing the shadow DOM of the details element, 274 | plus the (new, I think) concept of allowing developers 275 | to replace a user-agent provided shadow DOM. 276 | These seem like somewhat major obstacles. 277 | 278 | On the positive side, it would do a good job of ensuring that developers 279 | can style the `details` element as they want. 280 | But developers who replace the shadow DOM 281 | would then be responsible for rebuilding the necessary 282 | key handling, focus behavior, and ARIA integration. 283 | 284 | ### Proposal #5: Support `flex` and `grid` insides on `list-item`s 285 | 286 | Currently the 287 | [specification](https://drafts.csswg.org/css-display-3/#typedef-display-listitem) 288 | allows only `flow` and `flow-root` as the inner display types for the 289 | inside of a `list-item`; `flex` and `grid` are not allowed. This means 290 | it is not possible to style the inside of a `summary` element as a flex 291 | or grid layout. 292 | 293 | This probably isn't a major problem, but it's worth noting here that we 294 | could adjust this if it were necessary to do so. 295 | 296 | ## See also 297 | * [Chromium bug 1469418](https://bugs.chromium.org/p/chromium/issues/detail?id=1469418) 298 | * [Mozilla bug 1856374](https://bugzilla.mozilla.org/show_bug.cgi?id=1856374) (display setting) 299 | * [CSS Working Group Minutes, 2023-07-20](https://lists.w3.org/Archives/Public/www-style/2023Sep/0019.html) 300 | -------------------------------------------------------------------------------- /examples/opacity-animation.html: -------------------------------------------------------------------------------- 1 | 2 | 27 |
28 | What does this summarize? 29 | 30 | It turns out it doesn't summarize very much. This is just a demo. 31 | So the contents are quite boring. 32 | But there's a decent amount of text here. 33 |
34 | -------------------------------------------------------------------------------- /phase-1.md: -------------------------------------------------------------------------------- 1 | # Improvements to `
` styling, phase 1 2 | 3 | L. David Baron, , May 2024 4 | 5 | * CSS standardization issue: [w3c/csswg-drafts#9879](https://github.com/w3c/csswg-drafts/issues/9879) 6 | * HTML standardization PR: [whatwg/html#10265](https://github.com/whatwg/html/pull/10265) 7 | 8 | This explainer describes the initial phase of changes proposed 9 | to improve styling of the `
` and `` elements. 10 | For more detail on the overall goals, see 11 | the [overall project explainer](README.md), 12 | which includes some alternatives that are not being done 13 | and some alternatives (particularly improvements to marker styling) 14 | that may still be done in the future. 15 | 16 | ## Goals 17 | 18 | The HTML `details` element represents a 19 | [disclosure](https://open-ui.org/components/disclosure.research) widget. 20 | It can also be used as a part of an 21 | [accordion](https://open-ui.org/components/accordion.research) widget. 22 | However, there are many disclosure widgets on the web 23 | that do not use the `details` element. 24 | In many cases, the styling of these disclosure widgets 25 | is not achievable using the `details` element. 26 | 27 | We should instead be in a situation where stylability 28 | is not an obstacle to the use of the `details` element 29 | for the vast majority of disclosure widgets on the Web. 30 | 31 | ## User needs 32 | 33 | Developers regularly use disclosure and accordion widgets on the Web. 34 | Today, that often means that they build their own widget 35 | rather than using a widget provided by the platform. 36 | 37 | This proposal is suggesting that we add features that would enable 38 | developers to use the platform's widget in more cases 39 | (hopefully the vast majority of cases). 40 | Doing so would help users because 41 | it would make (or at least would enable making) 42 | the user experience 43 | more consistent, and generally better, in a number of areas: 44 | * keyboard shortcuts and focus handling, 45 | * exposure via ARIA to assistive technology, and 46 | * integration with browser features such as find-in-page. 47 | 48 | Reducing the need for developers to build their own widgets 49 | should also reduce the size of pages that use such widgets, 50 | which reduces the time and bandwidth needed 51 | for users to load those pages. 52 | 53 | ## State prior to this proposal 54 | 55 | Prior to this proposal 56 | the specification text describing the rendering of the `
` 57 | and `` elements is 58 | the following [section](https://html.spec.whatwg.org/multipage/rendering.html#the-details-and-summary-elements) of HTML 59 | reproduced here in its entirety: 60 | 61 | > ```css 62 | > @namespace "http://www.w3.org/1999/xhtml"; 63 | > 64 | > details > summary:first-of-type { 65 | > display: list-item; 66 | > counter-increment: list-item 0; 67 | > list-style: disclosure-closed inside; 68 | > } 69 | > details[open] > summary:first-of-type { 70 | > list-style-type: disclosure-open; 71 | > } 72 | > ``` 73 | > 74 | > The details element is expected to render as a block box. The element is also expected to have an internal shadow tree with two slots. The first slot is expected to take the details element's first summary element child, if any. The second slot is expected to take the details element's remaining descendants, if any. 75 | > 76 | > The details element's first summary element child, if any, is expected to allow the user to request the details be shown or hidden. 77 | > 78 | > The details element's second slot is expected to have its style attribute set to "display: block; content-visibility: hidden;" when the details element does not have an open attribute. When it does have the open attribute, the style attribute is expected to be removed from the second slot. 79 | > 80 | > > [!NOTE] 81 | > > Because the slots are hidden inside a shadow tree, this style attribute is not directly visible to author code. Its impacts, however, are visible. Notably, the choice of content-visibility: hidden instead of, e.g., display: none, impacts the results of various APIs that query layout information. 82 | 83 | The structure of the shadow tree was implemented as described in Chromium, Gecko, and WebKit. 84 | 85 | That the disclosure triangle exists because it is a list item marker is implemented only in Chromium and Gecko; 86 | WebKit has a separate `::-webkit-details-marker` mechanism. 87 | 88 | All three of those engines 89 | interpret the prose above to restrict changes to the `display` property on the `
` element, 90 | and some also restrict changes on the `` element. 91 | 92 | ## Proposed changes 93 | 94 | This proposes a set of changes that improve the ability of authors to style these elements: 95 | * remove restrictions on the `display` property of these elements so that they can be styled with other display types (such as flexbox or grid) 96 | * specify the structure of the shadow tree more clearly (so that it is clear that the slots are siblings of each other, and their order) so that display types (such as flexbox and grid) that depend on the tree structure (and particularly on the lack of other intermediate containers) will produce interoperable results 97 | * add a `::details-content` pseudo-element to address the second slot so that a container for the "additional information" in the `
` element can be styled. 98 | 99 | For details, see: 100 | * CSS standardization issue: [w3c/csswg-drafts#9879](https://github.com/w3c/csswg-drafts/issues/9879) 101 | * HTML standardization PR: [whatwg/html#10265](https://github.com/whatwg/html/pull/10265) 102 | 103 | ## Related changes 104 | 105 | There are also a set of related changes that help to improve the ability to animate these elements, 106 | although these are not strictly part of this proposal: 107 | 108 | * [The `transition-behavior` property](https://drafts.csswg.org/css-transitions-2/#transition-behavior-property) 109 | (part of the `@starting-style` and `transition-behavior` focus area in [Interop 2024](https://wpt.fyi/interop-2024)) 110 | * [The `@starting-style` rule](https://drafts.csswg.org/css-transitions-2/#defining-before-change-style) 111 | (part of the `@starting-style` and `transition-behavior` focus area in [Interop 2024](https://wpt.fyi/interop-2024)) 112 | * [The ability to transition to/from auto heights](https://github.com/w3c/csswg-drafts/blob/main/css-values-5/calc-size-explainer.md) 113 | 114 | ## Examples 115 | 116 | The following [example](examples/opacity-animation.html) code causes the opacity and the height 117 | of a `
` element to animate when it opens and closes. 118 | 119 | ```css 120 | :root { 121 | interpolate-size: allow-keywords; 122 | } 123 | 124 | details { 125 | --open-close-duration: 500ms; 126 | } 127 | 128 | details::details-content { 129 | opacity: 0; 130 | height: 0; 131 | overflow-y: hidden; /* clip content when height is animating */ 132 | transition: content-visibility var(--open-close-duration) allow-discrete, 133 | opacity var(--open-close-duration), 134 | height var(--open-close-duration); 135 | } 136 | 137 | details[open]::details-content { 138 | opacity: 1; 139 | height: auto; 140 | } 141 | ``` 142 | -------------------------------------------------------------------------------- /tests-of-existing-behavior/no-triangle-display-block.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 11 | 12 |
13 | Test summary. 14 | 15 | Test details. 16 |
17 | 18 |
19 | Test details with no summary. 20 |
21 | -------------------------------------------------------------------------------- /tests-of-existing-behavior/no-triangle-webkit-details-marker.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 11 | 12 |
13 | Test summary. 14 | 15 | Test details. 16 |
17 | 18 |
19 | Test details with no summary. 20 |
21 | -------------------------------------------------------------------------------- /tests-of-existing-behavior/shadow-mode-open.html: -------------------------------------------------------------------------------- 1 | 2 | Is the shadow mode of a details element open? 3 | 4 |
5 | Test summary. 6 | 7 | Test details. 8 |
9 | 10 | 15 | -------------------------------------------------------------------------------- /tests-of-existing-behavior/styling-attribute-selector-open.html: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 |
12 | Test summary. 13 | 14 | Test details. 15 |
16 | 17 |
18 | Test details with no summary. 19 |
20 | --------------------------------------------------------------------------------