Pseudo-elements for tracks and thumbs

tl;dr: let's actually do part of w3c/csswg-drafts#4410 sooner rather than later.

Background

<input type=range> was first specced , with implementations shipping not that long after. Every implementation has supported the ability for authors to style the two basic pieces of the range slider (the "track" and the "thumb"), despite the fact that no spec said how to. We punted on speccing it at the time in anticipation of someone robustly defining the appearance property. Nobody did so.

w3c/csswg-drafts#4410 proposes to add pseudo-elements for the track and thumb (and more); we resolved to do so, everybody wants us to do so, so let's actually do so.

The proposal

We add two new pseudo-elements:

::track
Represents the track that the thumb moves along.
::thumb
Represents the thumb that moves along the track.

They work like this:

Box hierarchy
the ::track and ::thumb pseudos are siblings of each other, per @thebabydino's reasoning in w3c/csswg-drafts#4410.
Properties which can be set on them
¯\_(ツ)_/¯ Whatever Emilio says they should be. (It'd be nice to support the content property for switch controls; see below.)
Elements that sprout them

Naming

All engines call these pieces the "track" and the "thumb":

Proprietary track and thumb pseudo-elements in each engine
EngineTrack pseudo-element nameThumb pseudo-element name
EdgeHTML::-ms-track::-ms-thumb
Gecko::-moz-range-track::-moz-range-thumb
WebKit (and Blink)::-webkit-slider-runnable-track::-webkit-slider-thumb

"Track" and "thumb" are also the terms used for the analagous parts of scrollbars.

Given the apparent naming consensus, let's skip the bikeshedding and standardize these names.

That's it‽

Yup. Baby steps.

There are many more pieces of these controls to also standardize. I look forward to a world in which web authors reap the rewards of a more holistic effort at tackling form control styling with appearance: base or whatever, but I'm not trying to do that here.

I'm really just proposing that we finally spec ::track and ::thumb pseudos that can be shared by range and switch controls, and that we not let the (very reasonable) desire for more to get in the way of this small bit.

Let's not let the perfect be the enemy of the good.

Potential issues

  1. People may find the name ::track confusing, given the existence of HTML's <track> element. I doubt this will prove to be a problem in practice, considering the <track> element is specific to media and does not create CSS boxes.
  2. People may expect to be able to style scrollbar tracks and thumbs with these pseudo-elements. They can't. I don't think there's much to be done about this.

Future work

After we add ::track and ::thumb there's plenty more to do! w3c/csswg-drafts#4410 and Open UI have a bunch of ideas that go way beyond these two pseudos.

The two sides of the track

For instance, EdgeHTML also allows you to separately style the bits of the track on either side of the thumb with the ::-ms-fill-lower and ::-ms-fill-upper pseudos, and Gecko allows you to separately style the lower portion. The <progress> and <meter> elements also often have a two-part track, and styling them is possible in each engine, though the mechanisms vary quite a bit from one another.

If we want to make it possible to style the two sections of the track differently without resorting to appearance: none, we should really do so in a way that's consistent across all of these elements. That might take a while, so let's not block ::track and ::thumb on it.

Circular sliders

This is a very cool idea, but I think for now it's okay to leave it to the appearance:none escape hatch.

Text inside switches

I don't think this needs to be part of the switch MVP, but if authors want to place text in the thumb or the track of the switch control, we could simply let them set the content property on these pseudos (in concert with :checked if necessary), e.g.

#power::thumb {
  content: "⏻";
}
#power::track {
  content: "Off";
}
#power:checked::track {
  content: "On";
}