It’s the markup that matters

A presentation at JSConf Budapest in June 2022 in Budapest, Hungary by Hidde de Vries

Slide 1

Slide 1

Intro

Hello JSConf! Tejas was absolutely correct, this talk is about HTML.

Slide 2

Slide 2

So in the next 30 minutes, sorry to disappoint, unlike Lucky, I won’t be flying drones with bananas… that was a great talk wasn’t it? I will also not hide gorillas in these slides, as Moran did, or combine the history of art with the awesome possibilities CSS has today, like Nils… instead this talk will be about HTML and what it can do, for you and for your users.

Slide 3

Slide 3

HTML is awesome, because it enables lots of things.

Slide 4

Slide 4

It enables a multi device web… we use CSS to create experiences that work across device and viewports and what not… the reason we have a structure to program our CSS against: HTML!

Slide 5

Slide 5

HTML enables browsers to come with sensible defaults. Maybe your project uses a CSS reset, but there’s likely still styles that are set by the browser, like table styles to make stuff appear next to other stuff, and all sorts of other things, have you ever stared at the computed styles in dev tools?

Slide 6

Slide 6

There’s browse by heading, which I’ll get into in a minute.

Slide 7

Slide 7

Default behaviors are enabled by HTML, so like buttons would submit a form by default and the browser knows to do that because HTML exists.

Slide 8

Slide 8

Or reader modes… which are essential for people with certain disabilities and nice for us all, on today’s web that gets more and more complicated over time.

Slide 9

Slide 9

Ok, so my talk is called It’s the markup that matters, I guess that won’t surprise you now. Let me tell you why over the next 30 minutes!

Slide 10

Slide 10

First, I haven’t introduced myself, I am Hidde, i do dveloper relations at Sanity. We’re on a mission to make content easier to work with for content creators, developers and even businesses… the end goal is more delightful, remarkable digital experiecnes. In recent years I also did a lot of accessibility work, most recently at the World Wide Web Consortium, promoting web standards for accessibility. And I blog, you can like and subscribe at hidde.blog, or follow me on Twitter, I’ll post my slides there too.

Slide 11

Slide 11

So let’s talk about accessibility.

Slide 12

Slide 12

In its simplest form, web accessibility is all about ensuring people with disabilities can use your site or app.

Slide 13

Slide 13

Or, to phrase it differently… it is to ensure they can buy your product.

Slide 14

Slide 14

Or use your service.

Slide 15

Slide 15

Yesterday there was this show of hands around who is or knows people with a disability… the stats don’t lie, many of us have disabilities, in many shapes and forms, from neurological conditions to motor impairments.

Slide 16

Slide 16

Like, a lot of people use high contrast modes.

Slide 17

Slide 17

Or zoom in on websites, which low vision users do to access the content.

Slide 18

Slide 18

Some people prefer reduced motion as motion could make them sick, literally.

Slide 19

Slide 19

Lots of people don’t use a mouse, for a variety of reasons… they might be using a switch control or use their voice or use a keyboard.

Slide 20

Slide 20

So, many things to optimise for, which is why everyone in the team has some accessibility responsibilities. But today I want to focus.

Slide 21

Slide 21

Today, I want to focus on specifically people who use assistive technologies, as that’s the part where code and developers make a huge difference.

Slide 22

Slide 22

It’s tech like voice control that lets users control their computer by voice, switch controls, braille displays that translate what happens on the screen into braille in real time and screenreaders. All of this tech exists so that people can use computers and the web in a way that works for them.

Slide 23

Slide 23

Our markup hugely impacts the user experience, let’s look at how.

Slide 24

Slide 24

When someone accesses your site, let’s say they type in a URL and press enter, your server is going to respond with markup. The browser turns that into a DOM tree.

Slide 25

Slide 25

