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

Editorial review: Document customizable <select> elements #38470

Open
wants to merge 25 commits into
base: main
Choose a base branch
from

Conversation

chrisdavidmills
Copy link
Contributor

@chrisdavidmills chrisdavidmills commented Mar 5, 2025

Description

Chrome 134 supports customizable <select> elements (see https://chromestatus.com/feature/5737365999976448).

This includes a multitude of sub-features, which are as follows:

  • The <selectedcontent> element mirrors the currently-selected <option> contents. This is the content visible inside the closed <select> element, otherwise known as the select <button>.
  • The ::picker(select) pseudo-element, which targets the entire contents of the select drop-down menu, otherwise known as the picker.
  • The appearance property value base-select, which opts the <select> element and the ::picker(select) pseudo-element into the browser-defined default styles and behavior for customizable select.
  • The :open pseudo-class, which can now target the select <button> when the picker (::picker(select)) is open.
  • The ::picker-icon pseudo-element, which targets the picker icon inside the select <button> — the little down-facing arrow on the inline-end side.
  • The :checked pseudo-class, which can now target the currently-selected <option> element.
  • The ::checkmark pseudo-element, which targets the checkmark placed inside the currently-selected <option> element to provide a visual indication of which one is selected.

In addition, the select <button> and the picker have the following behavior assigned to them automatically:

  • They have an invoker/popover relationship, as specified by the Popover API.
  • They have an implicit anchor reference, meaning that the picker is automatically positioned relative to the select <button> via CSS anchor positioning.

This PR aims to document all of the above new/updated features, and:

  • provide a guide to creating customizable <select>s.

Motivation

Additional details

Related issues and pull requests

Fixes #37857

BCD: mdn/browser-compat-data#26171

@chrisdavidmills chrisdavidmills requested a review from a team as a code owner March 5, 2025 18:09
@chrisdavidmills chrisdavidmills requested review from hamishwillee and removed request for a team March 5, 2025 18:09
@chrisdavidmills chrisdavidmills marked this pull request as draft March 5, 2025 18:09
@github-actions github-actions bot added Content:Learn Learning area docs size/m [PR only] 51-500 LoC changed labels Mar 5, 2025
Copy link
Contributor

github-actions bot commented Mar 5, 2025

Preview URLs (30 pages)
Flaws (40)

Note! 16 documents with no flaws that don't need to be listed. 🎉

URL: /en-US/docs/Learn_web_development/Extensions/Forms/UI_pseudo-classes
Title: UI pseudo-classes
Flaw count: 2

  • broken_links:
    • /en-US/docs/Glossary/void_element is ill cased
  • macros:
    • Macro produces link /en-US/docs/Glossary/void_element which is a redirect

URL: /en-US/docs/Learn_web_development/Extensions/Forms/Other_form_controls
Title: Other form controls
Flaw count: 2

  • broken_links:
    • /en-US/docs/Glossary/void_element is ill cased
  • macros:
    • Macro produces link /en-US/docs/Glossary/void_element which is a redirect

URL: /en-US/docs/Learn_web_development/Extensions/Forms/Sending_and_retrieving_form_data
Title: Sending form data
Flaw count: 2

  • broken_links:
    • /en-US/docs/Glossary/submit_button is ill cased
  • macros:
    • Macro produces link /en-US/docs/Glossary/submit_button which is a redirect

URL: /en-US/docs/Learn_web_development/Extensions/Forms/Basic_native_form_controls
Title: Basic native form controls
Flaw count: 2

  • broken_links:
    • /en-US/docs/Glossary/void_element is ill cased
  • macros:
    • Macro produces link /en-US/docs/Glossary/void_element which is a redirect

URL: /en-US/docs/Learn_web_development/Extensions/Forms/HTML5_input_types
Title: The HTML5 input types
Flaw count: 2

  • broken_links:
    • /en-US/docs/Web/API/validityState/typeMismatch is ill cased
  • macros:
    • Macro produces link /en-US/docs/Web/API/validityState/typeMismatch which is a redirect

URL: /en-US/docs/Learn_web_development/Extensions/Forms/Your_first_form
Title: Your first form
Flaw count: 2

  • broken_links:
    • /en-US/docs/Glossary/void_element is ill cased
  • macros:
    • Macro produces link /en-US/docs/Glossary/void_element which is a redirect

URL: /en-US/docs/Learn_web_development/Extensions/Forms/Sending_forms_through_JavaScript
Title: Sending forms through JavaScript
Flaw count: 2

  • broken_links:
    • /en-US/docs/Glossary/progressive_web_apps is ill cased
  • macros:
    • Macro produces link /en-US/docs/Glossary/progressive_web_apps which is a redirect

URL: /en-US/docs/Learn_web_development/Extensions/Forms/How_to_build_custom_form_controls
Title: How to build custom form controls
Flaw count: 6

  • broken_links:
    • /en-US/docs/Web/API/element/classList is ill cased
    • /en-US/docs/Web/API/element/querySelector is ill cased
    • /en-US/docs/Web/API/element/querySelectorAll is ill cased
  • macros:
    • Macro produces link /en-US/docs/Web/API/element/classList which is a redirect
    • Macro produces link /en-US/docs/Web/API/element/querySelector which is a redirect
    • Macro produces link /en-US/docs/Web/API/element/querySelectorAll which is a redirect

URL: /en-US/docs/Learn_web_development/Extensions/Forms/HTML_forms_in_legacy_browsers
Title: HTML forms in legacy browsers
Flaw count: 1

  • unknown:
    • No generic content config found

URL: /en-US/docs/Learn_web_development/Extensions/Forms/Customizable_select
Title: Customizable select elements
Flaw count: 3

  • broken_links:
    • /en-US/docs/Glossary/top_layer is ill cased
  • macros:
    • Macro produces link /en-US/docs/Glossary/top_layer which is a redirect
    • Can't resolve /en-US/docs/Web/CSS/@starting-state

URL: /en-US/docs/Web/API/Popover_API/Using
Title: Using the Popover API
Flaw count: 8

  • broken_links:
    • /en-US/docs/Glossary/top_layer is ill cased
    • /en-US/docs/Glossary/top_layer is ill cased
    • /en-US/docs/Glossary/inset_properties is ill cased
    • /en-US/docs/Glossary/top_layer is ill cased
  • macros:
    • Macro produces link /en-US/docs/Glossary/top_layer which is a redirect
    • Macro produces link /en-US/docs/Glossary/top_layer which is a redirect
    • Macro produces link /en-US/docs/Glossary/inset_properties which is a redirect
    • Macro produces link /en-US/docs/Glossary/top_layer which is a redirect

URL: /en-US/docs/Web/HTML/Element/button
Title: <button>: The Button element
Flaw count: 4

  • broken_links:
    • /en-US/docs/Glossary/user_agent is ill cased
    • /en-US/docs/Glossary/accessible_name is ill cased
  • macros:
    • Macro produces link /en-US/docs/Glossary/user_agent which is a redirect
    • Macro produces link /en-US/docs/Glossary/accessible_name which is a redirect

URL: /en-US/docs/Web/HTML/Element/select
Title: <select>: The HTML Select element
Flaw count: 2

  • broken_links:
    • /en-US/docs/Glossary/user_agent is ill cased
  • macros:
    • Macro produces link /en-US/docs/Glossary/user_agent which is a redirect

URL: /en-US/docs/Web/CSS/CSS_anchor_positioning/Using
Title: Using CSS anchor positioning
Flaw count: 2

  • broken_links:
    • /en-US/docs/Glossary/inset_properties is ill cased
  • macros:
    • Macro produces link /en-US/docs/Glossary/inset_properties which is a redirect
External URLs (85)

URL: /en-US/docs/Learn_web_development/Extensions/Forms/UI_pseudo-classes
Title: UI pseudo-classes


URL: /en-US/docs/Learn_web_development/Extensions/Forms/Other_form_controls
Title: Other form controls


URL: /en-US/docs/Learn_web_development/Extensions/Forms/Sending_and_retrieving_form_data
Title: Sending form data


URL: /en-US/docs/Learn_web_development/Extensions/Forms/Basic_native_form_controls
Title: Basic native form controls


URL: /en-US/docs/Learn_web_development/Extensions/Forms/HTML5_input_types
Title: The HTML5 input types


URL: /en-US/docs/Learn_web_development/Extensions/Forms/Your_first_form
Title: Your first form


URL: /en-US/docs/Learn_web_development/Extensions/Forms/Form_validation
Title: Client-side form validation


URL: /en-US/docs/Learn_web_development/Extensions/Forms/How_to_build_custom_form_controls
Title: How to build custom form controls


URL: /en-US/docs/Learn_web_development/Extensions/Forms/How_to_structure_a_web_form
Title: How to structure a web form


URL: /en-US/docs/Learn_web_development/Extensions/Forms/HTML_forms_in_legacy_browsers
Title: HTML forms in legacy browsers


URL: /en-US/docs/Web/API/HTMLSelectedContentElement
Title: HTMLSelectedContentElement


URL: /en-US/docs/Web/HTML/Element/selectedcontent
Title: <selectedcontent>: The selected option display element

(comment last updated: 2025-03-10 17:16:57)

@github-actions github-actions bot added Content:HTML Hypertext Markup Language docs size/l [PR only] 501-1000 LoC changed and removed size/m [PR only] 51-500 LoC changed labels Mar 7, 2025
@github-actions github-actions bot added the Content:WebAPI Web API docs label Mar 7, 2025
@github-actions github-actions bot added the Content:CSS Cascading Style Sheets docs label Mar 10, 2025
@chrisdavidmills chrisdavidmills marked this pull request as ready for review March 10, 2025 13:18
@chrisdavidmills chrisdavidmills requested review from a team as code owners March 10, 2025 13:18
@chrisdavidmills chrisdavidmills requested review from dipikabh and removed request for a team March 10, 2025 13:18
@@ -62,6 +62,8 @@ The article [Advanced form styling](/en-US/docs/Learn_web_development/Extensions
- [`<input type="range">`](/en-US/docs/Web/HTML/Element/input/range)
- [`<input type="file">`](/en-US/docs/Web/HTML/Element/input/file)
- Elements involved in creating dropdown widgets, including {{HTMLElement("select")}}, {{HTMLElement("option")}}, {{HTMLElement("optgroup")}} and {{HTMLElement("datalist")}}.
> [!NOTE]
> Modern browsers now support [Customizable select elements](/en-US/docs/Learn_web_development/Extensions/Forms/Customizable_select), a set of HTML and CSS features that together enable full customization of `<select>` elements and their contents just like any regular DOM elements.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Modern?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated to "Some", same as your edit suggestion in the "Advanced..." article.

@@ -385,7 +389,7 @@ You can see an isolated example of this in our [Popover positioning example](htt

There is another useful positioning option that the Popover API provides. If you want to position a popover relative to its invoker rather than the viewport or a positioned ancestor, you can take advantage of the fact that popovers and their invokers have an **implicit anchor reference**.

Associating any kind of popover with its invoker using the [`popovertarget`](/en-US/docs/Web/HTML/Element/button#popovertarget) attribute or the `source` option of the {{domxref("HTMLElement.showPopover()")}} or {{domxref("HTMLElement.togglePopover()")}} methods creates an implicit anchor reference between the two. This causes the invoker to become the popover's **anchor element**, meaning that you can position the popover relative to it via [CSS anchor positioning](/en-US/docs/Web/CSS/CSS_anchor_positioning).
[Associating any kind of popover with its invoker](#other_ways_to_set_up_a_popover-invoker_relationship) creates an implicit anchor reference between the two. This causes the invoker to become the popover's **anchor element**, meaning that you can position the popover relative to it via [CSS anchor positioning](/en-US/docs/Web/CSS/CSS_anchor_positioning).
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
[Associating any kind of popover with its invoker](#other_ways_to_set_up_a_popover-invoker_relationship) creates an implicit anchor reference between the two. This causes the invoker to become the popover's **anchor element**, meaning that you can position the popover relative to it via [CSS anchor positioning](/en-US/docs/Web/CSS/CSS_anchor_positioning).
[Associating any kind of popover with its invoker](#other_ways_to_set_up_a_popover-invoker_relationship) creates an implicit anchor reference between the two. This causes the invoker to become the popover's **anchor element**, meaning that you can position the popover relative to it using [CSS anchor positioning](/en-US/docs/Web/CSS/CSS_anchor_positioning).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated


{{CSSRef}}

The **`::checkmark`** [CSS](/en-US/docs/Web/CSS) [pseudo-element](/en-US/docs/Web/CSS/Pseudo-elements) targets the checkmark placed inside the currently-selected {{htmlelement("option")}} element of a [customizable select element](/en-US/docs/Learn_web_development/Extensions/Forms/Customizable_select) to provide a visual indication of which one is selected.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is "targets" the right word? I'd tend to use that as a synonym for selects OR if there is a checkmark by default (which depends on the UA probably).
Perhaps:

Suggested change
The **`::checkmark`** [CSS](/en-US/docs/Web/CSS) [pseudo-element](/en-US/docs/Web/CSS/Pseudo-elements) targets the checkmark placed inside the currently-selected {{htmlelement("option")}} element of a [customizable select element](/en-US/docs/Learn_web_development/Extensions/Forms/Customizable_select) to provide a visual indication of which one is selected.
The **`::checkmark`** [CSS](/en-US/docs/Web/CSS) [pseudo-element](/en-US/docs/Web/CSS/Pseudo-elements) styles a checkmark placed inside the currently-selected {{htmlelement("option")}} element of a [customizable select element](/en-US/docs/Learn_web_development/Extensions/Forms/Customizable_select). It might be used to provide (or remove) a visual indication of which option is selected.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Targets" is the right word, IMO. A selector targets one or more things to style on the page. You need the whole rule to actually do the styling.

I've updated the last bit as suggested, except I haven't included "(or remove)" — I think it is enough to imply this, and I don't want to encourage people to get rid of useful UX features any more than necessary.

Comment on lines 20 to 23
### Parameters

None.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do pseudo elements ever have parameters? Not sure, but looking at other ones, they don't.

Suggested change
### Parameters
None.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, they do. See ::picker() and ::part() as examples.

I don't need to add the "Parameters" section if it doesn't take parameters tho, so I've removed it.

::checkmark {
/* ... */
}
```
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are there any restrictions on properties that can be styled? For example ::highlight() only allows a subset.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this case, no. I do tend to point out the limitations, in such cases.


> [!NOTE]
> The `::checkmark` pseudo-element is not included in the accessibility tree, so any generated {{cssxref("content")}} set on it will not be announced by assistive technologies. You should still make sure that any new icon you set visually makes sense for its intended purpose.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pseudo elements often have a section on Accessibility - are there any concerns or notes to add here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not as far as I know.


## Description

The `::checkmark` pseudo-element targets the checkmark placed inside a [customizable select element's](/en-US/docs/Learn_web_development/Extensions/Forms/Customizable_select) currently-selected `<option>`.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"targets"? (as above)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See above


The `::checkmark` pseudo-element targets the checkmark placed inside a [customizable select element's](/en-US/docs/Learn_web_development/Extensions/Forms/Customizable_select) currently-selected `<option>`.

It is only available to target when the originating element has a picker and has base appearance set on it via the {{cssxref("appearance")}} property `base-select` value. Its generated box appears before any boxes generated by the {{cssxref("::before")}} pseudo-element, with the icon specified in default browser stylesheet; you can customize it using the {{cssxref("content")}} property.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"with the icon specified in default browser stylesheet" - if it is

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is in Chrome, certainly.

}
```

Assuming [flexbox](/en-US/docs/Web/CSS/CSS_flexible_box_layout) is being used to lay out the `<option>` elements (which it is by default in customizable selects), you could then move the checkmark from the start of the row to the end by setting an {{cssxref("order")}} value on it greater than `0`, and aligning it to the end of the row using an `auto` {{cssxref("margin-left")}} value (see [Alignment and auto margins](/en-US/docs/Web/CSS/CSS_box_alignment/Box_alignment_in_flexbox#alignment_and_auto_margins)).
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(which it is by default in customizable selects)

Is that true according to spec, or just Chrome?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't say this in the spec, but it is definitely true in Chrome. I've removed the parens.


Assuming [flexbox](/en-US/docs/Web/CSS/CSS_flexible_box_layout) is being used to lay out the `<option>` elements (which it is by default in customizable selects), you could then move the checkmark from the start of the row to the end by setting an {{cssxref("order")}} value on it greater than `0`, and aligning it to the end of the row using an `auto` {{cssxref("margin-left")}} value (see [Alignment and auto margins](/en-US/docs/Web/CSS/CSS_box_alignment/Box_alignment_in_flexbox#alignment_and_auto_margins)).

The value of the {{cssxref("content")}} property could also be set to a different emoji, to set a different icon to display.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
The value of the {{cssxref("content")}} property could also be set to a different emoji, to set a different icon to display.
The value of the {{cssxref("content")}} property could also be set to a different emoji to change the displayed icon.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated!

Comment on lines 20 to 23
### Parameters

None.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
### Parameters
None.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed.


{{CSSRef}}

The **`::picker-icon`** [CSS](/en-US/docs/Web/CSS) [pseudo-element](/en-US/docs/Web/CSS/Pseudo-elements) targets the picker icon inside form controls that have an icon associated with them. In the case of a [customizable select element](/en-US/docs/Learn_web_development/Extensions/Forms/Customizable_select), it selects the down-facing arrow on the inline-end side of the `<select>` element.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. targets? (see previous comment - might be OK, just checking)
  2. See previous comments on "it selects the down-facing arrow on the inline-end side of the <select> element."
  3. Do we need an accessibility section

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. Yup.
  2. Updated to "...it selects the arrow icon shown on the <select> element that points down when it is closed."
  3. No

{{CSSRef}}

The **`::picker-icon`** [CSS](/en-US/docs/Web/CSS) [pseudo-element](/en-US/docs/Web/CSS/Pseudo-elements) targets the picker icon inside form controls that have an icon associated with them. In the case of a [customizable select element](/en-US/docs/Learn_web_development/Extensions/Forms/Customizable_select), it selects the down-facing arrow on the inline-end side of the `<select>` element.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is common to have a try-it example up the top (this is true for all cases).
This would not be too hard - you could cut back the one one the customized page to minimize the number of elements and their styling to just cover the icon

If that happened to have the SVG below that would be OK. But I would make that a local file as it would not add to the information that is relevant to this topic.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't tend to add try it examples to pages when they are only supported in one engine; at least, that is my understanding.

At least interactive examples are easier to add now - they are done with inline code rather than needing to be in the interactive-examples repo.

{{CSSRef}}

The **`::checkmark`** [CSS](/en-US/docs/Web/CSS) [pseudo-element](/en-US/docs/Web/CSS/Pseudo-elements) targets the checkmark placed inside the currently-selected {{htmlelement("option")}} element of a [customizable select element](/en-US/docs/Learn_web_development/Extensions/Forms/Customizable_select) to provide a visual indication of which one is selected.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See https://github.com/mdn/content/pull/38470/files#r2011152685 - interactive example is usually present, and this would not be very hard to do because you'd just cut back the existing ones.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

see above comment.


{{CSSRef}}

The **`::picker()`** [CSS](/en-US/docs/Web/CSS) [pseudo-element](/en-US/docs/Web/CSS/Pseudo-elements) represents the picker part of an element, for example the drop-down picker of a [customizable select element](/en-US/docs/Learn_web_development/Extensions/Forms/Customizable_select).
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
The **`::picker()`** [CSS](/en-US/docs/Web/CSS) [pseudo-element](/en-US/docs/Web/CSS/Pseudo-elements) represents the picker part of an element, for example the drop-down picker of a [customizable select element](/en-US/docs/Learn_web_development/Extensions/Forms/Customizable_select).
The **`::picker()`** [CSS](/en-US/docs/Web/CSS) [pseudo-element](/en-US/docs/Web/CSS/Pseudo-elements) selects the picker part of an element, for example the drop-down picker of a [customizable select element](/en-US/docs/Learn_web_development/Extensions/Forms/Customizable_select).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd prefer "target" to keep it consistent with other pages in this PR. Updated it to that.

Quite a few pseudo-element pages use "represent", which is also OK, imo — pseudo-elements actually exist on the page as boxes, and they represent specific items that are not DOM elements. They can also be included in stylesheets as selectors, that select those pseudo-elements.


## Description

The `::picker()` pseudo-element targets the picker part of a form control, that is, the pop-up part that appears to allow you to make a selection when you press the control button. It is only available to target when the originating element has a picker and has base appearance set on it via the {{cssxref("appearance")}} property `base-select` value.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
The `::picker()` pseudo-element targets the picker part of a form control, that is, the pop-up part that appears to allow you to make a selection when you press the control button. It is only available to target when the originating element has a picker and has base appearance set on it via the {{cssxref("appearance")}} property `base-select` value.
The `::picker()` pseudo-element selects the picker part of a form control, that is, the pop-up part that appears to allow you to make a selection when you press the control button. It is only available to target when the originating element has a picker and has base appearance set on it via the {{cssxref("appearance")}} property `base-select` value.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I prefer targets.

position-area: block-end span-inline-end;
```

- The browser default styles also define some position try fallbacks that reposition the picker if it is in danger of overflowing the viewport. Position try fallback are explained in [Handling overflow: try fallbacks and conditional hiding](/en-US/docs/Web/CSS/CSS_anchor_positioning/Try_options_hiding). For reference, the related default fallback styles are as follows:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

position-try?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed; updated


### Basic custom select usage

To opt-in to customizable select functionality, the `<select>` element and its picker both need to have an {{cssxref("appearance")}} value of `base-select` set on them:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See previous comments about what base-select is doing.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated to use the same wording used in the guide.

@@ -53,9 +53,13 @@ This element includes the [global attributes](/en-US/docs/Web/HTML/Global_attrib

## Styling with CSS

Styling the **`<option>`** element inside a `<select>` dropdown is highly limited and depends on the browser and operating system. Depending on the operating system, the [`font-size`](/en-US/docs/Web/CSS/font-size) of the owning `<select>` is respected in Firefox and Chromium. Chromium may additionally allow [`color`](/en-US/docs/Web/CSS/color), [`background-color`](/en-US/docs/Web/CSS/background-color), [`font-family`](/en-US/docs/Web/CSS/font-family), [`font-variant`](/en-US/docs/Web/CSS/font-variant), and [`text-align`](/en-US/docs/Web/CSS/text-align) to be set.
Styling `<option>` elements has historically been highly limited, hence features being introduced to enable their full customization, just like any regular DOM element. See [Customizable select elements](/en-US/docs/Learn_web_development/Extensions/Forms/Customizable_select) for more details.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Styling `<option>` elements has historically been highly limited, hence features being introduced to enable their full customization, just like any regular DOM element. See [Customizable select elements](/en-US/docs/Learn_web_development/Extensions/Forms/Customizable_select) for more details.
Styling `<option>` elements has historically been highly limited. [Customizable select elements](/en-US/docs/Learn_web_development/Extensions/Forms/Customizable_select) explains newer features that enable their full customization, just like any regular DOM element.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like it; updated!


For example, your `<option>` elements may contain icons, images, or even videos. This content might look nice inside the picker, but could cause the select `<button>` to increase in size, look untidy, and affect the surrounding layout.

This can be fixed by hiding the problem content when it is contained inside `<selectedcontent>`. For example:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Can" implies this is a good fix. It isn't if you want the icon.

Suggested change
This can be fixed by hiding the problem content when it is contained inside `<selectedcontent>`. For example:
This might be fixed by hiding the problem content when it is contained inside `<selectedcontent>`. For example:

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think "might" feels weird when used like this. I've changed it to "could", to make it a bit less definite, i.e. it is an option, there are other options you could explore.


{{HTMLSidebar}}

The **`<selectedcontent>`** [HTML](/en-US/docs/Web/HTML) element contains a clone of a {{htmlelement("select")}} element's currently-selected {{htmlelement("option")}} element content, created using {{domxref("Node.cloneNode", "cloneNode()")}} under the hood. `<selectedcontent>` represents the content visible inside the closed `<select>` element, otherwise known as the **select {{htmlelement("button")}}** as it is the button you need to press to open the drop-down picker.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider saying what it achieves first - i.e. starting with

The <selectedcontent> HTML element can be used to display the content of the currently selected option in the button for a closed <select> list.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, I've changed this around quite a bit. The opening paragraph now just reads:

The <selectedcontent> HTML element can be used to display the content of the currently selected <option> inside a closed <select> element.

I moved the other content to the "Description" section.

Copy link
Collaborator

@hamishwillee hamishwillee left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@chrisdavidmills I have gone through this, but was exhausted by the end, so might have got sloppy. There's a lot here - looks good.

One thing that I don't think was covered is the stuff in the explainer around default aria stuff. Might not be needed, but worth a quick re-read to see if there is something to be said.

aarongable pushed a commit to chromium/chromium that referenced this pull request Mar 25, 2025
The ::checkmark pseudo-element has its contents populated via the
content property. The value of the content property can have an
additional argument provided to set the accessible name, which we
currently set to an empty string by default to hide it from the a11y
tree.

The value isn't important because I think the checked state of the
option element is already provided in a different way, and announcing a
checkmark icon is not helpful.

Based on this discussion, we should do this by default for the
::checkmark pseudo without requiring the author to also set the
accessible name to the empty string:
mdn/content#38470 (comment)

Fixed: 405946933
Change-Id: I983b1e7dff879f2c1a2184c505046d0581f93380
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6388535
Reviewed-by: Aaron Leventhal <aleventhal@chromium.org>
Commit-Queue: Aaron Leventhal <aleventhal@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1437677}
chromium-wpt-export-bot pushed a commit to web-platform-tests/wpt that referenced this pull request Mar 25, 2025
The ::checkmark pseudo-element has its contents populated via the
content property. The value of the content property can have an
additional argument provided to set the accessible name, which we
currently set to an empty string by default to hide it from the a11y
tree.

The value isn't important because I think the checked state of the
option element is already provided in a different way, and announcing a
checkmark icon is not helpful.

Based on this discussion, we should do this by default for the
::checkmark pseudo without requiring the author to also set the
accessible name to the empty string:
mdn/content#38470 (comment)

Fixed: 405946933
Change-Id: I983b1e7dff879f2c1a2184c505046d0581f93380
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6388535
Reviewed-by: Aaron Leventhal <aleventhal@chromium.org>
Commit-Queue: Aaron Leventhal <aleventhal@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1437677}
chromium-wpt-export-bot pushed a commit to web-platform-tests/wpt that referenced this pull request Mar 25, 2025
The ::checkmark pseudo-element has its contents populated via the
content property. The value of the content property can have an
additional argument provided to set the accessible name, which we
currently set to an empty string by default to hide it from the a11y
tree.

The value isn't important because I think the checked state of the
option element is already provided in a different way, and announcing a
checkmark icon is not helpful.

Based on this discussion, we should do this by default for the
::checkmark pseudo without requiring the author to also set the
accessible name to the empty string:
mdn/content#38470 (comment)

Fixed: 405946933
Change-Id: I983b1e7dff879f2c1a2184c505046d0581f93380
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6388535
Reviewed-by: Aaron Leventhal <aleventhal@chromium.org>
Commit-Queue: Aaron Leventhal <aleventhal@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1437677}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Content:CSS Cascading Style Sheets docs Content:HTML Hypertext Markup Language docs Content:Learn Learning area docs Content:WebAPI Web API docs size/xl [PR only] >1000 LoC changed
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Customizable select element
5 participants