RubyConf AU 2024
Advanced HTML for Performance & Accessibility
Summarized using AI

Advanced HTML for Performance & Accessibility

by Mandy Michael

Summary of 'Advanced HTML for Performance & Accessibility'

In her talk at RubyConf AU 2024, Mandy Michael emphasizes the importance of utilizing HTML not just as a foundational web technology, but as a crucial element in enhancing website performance and accessibility. She encourages developers to rethink their approach to HTML, dispelling the misconception that its simplicity equates to insignificance.

Key Points:

  • Value of HTML: HTML is vital for conveying the structure and meaning of content on the web. Its simplicity often leads developers to overlook its significance.
  • Accessibility Concerns: Proper use of HTML elements directly impacts the accessibility tree constructed by browsers, which assists technologies such as screen readers. Using generic elements like <div> leads to poor accessibility outcomes.
  • Content Structure: Utilizing semantic HTML tags over generic ones improves content structure. For instance, using appropriate heading levels helps identify the hierarchy of content, improving navigation for assistive technologies.
  • Performance Implications: A well-structured HTML document can reduce the complexity of the DOM, leading to improved load times and better performance metrics. It is essential to keep the DOM tree manageable.
  • Use of Built-in Elements: Leverage native HTML functionality for features like buttons and forms instead of replicating them with <div> elements. This reduces the need for additional JavaScript, streamlining code and enhancing performance.
  • Resource Loading Optimization: Mandy discusses HTTP/2 and the importance of resource prioritization to improve loading times. Techniques like preconnect, dns-prefetch, and preload play significant roles in optimizing resource requests from the server.
  • Implementing Fetch Priority: The fetch priority attribute allows developers to adjust the priority of resources, enhancing browser performance during the loading process.
  • Conclusion: The session concludes with the message that careful consideration and proper implementation of HTML can enhance both accessibility and performance. Developers are encouraged to invest time in learning how to use HTML effectively, as it leads to more usable and responsive web applications.

Takeaways:

By understanding and applying the semantics of HTML effectively, developers can create web pages that serve a broader range of users and technologies while also resulting in better overall performance.

Mandy invites attendees to reach out for further questions, emphasizing the accessible nature of the resources she shared during her presentation.