From the DOM tree, the browser creates a secondary structure called the accessibility tree. It has things like here’s a radio button called ‘Round trip’ that you can press and it is selected, a slider that can go from 0 to 24 and it is set to 7, it’s called ’Departure time’ and you can increment and decrement it. A button that is called ‘Search’ that can be pressed. By now you may be able to visualise some kind of UI that allows users to do the things defined here in the abstract. Assistive technologies do this too, but they use interfaces specific to their user group.

Example of an Accessibility Tree (image of description above)

Slide 26

Slide 26

For each accessibility-relevant DOM node, accessibility trees have information on what kind of thing an element is, like is it a button or a link, or a text input… that’s called the ‘role’. There is info on how to refer to it, these are the name and description, stuff like this button is called ‘Save details‘ or that slider is ’Departure time‘. And then there is some more meta info like is this thing selected or checked or expanded.

Slide 27

Slide 27

When I audit a website for accessibility, I’ll be looking for this sort of information. Among other things. So if I see a website has a bunch of links, I’ll go and check… 

Slide 28

Slide 28

Oh cool, this one has a role of link, name is “World”

Slide 29

Slide 29

another role of link, with the name “US politics”… ok let’s skip that one for now.

Slide 30

Slide 30

then there is a role of link with the name “Business”

Slide 31

Slide 31

and a role of button with the name of “Edition”. I guess I can find different editions of CNN dot com there.

Slide 32

Slide 32

So as mentioned, our markup informs the DOM tree, out of that the accessibiliy tree is constructed, that’s the story so far. From there on, information is passed to so-called Platform Accessibility APIs that are built into all the major platforms, Windows, Mac, Linux, mobile OSes… and then from those APIs, ultimately the assistive tech is informed, and with that, the user. So, our markup matters, it impacts the AT, ultimately.

Slide 33

Slide 33

You can look at accessibility trees in all major browsers, there are tabs available and popups that show up when you inspect elements. If it mentions roles and names and states you now know what they are.

Slide 34

Slide 34

Ok, so what does that look like in practice?

Slide 35

Slide 35

Let’s look at some examples… and don’t worry, the following examples work with all of your favourite tools)… whatever generates your HTML for you, it’s all going to go into that same DOM and interpreted the same way. All tools are welcome here.

Slide 36

Slide 36

One question markup answers is “Where am I?” When a screenreader user arrives on your page, they will hear what’s inside your ‘title’ element.

Slide 37

Slide 37

This is often an element that is somewhere in a template we never go… but this means it’s super important to keep it up to date and have a fresh title for each page, including in single page apps, where you might need to update this on route.

Code example: <html lang=”nl”> <head> <title>It’s the markup that matters Presentations - My site</title> </head> <body> … </body> </html>

Slide 38

Slide 38

A cool video about this is on Smashing TV with my friend Léonie Watson, accessibility expert and screenreader user, who explains that the title confirms to her that it is the page she intended to reach.

Slide 39

Slide 39

Another question markup answers is “What is on this page?” It’s done with headings.

Slide 40

Slide 40

So whenever you use <h1>, <h2>, <h3>, people can see headings in reader mode, but also they can navigate by heading. Most screenreaders have a way to access headings of a page, and it lets jump people directly to that heading, so it’s a way to find content fast. It’s a bit like when you call a customer service and they say something like “Press 1 for support, press 2 for sales”, but based on your headings on your website.

Slide 41

Slide 41

For this reason it’s so important to ensure the headings are well written.

Slide 42

Slide 42

Another question you can answer with markup is: which areas are on this page? Like, remember yesterday when the organisers started explaining the venue and pointed out there are toilets, community lounge, sponsor booths, et cetera

Slide 43

Slide 43

With landmarks in HTML you can do that sort of thing but for your page.

Slide 44

Slide 44

HTML has some elements built in that are landmarks natively, if you use them in your code you are basically establishing a landmark.

Slide 45

Slide 45

