How to Label Custom Elements – A11ycasts #24

[MUSIC PLAYING] ROB DODSON: Hey, everybody. What’s up? It’s Rob Dodson. Welcome back to
the A11ycast show. Today, I want to talk about
how we label custom elements. And when I talk about
custom elements, I’m specifically referring to
the web component specification that lets you, the developer,
create your own custom HTML tags. Now, custom elements
are really cool. They let you make all
these awesome components. But it’s really
important when we do that we also make
sure we’re including all of the accessibility
and usability affordances that native elements have. So follow me over
here to my laptop, and I want to walk you
through a little example. So here I’ve got some
HTML, and right now, I’m just using native elements. So I’ve got a label
tag here, and I’ve got an input inside of it–
just a regular text field. And then down below, I’ve
got another label element. And this time, I’m using the for
attribute for the label element to point at the ID for
this checkbox control. So let’s go see what that
looks like in our browser. As we can see, it renders
as we would expect. Now, the cool thing here is
we can actually go and look at our input field. And if we look at the
Accessibility Inspector in the Dev Tools panel,
we can see that the name for the element– the
computed accessible name– is Username. And that name comes
from our label control. And the reason why
that name is important is because if someone is
using assistive technology like a screen reader, when
they land on that control, that is what the screen
reader will announce to them. It’ll say Username, Input Text. And another cool benefit that we
get from working with the label element is when we
click on these controls, it will actually focus them. So if I click on the Join
Newsletter thing here, it’ll check or
uncheck my checkbox. Click on Username– its
focus is my input field. And that’s really useful
because we’re effectively increasing the touch
or the click target size for those elements. So a checkbox can
be kind of small. But when it’s got a nice
big touch target associated with the label, it just makes
it easier to interact with. Now, let’s look at
the same example. But this time, we’ll use
some custom elements. So over here, I will go
down, and I will uncomment this bit of code here. So here I’ve got a
label tag, and I’m wrapping a howto-checkbox. So this howto-checkbox– this
is just a custom checkbox that I created. And we’ve got some text next
to it which says Click Me. So if we look at
that in our browser, it renders as we would expect. And we can check or uncheck
the checkbox and everything. But let’s inspect
it in our Dev Tools. And you’ll see that the computed
name for this checkbox element is empty. And similarly, when we go and
we click on this label field right here, it does not check
or uncheck the checkbox– not like the
built-in element did. So what’s going on here? Well, the native
label element really has no way of knowing that
a custom element is meant to be an interactive control. We don’t have any APIs in
the custom element spec that lets an author
hook into that behavior. And so that means when you’re
building a custom element, and you want to label
it, you’re going to have to do some
additional work. Now, since there
aren’t built-in APIs, the solution that
I’ve landed on is to just go ahead and build my
own custom label element that works a lot like the
native built-in one but also knows how to work
with other custom controls. So follow me back to
my laptop, and I’ll show you what I mean by that. So here I’ve got a little div. And we will uncomment this. And inside of here, you
can see that there’s a howto-label element now
along with our howto-checkbox. And so if we go back to Chrome,
and we see this in action, it renders the same. But the important bit is
when we go and inspect our howto-checkbox,
now we can see that, yes, it does now
have a computed name coming from that label. And similarly, we can go, and
we can just click on the label, and it will check or
uncheck the checkbox, just like the built-in label element. So let’s look a
little bit at what’s going on in our Elements panel. We can see how this works. So looking at our
howto-label up here, we can see that
it auto-generated an ID for itself. And looking at our
checkbox, we can see that its REL labeled
by attribute has been set, and it’s referring back
to that auto-generated ID. So under the hood, what
howto-label is doing– it’s just looking at any
children inside of it. It’s generating
an ID for itself, and it’s building
this association using rel labeled by. Now, if you don’t remember
how rel label or rel labeled by works, I’ll include some
links down in the show notes, so you can get a
refresher there. But basically, it’s just
a way for an element to point at another
control and say, hey, that control over there? That’s where I get my
accessible name from. And there’s other cool things we
can do with the howto-checkbox. So if we scroll down here
and look at this example, we can use the for
attribute that we had with the built-in label. So we can say for=”foo”, and
then we can point it at this other element who
has an ID of “foo”. So it says, “Give
us some money!” And we go, and we inspect that. Basically the same
thing– we can see that we have that association. We can see that we
have the computed name. Clicking or unclicking works. And we can even do
some fancier things. So if we wanted to,
inside of our label, we might have multiple
elements that we’re trying to use to
style our label, so it looks really fancy. So inside of here,
I’ve got a strong tag. And I’ve got some emphasis tags,
and then I’ve got my checkbox. And in order to differentiate
which of these elements is the one that
should be labeled, the howto-label element also
supports this little attribute. So we say howto-label target. We put that on our
control, and that tells that how to label element. Hey, that’s the thing
I should be labeling. So we go, and we look
at this in Chrome. Refresh the page, or save it
and then refresh the page. So now we’ve got this
very fancy label. And then we can
still click on this, and we get all the same
behavior, same name association. Now, I’d like to show
you how we actually implemented howto-label. But to be honest,
it’s way too much code to fit into just
this one episode. So instead, what
I want to do is I want to point you at a project
that we’ve been working on called the howto-components. You’ve already seen a few
of them in this example. But if you go over to components, we’ve got a
repository here of a number of custom element examples. And the idea behind
the howto-components is we want to create what we’re
calling literate code examples. So these are not elements
that you should ship into production or anything. Most of them are
not even styled. But what we wanted to do was
implement common UI patterns and show how to do so in
an accessible fashion. So if you look in the
Elements directory, you will see we’ve
got our checkbox, and accordion, and
other things like that. I’ve actually got a
pull request right now to add howto-label to the set. But you can go through, and
you can look at the elements. And if you look at
their JavaScript files, you’ll see that they’re
heavily, heavily code commented. And that’s because we want folks
to read these implementations, understand the concepts,
and then port those over to their own elements
that they’re writing. On the repo, you can also see
up at the top there is a link to So there’s actually
a section over there where we’ve extracted a few
exemplary howto elements and done little
write-ups on them. So here’s our checkbox again. And one of the
things that we did– which I think is kind of cool– is we’ve got side-by-side the
code along with some comments. So you can actually
understand very clearly like what we did, why we did it,
when we did it, how we did it, things like that. So definitely check out the
howto-components on GitHub, and also check out the section
on That about covers it for today. So if you have any
questions for me, as always, you can leave them down
below in the comments or hit me up on a social
network of your choosing. Also, thank you so
much for watching, and I’ll see you next time. [MUSIC PLAYING]