00:00:03.480 I'm sorry about the pineapple thing. They asked for a controversial opinion, and that's the one I went with.
00:00:09.360 Because it does not belong on pizza, I'm sorry. We can talk about that later, though. Um, hello, thank you for having me.
00:00:15.559 I've never been to RubyConf before, so this has been really fun for me. I want to start off my talk by saying thanks to Toast Creative for allowing me to use the illustrations in my talk.
00:00:21.320 It is why it looks so pretty. And very importantly, this is my dog, Jello. The reason I'm mentioning this is because I use the word "jello" a bit in my talk.
00:00:27.400 People get confused and think it's the food, so today we're going to be talking about HTML.
00:00:35.200 We're going to look at how you can utilize it to improve the performance and accessibility of your websites and applications.
00:00:41.280 Now, I know HTML has nothing to do with Ruby, and everyone knows HTML, but I think it's true that HTML is very simple.
00:00:51.960 I'm very upfront about that. But because it's simple, we often make the mistake of assuming that it's not valuable.
00:01:03.120 I'm hoping to dispel that way of thinking today because it's something that we use a lot, and it plays a pivotal role in making good functional websites.
00:01:08.960 The functionality of a website is constructed from what we provide the browser, typically via HTML.
00:01:14.479 We specify whether we want a heading, what kind of heading it should be, a paragraph, a date, a form, a label. There's a whole suite of elements we can choose to best represent our content.
00:01:20.880 And then, of course, there's the div, which has no meaning and doesn't mean anything. When you use a div, it means the content can be anything.
00:01:31.880 But if you choose a generic element, you're going to get generic output, and you lose the benefits of the language.
00:01:38.040 This output can be hugely problematic for assistive technology and for accessibility.
00:01:43.320 Assistive technologies attempt to read our HTML to infer information about the page and its content. Not everyone and everything will interact with your page the same way; there are many technologies that try to read and consume our content, relying on us to use the language correctly.
00:02:01.240 This includes Google search bots, reading apps like Safari's reading mode, text-to-speech tools like Alexa and Siri, or accessibility tools like screen readers.
00:02:08.160 It's not just our eyes that are going to consume our content. The DOM and the HTML play a big part in how successful that can be.
00:02:25.760 Now, as the browser creates the DOM, it also modifies the DOM tree to form an 'accessibility tree' which takes the native semantics of HTML and creates an interface for reading and navigating a page.
00:02:41.120 A screen reader, for example, is able to interpret the accessibility tree and reproduce it as speech. Major browsers like Chrome and Firefox have accessibility tree inspectors that allow you to look at the accessibility tree.
00:02:58.200 The accessibility tree is made up of what we provide the DOM via HTML. If we don't utilize HTML well, what it generates is not very good.
00:03:10.040 A poorly structured page about my dog Jello, for instance, may just be made of divs, including the links at the top which have an onclick event. All you get from the accessibility tree is a bunch of sections and text leaves.
00:03:29.400 If you compare that to a page that uses more meaningful HTML, you can see there's a lot more information: paragraphs, graphics, block quotes, and landmarks. There's a more defined and meaningful structure.
00:03:49.319 A really good way to demonstrate this is actually with a screen reader. So we're going to listen to that. We're going to use Apple's VoiceOver for Mac, and we're going to look at the div page first.
00:04:10.000 So let's have a listen: "Home, good dogs, bad dog myths. Dogs, they are good. We are dedicated to educating the world on why dogs are good and how they can make your life good."
00:04:22.040 Mandy Michael, August third, 2018. Why are dogs good? Dogs are loyal, intelligent, devoted, and affectionate. They are known to improve our physical and mental health.
00:04:34.160 Mitch and Jello, also known as JelloSL, screen percent 20 shot percent. Okay, terrible image. It was a screenshot from Instagram; I didn't rename it and didn't use an alt attribute.
00:04:41.600 So it reads out that really terrible file name. Now, this was not very good. If you didn't notice, it said "third" instead of "August third" for the date.
00:04:53.080 It didn't tell us that there were links in the page. And the reason it didn't tell us is because, as far as the accessibility tree is concerned, it's just text. It doesn't know the on-click event is there.
00:05:10.160 So in comparison, let's listen to the one with better HTML: Navigation, main navigation, one item list, three items, visited link, home link, good dogs link, bad dog myths.
00:05:21.919 Heading level one, dogs. They are good. We are dedicated to educating the world on why dogs are good and how they can make your life good.
00:05:34.520 Mandy Michael, August third, 2018. Heading level two. Okay, I won't make you listen to the image again. It is better, but I feel like my point was made.
00:05:47.680 This is a really simple page and just a very small part of a really simple page, and the differences are quite noticeable. It told me how many links there were, that I had visited a link, that something was a link, and it read out headings.
00:06:05.560 The date was better, and all I did was pick HTML that represented the content. Now we have a functional page. Prior to that, it was not very functional.
00:06:18.680 The user had to do a lot of the heavy lifting and take on the cognitive load to try and figure out what was going on. It's not just accessibility that benefits from a more considered approach to HTML.
00:06:31.039 Overlooking HTML can lead to a very large complex DOM tree, and this can impact your load times. As users and scripts interact with your DOM, the browser has to recompute the position and styling of all nodes, which can severely impact rendering time.
00:06:47.760 Google's Lighthouse Performance Tool recommends less than 1,500 nodes and will warn at 800, so that should be an indicator that you want to be way on the low end of those numbers.
00:07:02.800 You might think that's a lot and that you'll never hit that, but more complex pages, especially in web apps with lots of widgets, tools, and features, can easily exceed this by mistake.
00:07:15.160 Especially if you're building at a component level, these days we build an isolated component with a div here and a div in that component and a component wrapper with more divs.
00:07:27.520 It's very easy to forget that all of these things have to come together on one page. While you might check that the component works, most people don't check what the actual HTML is on the page.
00:07:38.360 They've just checked the functionality, and as the accessibility tree is made up of what we provide the DOM, any performance impacts to the DOM further impact the accessibility tree.
00:07:50.480 I saw this great talk by Eric Bailey, who is an inclusive design advocate, and he says that when the accessibility tree is slowed down by excessive code, it can create a lack of synchronization between the current state of the page and what is being reported via assistive tech.
00:08:11.639 This results in a mismatch between the page and what the user is presented with via the accessibility tree.
00:08:18.360 So, as you can probably imagine, that's very confusing. You can kind of think of it like bad lag in a video game or bad dubbing, for example.
00:08:36.079 It's confusing, and users have to do a lot more work to figure out what's going on. In the worst-case scenario, it could crash the browser.
00:08:41.360 At the end of the day, everything that we put into our page impacts our performance and our accessibility. That includes every div, every button, and every link. Everything adds up to create these negative experiences with performance and accessibility.
00:08:58.600 So we need to dedicate some time to how we use our HTML. This was eight minutes of me talking just to say, don't just use divs. I'm not saying don't ever use them; they have a purpose.
00:09:16.840 Just don't only use divs. And when you are using HTML, use it correctly. For example, headings are very important, and they're numbered for a reason.
00:09:36.360 We're good with numbers, typically use them in order. They provide a clear structure and hierarchy for the page, and when you use them out of order, you mess with that hierarchy.
00:09:52.800 Headings are important for a number of reasons: Google Search bots use them to prioritize content and figure out what's important. They're also part of that little search preview in Google.
00:10:12.240 But importantly, they're very important for accessibility because users using assistive technology typically use headings to navigate the page via tooling, and that might be with keyboard shortcuts, through a screen reader, or something like the rotor.
00:10:30.640 The rotor is up on screen, which is kind of like a table of contents. It'll group things like links, headings, and landmarks, allowing people to navigate through and jump to sections on the page.
00:10:50.320 So if you don't use headings and you don't use them properly, you're taking away the user's ability to navigate your page. That would be like having no navigation and trying to figure out where you need to go by some imaginary lucky dip.
00:11:07.760 We should also use appropriately named elements for what we're building. If you have a header, use a header; a footer should be a footer; nav should be nav; article should be an article; label for labels; form for forms; button for buttons; section for sections; image for images.
00:11:28.320 HTML is intentionally simple; it's named to help you out. It's not a trap. Nobody's trying to trick you. I'll be the first to admit it's not always that simple.
00:11:44.480 We have link and anchor, which can be confusing, and sometimes it's not obvious what something should be, but it's a really good place to start because it is trying to be helpful.
00:12:07.920 It will improve your accessibility just by changing the HTML, so if that's the only thing you do for accessibility, that's a big step forward.
00:12:29.480 In some cases, it might also reduce the number of nodes on the page because you're simply being more considered in your approach.
00:12:46.200 More often than not, you should also make use of built-in functionality over creating your own. I know this isn't always easy to do, but it's a good place to start.
00:13:10.720 There are a lot of useful built-in features that don't require additional JavaScript. Now, I'm not sure about the Ruby community's position on JavaScript, but as a front-end developer, I have to say we definitely could use less of it in our websites.
00:13:31.240 So if you can use native functionality, you can have less of that. It also tends to work better across mobile devices and for accessibility as well. Not always, but typically, it's a lot better.
00:13:49.320 Definitely better than Stack Overflow code might be better than ChatGPT and co-pilot. I don't know, that might change over time as they get smarter.
00:14:07.960 There are some good things you can use, like details, which is like an accordion; the date picker, which I'm sure you're all familiar with.
00:14:22.640 Actually, this one's an interesting one: Date pickers are great for discoverable dates like appointments, you know, like next Tuesday in three weeks.
00:14:36.760 They are not great for dates of birth, especially the older you get. I don't like having to click back to the 1900s to find my year of birth.
00:14:54.200 It's a very humbling experience. There's a great article called "You Might Not Need a Date Picker" by Adrian Roselli; it's in my resources, and I highly recommend you read it.
00:15:07.920 You can just use a text input for the date of birth.
00:15:22.400 Another situation you might come across with these is where you get a design that is pretty but doesn't match the native style.
00:15:36.120 What I would say about that, between us, is just because it's in a design does not mean you have to do it. It's controversial, but I'm not saying be a jerk about it.
00:15:49.679 There's always room to have these discussions with designers. There's always room for compromise, especially if it's going to make functional accessible improvements to your page.
00:16:05.320 So don't feel like just because it's in the design it's something you have to do. Definitely ask about it if you can.
00:16:19.760 That said, there are also things with really good styling options, like the dialog, which is kind of like a modal where the page behind it is disabled.
00:16:33.480 Another option is the popover, which you might say is exactly the same as a dialog, but it's not. It does not disable the page; this is better for toast notifications or content pickers.
00:16:46.320 It's actually kind of new; it's been supported in the browsers for about a month now. There's also a JavaScript API, but who cares about that.
00:17:01.240 Of course, buttons have lots of useful features, but typically people these days do this. And I know we had the eight minutes of don't use divs, but I wanted to show my little table here.
00:17:14.360 Because it really drives the point home: buttons have all these features, specifically, they're very good for accessibility, announce, very assistive tech keyboard interaction, focusable.
00:17:30.760 Reported to the accessibility tree, divs, however, have none of that. If you use a div to replicate these features, you need to write more code, test more code, and maintain more code.
00:17:45.560 That means you've got more JavaScript on your page, which we've already established is a bad thing. I mean, I love JavaScript, don't get me wrong, but you don't need it to make a button.
00:18:03.760 When we already have an HTML element, don't make your life more difficult. When you make use of native functionality, it's basically like using a JavaScript library that's already built for you.
00:18:14.120 This means less JavaScript, smaller JavaScript bundle sizes, which improves the performance of our pages.
00:18:28.920 Now we're going to talk about optimizing and loading prioritization. To do that, I'm going to briefly talk about browser prioritization.
00:18:50.720 With HTTP/1, we would have multiple TCP connections, and they would load one resource at a time, so prioritization was based on whatever was requested first.
00:19:09.560 But with HTTP/2 and HTTP/3, this was changed. Instead of multiple connections, it was changed to a single connection with multiple requests at the same time.
00:19:30.360 However, that doesn't mean that every request can be responded to at the same time because a connection is limited in how much data it can send.
00:19:49.080 This is particularly true at the start of a connection, as we can only send a limited amount of data for one network round trip.
00:20:04.920 Eventually, the server has to decide which resource it's going to respond to first.
00:20:20.600 As a result, the order of prioritization can have a big impact on your performance because, as it prioritizes one thing, it's going to deprioritize another.
00:20:38.400 If you send the JavaScript first, your images are delayed, and vice versa. This is particularly important for render-blocking items like JavaScript and CSS.
00:20:56.320 We need to download them in full before they can be applied and executed.
00:21:12.800 Additionally, browsers prioritize things differently, so depending on how you have things set up, you might see noticeable differences between each browser for your performance.
00:21:29.600 So what can HTML do for this? They introduced priority hints, specifically the fetch priority attribute.
00:21:49.840 Fetch priority allows you to specify the priority of resource types like CSS, fonts, scripts, and images, allowing us to change that default priority from the browser.
00:22:07.680 It also gives us the opportunity to make things more consistent across browsers. It has three options: high, prioritize, low, deprioritize, and auto, which is what the browser does by default.
00:22:30.240 Now, often when people use this, they expect that if you set a high priority, it's the highest priority; if you set a low priority, it's the lowest priority, but that is not what happens.
00:22:47.560 It actually just sets a relative priority. It's only going to raise or lower the priority by a specified amount.
00:23:06.560 For example, in Chrome, stylesheets are the highest priority by default. If you set a fetch priority of high, it's going to retain the highest priority.
00:23:25.440 If you set a fetch priority of low to a stylesheet, instead of being a low priority, it will be downgraded to a high priority.
00:23:45.120 So in neither of these situations are we explicitly saying high or low priority; it's just adjusting it relative to the browser rules.
00:24:14.320 A really good place to use this is in image carousels that marketing teams love. If you set a fetch priority of high to the first active image, it will request that quicker and therefore download quicker, improving your performance metrics.
00:24:36.160 This is particularly effective if it's in the viewport as part of the largest contentful paint.
00:24:56.200 If you set it to low, they will come after that first main one, so it's a really good way to utilize this.
00:25:06.600 Browser support is very good; I would say Chrome, Safari, Edge, and the associated mobile browsers all support it. However, it's not supported in Firefox yet.
00:25:18.400 They're actively working on it. The best thing about HTML is it'll just ignore it if it doesn't know what to do, so you can use it in the other browsers and wait for Firefox.
00:25:38.200 Next, I want to talk about requesting a resource from the server. This can take a really long time, so if you can handle it ahead of time, you can make your websites and applications feel a lot faster.
00:25:56.960 To do this, we use resource hints. There are two options: preconnect and DNS prefetch.
00:26:13.760 We use them with the rel attribute. So rel='preconnect' and rel='dns-prefetch', you can apply this to a link element in the head of your document.
00:26:28.640 If we look at preconnect first, it essentially informs the browser that your page intends to establish a connection to another domain and that you'd like the process to start as soon as possible.
00:26:49.520 This can speed up load times by about 100 to 500 milliseconds by establishing early connections. It's really handy for image CDNs and streaming media.
00:27:10.400 However, if you're making a lot of connections to third-party domains, preconnecting to all of them is counterproductive, so it's best to preconnect only on critical connections.
00:27:28.240 For everything else, you can use DNS prefetch, which saves time on the first step of the DNS lookup, usually about 20 to 120 milliseconds.
00:27:47.000 Now, that might not seem like a lot, but in a positive way, this time adds up. If you can save 50 to 100 milliseconds multiple times on multiple resources, you'll start to see performance improvements.
00:28:03.680 Preconnect has great support. DNS prefetch is only supported on HTTP and not HTTPS in Firefox. It's also not supported in iOS Safari or the Android browser.
00:28:20.720 But again, you can still use it in the others.
00:28:37.040 Finally, we are going to discuss preload. Preload is probably the most commonly used performance HTML feature. We use it the same way that we use the other two I just talked about, with the rel attribute on a link element and a value of preload.
00:28:56.640 What it does is help to prepare resources that you don't need right now but will need later. Keep in mind, again, when you preload one thing, you prioritize that and deprioritize another.
00:29:21.760 As a result, you only want to use that on critical connections, like preconnecting.
00:29:37.640 Unfortunately, people often misuse it. Zack Leatherman did this great tweet that I loved. If you use preload on everything or in the wrong places, you can actually make things worse.
00:29:49.840 I'll use this example from Robin Marks, which is a response to that previous tweet. What we see is an example without preload and with preload.
00:30:09.760 In the first example, the image request is deferred until after the JavaScript is downloaded, and it takes about 2.25 seconds, which is quite a long time.
00:30:24.920 In the second example, the image is requested alongside the JavaScript, and it's downloaded quicker, which is great.
00:30:39.760 However, what is more likely to happen is your image and your JavaScript are going to fight for bandwidth and priority, delaying both the JavaScript and the image download.
00:30:54.680 In some cases, the image might even download before the JavaScript, creating a janky page experience.
00:31:10.880 So you need to be careful about how you use this feature. You need to test it because it might not give you the results you were expecting.
00:31:28.480 Preload should be used for assets not loaded directly by the HTML but critical to the page experience. Consider things inside CSS, like fonts and images, or anything loaded by JavaScript, such as JSON, imported scripts, web workers, or large videos.
00:31:42.720 Finally, I wanted to talk about 103 early hints. This is not HTML; it is an HTTP status code called 103 early hints.
00:31:58.160 The reason I wanted to mention this is that early hints define new interactions between a client and a server.
00:32:15.360 You can utilize everything I've just talked about: DNS prefetch, preload, fetch priority, and preconnect.
00:32:30.640 For example, it will allow the browser to preconnect to sites or start preloading resources even before the server has prepared and sent the final response.
00:32:49.640 While the syntax is a little different, the great part about this is that it's transferable knowledge. You know if you live in that land more than you do in HTML or vice versa.
00:33:06.240 Sometimes you'll find it's better in early hints versus HTML and vice versa. Support is pretty good.
00:33:22.880 Preload is not supported in Safari, and behind a flag in Firefox.
00:33:39.760 So, what I want to finish with is to please make the most of HTML. Spend a bit of time learning it and how you can apply it to your pages for your content.
00:33:56.960 You'll make things more useful and more usable, not just for performance and accessibility, but for our users and different technologies as well.
00:34:14.640 All by using a technology you're already familiar with, just using it a little bit better.
00:34:31.360 There is so much to be gained from using HTML well. It's not difficult to learn, and there's absolutely nothing to lose.
00:34:49.960 Thank you very much! I hope you got something out of my talk. If you have questions, please come speak to me or reach out on my social networks. My resources are up on GitHub through this QR code. Thank you!
Explore all talks recorded at RubyConf AU 2024
+14