There’s a great article about using landmarks carefully and what to look out for called “Accessible landmarks” by Scott O’Hara, recommended reading if you want to get started using landmarks. One takeaway from this post is that you shouldn’t use too many. Thinking about the venu here, you wouldn’t want the organiser to point out every single chair in this hall, that would not be a meaningful thing to do.

Slide 46

Slide 46

Landmarks are currently only available in screenreaders. I’m going to embarrassingly quote my own presentation here… I did a talk a few years ago about what browsers could do about accessibility and one of the things I proposed there was browsers to expose landmarks so that sighted users could use them too. I’d still love to see that!

Slide 47

Slide 47

Ok, let’s move to form controls. There is a ton to say about them in terms of accessibility, I’ll focus on just one today, which is the accessible name. There’s this non profit called WebAIM in the US who look at the accessibility of the top 1 milion websites every year.

Slide 48

Slide 48

In the 2022 survey they found almost half of the websites they looked at had unlabelled form fields.

Slide 49

Slide 49

So, form fields like inputs, radio buttons, checkboxes, selects, textareas etc need to have labels, it gives them an accessible name in the accessibility tree.

Slide 50

Slide 50

Let’s say you use this code to write an input people can put their city into:

<div class=”form-item”> City <input type=”text” /> </div>

In the accessibility tree it is going to show up with a role of ‘textbox’ or ‘entry’ and a name of null or empty string.

Slide 51

Slide 51

Browsers have lots of ways to figure out what an input is called, to find the name, this is all specificied in a name and description computation specification… find the link for more details on that.

Source: Accessible Name and Description Computation 1.1

Slide 52

Slide 52

For now, I’ll give you one way to do it, which is to add a label element around the word ‘City’ and then relate it to the input using a for attribute on the label that corresponds with the id of the input.

Now the accessibility tree computes a role of ‘textbox’ / ‘entry’ and a name of ‘City’.

Code:

<div class=”form-item”> <label for=”city”>City</label> <input id=“city” type=”text” /> </div>

Slide 53

Slide 53

Then I’d like to mention table semantics.

Slide 54

Slide 54

There seems to be an urban myth that tables are bad for accessibility, but they are actually a great way for users to navigate tabular data.

Slide 55

Slide 55

One thing to look our for, though, is to make sure to add headings and set a scope. And in terms of naming, it’s often useful to add a caption element, which has to be the first child of the table.

Slide 56

Slide 56

A caption can be used to distinguish multiple tables on a page, like if you have this financial documents page, and I’m obviously not in finance, but let’s say you’ll need to distinguish between different tables, say one is for 2018 and another one is for 2019, you’ll want to add those unique names into the caption element. This way, users of screenreaders can find the tables more easily and when they find them, ideally know at once if they’re the one they are looking for.

Slide 57

Slide 57

The last element to discuss is buttons.

Slide 58

Slide 58

They are awesome! I know in some teams buttons are replicated by divs, but it is actually really hard to build a good button out of a div. Buttons come with lots of stuff built in, like you can find it in tab order, it works with a keyboard and it can even submit forms with the default button type.

Slide 59

Slide 59

Now what about the names of buttons? This is easy-ish when there is text, the text becomes the name, basically. But what if you buttons have just icons?

Slide 60

Slide 60

In markup it may look a bit like this. Inside of your button element, you may have some svg content. It’s a shape but the browser doesn’t know of what or what to do with it, so it is going to compute the accessible name to null.

Slide 61

Slide 61

Ways to fix that include adding an aria-label attribute to the button element, with as the value the name you want. This will override any contents this button has in terms of name computation, so if you had any text in there, it will be discarded and the aria-label value will be the name. Note that there have been bugs in browsers around translating this part when putting a page into Google Translate, so that’s a bit of a downside.

Slide 62

Slide 62

Another way to do it is to add actual text inside of the button. You can make it invisible with a so-called visually hidden class, sometimes it is called ‘visually-hidden’, sometimes also ‘sr-only’, the main thing is not to use display none or visibility hidden as that hides content from the accessibility tree as well, so these visually hidden techniques use CSS that preservces the content, like position absolute.

