html
html copied to clipboard
Define the `<selectedcontent>` element
The <selectedcontent> element is part of the customizable <select> proposal: https://github.com/whatwg/html/issues/9799
It allows authors to declaratively clone the contents of the currently selected <option> of a <select> and style it independently for use in a base appearance <select>'s button.
Some details on the cloning behavior, which were decided on in order to always make sure that the selectedcontent element is up to date and in order to reduce developer confusion:
- Cloning is done with an algorithm similar to the Node.cloneNode() function.
- Cloning is done synchronously at these times:
- When an
</option>end tag is parsed during HTML parsing. - A selectedcontent element is inserted, during its post-connection steps.
- Immediately before input and change events are fired on a select element.
- When the select.selectedIndex IDL is assigned to.
- When an
Fixes https://github.com/whatwg/html/issues/10520
The selectedcontent element has been discussed generally here: https://github.com/w3c/csswg-drafts/issues/10242
html-aria PR: https://github.com/w3c/html-aria/pull/528 html-aam PR: https://github.com/w3c/aria/pull/2344
- [x] At least two implementers are interested (and none opposed):
- Chrome
- Mozilla: https://github.com/mozilla/standards-positions/issues/1060
- WebKit: https://github.com/WebKit/standards-positions/issues/386
- [x] Tests are written and can be reviewed and commented upon at:
- https://wpt.fyi/results/html/semantics/forms/the-select-element/customizable-select/selectedcontent.tentative.html
- [x] Implementation bugs are filed:
- Chromium: Already implemented
- Gecko: https://bugzilla.mozilla.org/show_bug.cgi?id=1944403
- WebKit: https://bugs.webkit.org/show_bug.cgi?id=286642
- [x] MDN issue is filed: https://github.com/mdn/content/issues/37857
- [x] The top of this comment includes a clear commit message to use.
(See WHATWG Working Mode: Changes for more details.)
/form-control-infrastructure.html ( diff ) /form-elements.html ( diff ) /index.html ( diff ) /indices.html ( diff ) /infrastructure.html ( diff ) /interactive-elements.html ( diff ) /parsing.html ( diff )
It seems this is missing a lot of the boilerplate that new elements normally have as well as changes to content models, indexes, etc. See also this checklist at the top of source:
! Adding a new element involves editing the following sections:
! - section for the element itself
! - descriptions of the element's categories
! - images/content-venn.svg
! - syntax, if it's void or otherwise special
! - parser, if it's not phrasing-level
! - rendering
! - obsolete section
! - element, attribute, content model, and interface indices
Thanks!
- I added a dl with a bunch of metadata for the element itself.
- I didn't include this element in any categories
- I didn't update the content-venn image because I didn't add it to any categories.
- I didn't update syntax or parsing because it doesn't have any special rules and I didn't implement anything in the HTML parser for this.
- I didn't update rendering because I noticed that elements like
<div>and<span>don't have sections in there, and selectedoption is supposed to render like those elements. - I didn't update the obsolete section because nothing is becoming obsolete...?
- I updated the element and interface indexes
This still seems incomplete. Where does the button element indicate this element can be a descendant, for instance? If you don't adjust the categories, you still need to account for how the categories are used.
This still seems incomplete. Where does the
buttonelement indicate this element can be a descendant, for instance? If you don't adjust the categories, you still need to account for how the categories are used.
Thanks, I updated the content model of the button element
I just made some changes:
- Renamed from
<selectedoption>to<selectedcontent>based on the resolution in https://github.com/openui/open-ui/issues/1112 - Stopped observing mutations within the selected
<option>and replaced with<option>end tag parser cloning based on WHATNOT conversation and discussions in https://github.com/whatwg/html/issues/10520 and resolution in https://github.com/openui/open-ui/issues/825#issuecomment-2436124668
I just added a "disabled" concept to help prevent infinite loops during cloning due to putting a selectedcontent element inside multiple select elements, another selectedcontent element, or an option element.
I made the select.value and select.selectedIndex setters trigger cloning to follow this resolution: https://github.com/openui/open-ui/issues/1119#issuecomment-2450565150
In response to feedback from @dbaron, I made the one selectedcontent element which receives updates be the first one in tree order instead of the first one to be inserted. I also removed the select descendant selectedoption elements list.
Adding a proper backlink to: https://github.com/mozilla/standards-positions/issues/1142
I'm worried about breaking the implied invariant that the parser creates exactly one element node per (possibly implied) non-erroneous start tag. I don't at this time have a concrete end-to-end scenario of what badness exactly may ensue, but it's a bad sign about breaking an invariant leading to issues that then need addressing that there's already a remark about preventing infinite loops upthread and a separate issue about the timing of cloning (#10520).
In the error handling case where one element per start tag does not hold, the spec says "Create an element for the token for which the element node was created, in the HTML namespace" instead of cloning a formatting element. This is in response to https://www.w3.org/Bugs/Public/show_bug.cgi?id=6743 , which was motivated by avoidance of data flows from the live DOM into the tree builder algorithm. However, it looks like the option cloning as proposed could happen on the main thread in a way that does not affect the subsequent decisions of the tree builder algorithm.
Do I understand correctly that cloning into the regular DOM instead of a UA shadow DOM came from https://github.com/w3c/csswg-drafts/issues/10242#issuecomment-2250667040 ?
Do I understand correctly that cloning into the regular DOM instead of a UA shadow DOM came from https://github.com/w3c/csswg-drafts/issues/10242#issuecomment-2250667040 ?
Yes. We had many lengthy discussions about this, since cloning into shadow DOM avoids a few problems. But it also introduced a myriad of issues that were much more serious than the ones posed by cloning into regular DOM.
- @josepharhar: could you address Define the
<selectedcontent>element #10633 (review) by adding some detail to the commit message in the OP, especially around the cloning strategy we ultimately went with and how it relates to the discussion in Timing of cloning for the<selectedoption>element #10520?
Done. Copying into this comment too in case the commit message gets clobbered by the thing that updates the commit message with the build of the PR:
Some details on the cloning behavior, which were decided on in order to always make sure that the selectedcontent element is up to date and in order to reduce developer confusion:
- Cloning is done with an algorithm similar to the Node.cloneNode() function.
- Cloning is done synchronously at these times:
- When an
</option>end tag is parsed during HTML parsing. - A selectedcontent element is inserted, during its post-connection steps.
- Immediately before input and change events are fired on a select element.
- When the select.selectedIndex IDL is assigned to.
- When an
@domfarolino sorry, I missed your mention of me since I've already been mentioned in this thread, github doesn't make it clear when someone has been re-mentioned.
the html aam (2344) PR is waiting on this to merge. It hasn't had any updates since I made some wording changes to a note in February. There are various other HTML AAM PRs related to customizable select which are also ready to go once everything is ready to merge into the HTML spec.
the aria in html pr (528) is essentially ready to go as well. No more spec updates needed, just some issues to file against conformance checkers.
@josepharhar not sure if this is the PR to comment on or not, but per our chat discussion it's probably worth calling out that while <option label=foo> can be used with the customizable select, and will render a visible label for the option in the select's popup - if selected nothing will be returned to the selectedcontent element - since that works by cloning the descendants of the option, and in this care there are none.
Someone can still benefit from broader styling capabilities and still define option element label text using the attribute if their customized select does not contain a button part (and thus no selectedcontent element). Maybe it makes sense to call this out? that way, if someone does attempt to use label attributes when defining their options, it's made clear "if you want to do this, then you shouldn't use the button part/selectedconent elements. but, to have greater control, use child content of the option to define your labels, which will also allow for more styling capabilities for represented the selected content in the select's collapsed state.
or you know... word smith as you see fit
Thanks Scott! I added a note here: https://github.com/whatwg/html/pull/10633/commits/bcd9669f81aa55139c9c370ab29482a953d89f1a
Per https://github.com/mdn/content/pull/39411; "Dynamic modifications to the selected <option> element's content made after the <select> element has been created are not automatically cloned to the <selectedcontent> element, and must be manually updated by the developer."
This has usability and security risks. If the option can be updated without the content of the <selectedcontent> updating along with it without JS, this has the likelihood of leading to broken forms. It's also a security risk as the user may submit a form with an unintended value that is not visible due to malicious code.
We don't want to add anything to the web platform that may potentially break things, make a form control less accessible, or add any vulnerabilities.
If the option can be updated without the content of the
<selectedcontent>updating along with it without JS, this has the likelihood of leading to broken forms.
I don't think this is possible without JS. To get this behavior, you need JS manipulating the DOM in a very particular way: the <option> contents must be mutated after that <option> is appended to the <select>. If the site is using plain html and css, then <selectedcontent> should "just work" in all cases.
It's also a security risk as the user may submit a form with an unintended value that is not visible due to malicious code.
If the malicious code has DOM access, isn't this already true?
<select id=purchase_quantity>
<option value=1000000> 1 </option>
</select>
This would submit the value "1000000" even though the user sees "1".
If the site is using plain html and css, then
<selectedcontent>should "just work" in all cases.
If the site is using JS, will it ever break the <selectedcontent>? My understanding is that is can, and does.
<select id=purchase_quantity>
<option value=1000000> 1 </option>
</select>
while the above is currently and has always been possible, if the following is ever possible, the implementation needs to be fixed:
<select id=purchase_quantity>
<button>
<selectedcontent>1</selectedcontent>
</button>
<option selected> 10</option>
</select>
This being pseudo-markup: Where "selected" is not necessarily an attribute, but rather the current state
This PR won't be merged and will instead be included in a bigger PR including all customizable select PRs: https://github.com/whatwg/html/pull/10548
An element that modifies the page by adding/removing elements seems like a bad idea.
It will break any code that expects the structure of the html to be the same as it was served.