, , , , , , , , , , , , , , , , , , , , , , , , , , , ,

Post navigation

14 thoughts on “How to Label Custom Elements – A11ycasts #24

  1. Hello, Maybe it's not a good place for this question. so excuse me if it's not related.
    I'm seeing Google has invested on Web Component, moreover your team are here available for answering questions and providing videos, So Why Google Chrome team is trying to push developers to use platform stuff (like web components) ?
    I just don't know why they are serious about that by this level of investment.

  2. With Chrome 60, I am not seeing the Accessibility tab, this with an `<input>` selected in the Elements tab. Is this something only available in newer versions of Chrome, or something that needs to be enabled?

  3. Why can’t the <label for> attribute be used to reference the custom element? Isn’t that the obvious way forward? Browsers should just make <label> work with custom elements.

  4. Would it not be better to give the custom checkbox a label attribute, which if the user specifies a value it gets rendered as a label inside of the checkbox component? This enforces accessibility considerations onto the developers using the custom elements and removes the need for any hack or additional custom label components.

  5. Why not just use native labels+inputs inside your custom element? As you said, there is so much functionality you miss out on because it's a custom element, but you simply wrap native elements, you have your cake and eat it too! Example of functionality you retain: Native disable-ing of inputs, (which can also cascade from <fieldset>), form.elements just works, FormData just works, form submit just works, tabbing without need for explicit tabindex and more!

Leave a Reply

Your email address will not be published. Required fields are marked *