Slide 63

Slide 63

I hope by now you are all excited about the powers of HTML. If you want to know in much more detail how to use specific elements in HTML, developers.whatwg.org is a great place, it is basically the specification that browsers and other user agents also use, but with the browser specific stuff taken out.

Slide 64

Slide 64

Another great website about using HTML is HTMHell by my friend Manuel Matuzovich, this page collects examples of what went wrong with explanations of how it went wrong.

Slide 65

Slide 65

Ok, so we’ve looked at how to use markup for accessibility support, but as we’re at a JavaScript conference I thought it would be good to look at some work in progress around taking some of this stuff to JavaScript land. The Accessibility Object Model effort happening in a W3C community group works on exactly this.

Slide 66

Slide 66

They aim to “develop additions to the web platform to allow developers to provide information to assistive technology APIs, and to understand what information browsers provide to those APIs”, says the AOM explainer document. Note these are mostly proposals, we’ll talk about some of the plans that are being discussed.

Source: The Accessibility Object Model (AOM)

Slide 67

Slide 67

The first one is actually suported in both Chromium and Safari and it is the ability to set accessibility properties like roles and states as so called IDL attributes, so rather than using a setAttribute on the element you assign directly to a property. It has the same effect though and will reflect in the DOM tree and can be changed there.

Code: const el = document.querySelector(“el”); el.role = “button”; el.ariaDisabled = false;

Slide 68

Slide 68

When you’re building Web Components, you may want to “bake in” accessibiltiy properties to your components though. In recent Chrome Canary you would be able to set this through ElementInternals, eg you would set _internals.role on an element to set the role.

Slide 69

Slide 69

IDREFs are important in HTML as they can establish relationships between elements, like in the example I showed of where a <label> tag is related to an <input> in order to provide it with an accessible name. There are many relationships like that in ARIA too. The AOM folks are looking at assigning such relationships directly, so you would do something like element.ariaDescribedBy = someOtherElement. This isn’t supported anywhere yet.

Slide 70

Slide 70

One reason this is being explored, I believe, is that IDREFs don’t work across Shadow boundaries in Web Components. There is some early discussion on a “cross-root ARIA Delegation API”, the explainer is on github.com/leobalter/cross-root-aria-delegation/blob/main/cross-root-aria-delegation.md.

Slide 71

Slide 71

It would be, quoting the explainer, “an API to forward ARIA attributes and properties set on a Web Component to elements inside of its shadowroot”.

Slide 72

Slide 72

The original AOM discussions also included plans to include events from Assistive Technologies, so that you could, as a developer, get events for things like this Voice Control system clicked on a button. But like it has accessibility built in, the web has privacy built in, and there were privacy concerns.

Slide 73

Slide 73

The current proposals describe, instead of events from Assistive Technologies that would expose a user’s disability, synthesised DOM events, so a click event would get generated for an assistive tech click, and your code wouldn’t know if had come from an assistive techology or a mouse click. It works like this in many cases already, the AOM group are documenting some of this to make sure all the different cases align with actual behaviors.

Slide 74

Slide 74

The last part of AOM proposals is the idea of reading the accessibility tree from JavaScript. You could already find out stuff with JavaScript now, like you could read getAttribute(‘aria-label’) to see what name it tries to set, but this would give you access to what the browser has actually computed as role, name or other property. This is great for tests! This is available in Firefox and Chromium today, though with an outdated syntax.

Slide 75

Slide 75

Ok, so far we’ve looked at setting accessibility meta information by using HTML and JavaScript… before I leave you, let’s talk a bit more about doing accessibility through HTML.

Slide 76

Slide 76

As Tiger showed yesterday, using the power of the web platform can lead to great things! This goes for HTML too, HTML comes with accessibility built in… I mean, in lots of sense, like the image and video tags have features to provide text alternatives, most form controls come with accessibility features like semantics and keyboard behavior. I love this.

