- Kent Tamura tkent@google.com
This document proposes a new HTML element for a 'switch' control. It is provided as a built-in module.
This proposal is intended to incubate in the WICG once it gets interest on its Discourse thread. After incubation, if it gains multi-implementer interest, it will graduate to the HTML Standard as a new standard HTML element.
Many UI frameworks have switch controls to represent off/on states and ask a user to change the state. As of April 2019 the HTML standard has a checkbox, which is functionally similar to switch control. However:
- Semantically, a switch and checkbox have different meanings, with a switch being more appropriate for turning things on/off. (See e.g. Microsoft Fluent design guidelines, Nielsen Norman Group, UX Planet.)
- Switches and checkboxes manifest differently to accessibility technology: see the
switch
ARIA role. - It's hard to change checkbox's appearance to a switch-like appearance, for when that user experience is desired.
- Identical appearance on all platforms and all supported browsers by default (Issue #21)
- Easy and flexible customization
- The switch control should provide a way to switch its appearance from the default one to platform-dependent one.
- The switch control should provide a way to customize color, size, radius, etc. of its visual parts.
- API similar to existing form controls
- Explore new ways of building HTML elements, including:
<script type="module">
import 'std:elements/switch';
</script>
<form action="...">
<label>Enable something <std-switch name="something"></std-switch></label>
<input type="submit">
</form>
Users can turn on/off the switch by clicking it, and submitting the form will have an entry for the switch control.
The element is provided as a built-in module.
import 'std:elements/switch'
defines <std-switch>
element,
and it can expose StdSwitchElement
interface.
- Global attributes
autocomplete
disabled
form
name
required
TODO: Supports autofocus
, which should be a global attribute. (whatwg/html#4563)
These attributes should work same as existing form controls.
<std-switch>
should support on
and defaulton
attributes (Issue #2).
defaultOn
property reflects on defaulton
attribute value, and on
property reflects on on
attribute.
Code like switch.on = true
adds on
attribute. We need to specify defaulton
attribute
if we want to reset the element to on state, like ``` (Issue #4)
-
on
- Represents the element's state. See the previous section -
defaultOn
- Represents the default state. See the previous section -
disabled
- Same as existing form controls -
form
- Same as existing form controls -
labels
- Same as existing form controls -
name
- Same as existing form controls -
type
- returns'std-switch'
-
willValidate
- Same as existing form controls -
validationMessage
- Same as existing form controls -
checkValidity()
- Same as existing form controls -
reportValidity()
- Same as existing form controls -
setCustomValidity(errorMessage)
- Same as existing form controls
- Global ones such as
:focus
:hover
:target
:valid
- match if the element has norequired
attribute, of if the element hasrequired
attribute and the state is on.:invalid
- match if the element doesn't match to:valid
.:disabled
- match if the element hasdisabled
attribute, or an ancestor<fieldset>
hasdisabled
attribute.:enabled
- match if the element doesn't match to:disabled
.
TODO: Supports :checked
(Issue #3), :required
, and :optional
(w3c/webcomponents#813)
<std-switch>
dispatches input
and change
events when a user changes the element's state.
form
Markup like<form>...<std-switch></std-switch>...</form>
associates the<std-switch>
element to the<form>
.<form>
'selements
property lists the<std-switch>
, and submitting the<form>
adds an entry for the<std-switch>
.fieldset
Markup like<fieldset>...<std-switch></std-switch>...</fieldset>
associates the<std-switch>
element to the<fieldset>
.<fieldset>
'selements
property lists the<std-switch>
, and disabling the<fieldset>
also disables the<std-switch>
implicitly.label
Markup like<label>...<std-switch></std-switch></label>
associates the<std-switch>
element to the<label>
. Clicking anywhere in the<label>
changes the state of the<std-switch>
.
There are two approaches. We have not decided yet. (Issue #15, Issue #5)
- A) Compatible with
<input type=checkbox>
<std-switch name=something>
with "off" state will send no entry. One with "on" state will sendvalue
attribute value if it exists, orsomething=on
. - B) Send state simply
<std-switch name=something>
with "off" state will sendsomething=off
, one with "on" state will sendsomething=on
.
TODO: an easy flag to enable platform-dependent appearance (Issue #6)
When the flag is enabled, std-switch
element is styled as UISwitch on iOS, Material Design switch on Android, Fluent design toggle switch on Windows.
The element provides full customization capability by CSS Shadow Parts.
A <std-switch>
contains three parts, track
, track-fill
, and thumb
. track
and thumb
are siblings, and track-fill
is a child of track
.
(See Issue #7)
There are no known security or privacy impacts of this feature. Security/privacy impact of this feature is same as <input type=checkbox>
.
If the platform-dependent appearance is enabled, the origin can detect user's platform. However, that information is already exposed by navigator.platform
.
Providing a switch control as a variant of <input type=checkbox>
would be possible.
We can add switch
content attribute, add switch
keyword to appearance
CSS property, or something.
However, as decribed in the 'Why a switch control?' section, using <input type=checkbox>
for a switch control is semantically incorrect.
Also, it would add complexity to UA implementations, and it's difficult to provide
customization flexibility with a switch control implemented by these ways.
We would like to experiment with ways of making new HTML elements "pay for what you use".
Instead of every page paying the cost of loading a switch implementation into memory as a global (e.g. window.HTMLSwitchElement
),
we want pages to opt in to using the switch control.
The JavaScript module import system provides a convenient mechanism for this,
which is also used by other APIs that share the same goals (such as KV Storage).
Note that although adding a global switch control implementation is a small step, it contributes to a tragedy of the commons, which makes it harder and harder to add new APIs and elements. Exploring an opt-in solution here opens the door to more sustainable growth overall.
It is possible to continue requiring that web developers use a library to implement switches.
We believe that the platform should instead provide a basic control such as a switch out of the box.
Major modern UI platforms (e.g. Android, iOS, Windows, macOS) all provide switch controls,
and the web should as well.
The story for macOS is "use NSSwitch
and you get a switch control."
The story for the web should be similarly simple, instead of "use a checkbox, customize it with tons of CSS, and remember to change its ARIA role=""
."
The name <std-switch>
is unusual compared to built-in HTML elements,
none of which have a dash.
A more natural choice might be <switch>
, or perhaps <toggleswitch>
.
The reason to include a dash in the name is to allow the element to be polyfillable, using custom elements. We'd like to experiment with moving away from the world where browsers get a special namespace that can never be polyfilled.
There are alternative ways of achieving this goal; for example, we could lift the dash restriction on custom element names. There is some more discussion in WICG/virtual-scroller#161. This is definitely subject to change as we continue to prototype.
Not really.
This is a proposal for a new built-in HTML element,
similar to other new-ish elements like <details>
, <dialog>
, or the proposed <portal>
.
If it graduates from incubation successfully, it will become part of the HTML Standard.
The name does have a dash, as noted above.
And the goal of allowing custom elements to perfectly polyfill <std-switch>
will mean that <std-switch>
behaves like a custom element in many ways.
(As we proceed to writing a rigorous spec, those will be enumerated in detail.)
Indeed, browsers may even choose to implement <std-switch>
using custom elements under the hood.
(Chromium plans to do so.)
But in the end, this is a new element intended for the HTML Standard,
meant to ship natively with browsers.
This is a decision for individual browser vendors to make.
Note that historically some parts of browser codebases are shared
(e.g. Web Audio, RegExp
engines, Web RTC)
while many parts are implemented independently.
It will likely be easier to share code for <std-switch>
than for <input type=checkbox>
,
because our goal of making it 100% polyfillable and layered means that it will depend on standardized web-exposed API concepts instead of hooking directly into internal implementation details.
But in the end,
this repository will only provide a specification,
which can be implemented however makes most sense to individual browsers.
- whatwg/html#4180 posted by Atishay Jain gave us a motivation to start this project.