But… there isn’t HTML for everything! We don’t build websites with just some headings, lists and form elements.

Slide 77

Slide 77

I mean, some of probably have been through the pain of building a custom calendar widget? This sort of thing isn’t really there in the web platform… there is an input type of date, but it is tricky or impossible to customise and brand.

There are a bunch of elements in HTML that never needed to be styled, but it seems like today a lot of web developers are using a lot of their time customising UI controls, or building them from scatch. At least that’s an observation Nicole Sullivan (at Google) and Greg Withworth (at Salesforce, previously at Microsoft) had. They started an initiative called Open UI to work on this problem.

Slide 78

Slide 78

Open UI wants to make it unnecessary to reinvent built-in UI controls. The group works on features for the web platform, be it APIs, new HTML elements, attributes, CSS features, that all try to make it easier to build UI patterns with less effort for developers, leaving more to the browser.

I’ve been in this group for a bit of a year… I mean, I’m not a browser maker or pro spec writer, but I’ve been attracted to these meetings and discussions, wanted to follow along, because I believe in what this effort could achieve.

Slide 79

Slide 79

I think standardised controls can be a huge opportunity for accessibility. I was chatting to someone yesterday who worked on a design system and we talked about the huge ripple on effects these things can have… you build a component badly and the badness propagates everywhere… you build it well and the goodness propagates everywhere. More standardisation around browser controls, if done well, could end up propagating a lot of accessibility features towards end users.

Slide 80

Slide 80

Not easy though… Nicole Sullivan tweeted about this last month, a goal is to try and have “implied accessibility semantics”, to have accessibility “handled for common use cases”, it would be chef’s kiss… but, she says, this is hard. I agree with that, from the discussions we’ve been having at Open UI, there’s a lot of considerations and sometimes they conflict. Long story short, there’s a bunch of people working in different settings to try and ensure many accessibility considerations are met.

Slide 81

Slide 81

I want to share two different things that we are working on at Open UI. One is the selectmenu tag.

Slide 82

Slide 82

Has any of you built custom selects before? Greg Whitworth surveyed developers and asked how they liked styling select tags.

Responses included:

  • Hard to build “search in list” UI — 27.43% of respondents
  • Can’t customise popup window on desktop - 11.36% of respondents
  • Can’t style <option> — 17.85% of respondents
  • Need to insert arbitrary HTML — 7.82% of respondents
  • Can’t style default state — 14.01% of respondents

Source: Greg Whitworth, Can we please style the <select> control?

Slide 83

Slide 83

So if you were to build a regular select, you might do something like:

<select> <option>Tabs</option> <option>Spaces</option>

<option>A mix of both</option> </select>

and it looks however the browser decides to.

Slide 84

Slide 84

With the new <selectmenu>, you would do pretty much that, in its most basic form, but replace select with selectmenu. Now you can do things like replace the HTML of some of these contents, and, what I want to show you today, style the individual pieces as if you were styling divs.

Example from FAST UI

Slide 85

Slide 85

So you could style h button by selecting selectmenu::part(button) in CSS and applying styles, like background-color: #f00; border-radius: 5px;

Slide 86

Slide 86

You could style the listbox with selectmenu::part(listbox).

Slide 87

Slide 87

Or the selected value with selectmenu::part(selected-value).

Slide 88

Slide 88

The cool thing is, you can play with it today if you have Chromium or Edge Canary and turn on the Experimental Web Features flag. Note there are known accessibility issues and all of this is subject to change. Do try this at home, just not on a public facing websites, basically, just yet.

Slide 89

Slide 89

The second element I want to highlight is really an attribute, this recently changed. The popup attribute would let you make popup like interfaces.

Slide 90

Slide 90

At Sanity, we have a component to upload images and it comes with an action menu with some image related actions, like Copy URL and Replace. This sort of thing could be built as a popup in the future.

Slide 91

Slide 91

And action menus is just one example of popup-like behavior, others are teaching UI, content pickers such as date pickers, form element suggestions and, as just discussed, selects.

Chrome Platform Status: The Popup API

Slide 92

Slide 92

What popups have in common is that they are on top of other content, that they are ‘ephemeral’, like, temporary, they’re only open when they need to be, otherwise closed. And there’s usually one at the time.

Popup API (Explainer)

Slide 93

Slide 93

Ok, so let’s look at what the markup for that would look like. Again, this is all still in development, but this is what it would work like according to current proposals.

So let’s build our image action menu. We’ll create a div with inside of that a heading and two buttons.

Slide 94

Slide 94

Then we’ll add the popup attribute to the outer div. This turns it into a popup, meaning the browser will be closing (or really, hiding) it by default. If it needs opening, you’ll be able to call a showPopup method in JavaScript. Or, and I love this, add the open behavior declaratively.

Code:

<div popup> <h3>Replace image</h3> <button>Upload</button> <button>Browse</button> … </div>

Slide 95

Slide 95

Let’s add an ID for that, we’ll add id=options to the div.

Slide 96

Slide 96

What we can do then, and here’s the IDREF again, refer to the popup from a button, by setting a togglepopup attribute on the button, with the ID of the popup as its value.

Code: <button togglepopup=”options”> Image options </button>

<div popup id=”options”> <h3>Replace image</h3> <button>Upload</button> <button>Browse</button> … </div>

Slide 97

Slide 97

When we added the popup attribute, we were using popup’s auto mode. Having just the popup attribute is equivalent to doing popup=auto, it is the most popup-y popup.

Another type is popup=async. An example of that would be… at Sanity, when you publish a document, stuff happens on our content servers and if all goes well, a notification, ‘toast’ type of element appears that says the publishing was successful. This is the kind of thing you could use popup=async for.

Slide 98

Slide 98

It’s still under discussion whether this should be a live region by default, so that an announcement of the newly appearing content is made in a screenreader, for the time being we could wrap this popup in a div with a role of alert.

Slide 99

Slide 99

So, if we have a div with popup async, we can leave that empty until we know the content. In JavaScript, we first find the element.

Slide 100

Slide 100

Then, whenever we’re in the success state, for simplicity I’ll leave all of that out, that’s for another talk, let’s say the upload was successful… we basically update the content of our ssync popup and call the showPopup method on this element.

Slide 101

Slide 101

Like <selectmenu>, popup is available in Chrome and Edge Canary, you can go play with it.

Slide 102

Slide 102

If you do, we want your thoughts! One way to get involved is to follow @OpenUICG on Twitter, tag along on Discord or even join the meetings, they are open to all, if you’re a developer building UI components your input is very much valued.

Slide 103

Slide 103

Ok, so, let’s wrap up!

Slide 104

Slide 104

Today we’ve looked at the ways HTML can and will affect your user’s accessibility trees. If you want it or not, these trees are constructed based on your markup and you can impact the info that ends up there, ensuring names, roles and states are what they should be.

Slide 105

Slide 105

Excitingly, there is some work happening in the AOM group on allowing some accessibility meta information to be controlled and read from JavaScript land.

Slide 106

Slide 106

And, maybe, if things go well, we’ll get more markup, attributes, APIs, CSS features that will make it easier to build components that have accessibility built in. Even if that’s hard, I’m super excited about this, it’s a promising future!

Slide 107

Slide 107

And that’s all for me today, thanks so much again for listening!

You can find these slides on talks.hiddedevries.nl, follow me @hdv or email hidde@sanity.io.

Special thanks for clarifications, input, feedback Mason Freed, Scott O’Hara, Julia Silver, Eric Eggert, all at Open UI CG

Typefaces in the slides are Bungee by David Jonathan Ross (DJR) Rasa by Anna Giedryś, David Březina (Rosetta)