Check out a free preview of the full Web App Accessibility (feat. React) course:
The "Accessible HTML Solution: Product Details" Lesson is part of the full, Web App Accessibility (feat. React) course featured in this preview video. Here's what you'd learn in this lesson:

Marcy begins addressing some accessibility issues from the Accessible HTML exercise. The ProductDetails component is examined. Headings are added, and "sr-only" classes are applied to hide elements not needed for visual display.

Get Unlimited Access Now

Transcript from the "Accessible HTML Solution: Product Details" Lesson

>> It's time to come together and see what we can fix for HTML problems. So these components had some intentional things in there. I left some of them that were working okay, but there's always improvements we can make when it comes to HTML. So let's go look at this in a browser, and I'm gonna identify some problems that way.

[00:00:23] So going back over to Chrome, we've got our product page here for the K9 Float Coat. So I'm gonna go inspect and go and see what we have. So we do have a header, there's a roll of banner and a header, which I happen to know that you can only have one header roll banner.

[00:00:49] There's only one banner. That is one of the rules around landmarks, so we'll probably have to change one of those. We've got a lot of divs, so just kind of at a glance when I look at this content. And I'm actually gonna dock the DevTools over on the right so I can see more of this.

[00:01:11] When I'm working on mobile viewport sizes, I tend to put my dock off to the side in the DevTools. So there's a lot of divs here, especially when they should be repeated potentially. Let's see what these are. So these are the images going down the screen, there's a group of those.

[00:01:29] So really, those should be in a list of some kind so that in a screen reader someone could find that there are six images, or however many of those. If I go drill down into these, surprise, there's no alt text on these. And we had a great question earlier about backend services and how those could support accessibility.

[00:01:53] So if I'm getting my image assets from the backend, it'd be great if I could consume all texts at the same time on the frontend. I could plug that right into this component and then these would be labeled. And let's see, what else? So some of these components, there's a breadcrumb, the menu hasn't been built out yet, but we do have some icon buttons.

[00:02:15] So let's go inspect some of those, just seeing what's here on the page. So these links, just kind of going by feature, I'm going to inspect these. I can see that the link does have some text in it. It has an empty array label, but there is some screen reader only text in here.

[00:02:37] And so it can be helpful to look at this in the accessibility DevTools to see is something actually being generated, and it is. So that seems to work okay. Further down the page, we've got all these product details, so things like different color variants of this product. They do have alt text, but they're within an ARIA hidden true region.

[00:03:05] So this particular image is being suppressed, but that might not matter too much because it's within a label with some radio inputs. And so when I'm inspecting HTML in particular, I might do this way, where I'm looking at it in the DevTools and then going to fix things kind of on a more targeted basis.

[00:03:30] You probably wouldn't do this flow for an entire page, but sometimes I identify issues just by looking at the source code. So let's go do that. So within our product details, if I scroll down to some of our JSX code, that's where a lot of this stuff is coming from.

[00:03:49] So I see there's an h1 here. This kind of top level element, wait, I'm on ProductDetails, let's go to ProductPage. That'll be the top level element for this demo. So the demo is within the rest of our slide materials, but the kind of the intent is to think of it as its own thing cuz that's what we'd end up on a customer-facing website.

[00:04:16] So kind of thinking of it that way, our scope is really any accessibility issues that we might introduce by treating this as its own document, we just kind of ignore for the moment. But we need some landmarks in here, I think. So looking at the page itself, I'm gonna close this and just go look at this.

[00:04:43] So we've got our header up here at the top. I think everything below the header could go into a main landmark. And so that way, we have this separation between those regions of the page. This side content with the product title and reviews and price and everything, you might be tempted to put that into an aside.

[00:05:04] But if it's inside of a main element, that's not gonna be top level anymore. So we kind of have to choose, main has to be top level, meaning it's not wrapped in any other landmarks aside. Also has to be top level, so it might not be the right choice for this one.

[00:05:22] Maybe it does not necessarily need to be in a semantic landmark, we could use headings. Let us look at our Headings tool, I don't think we've really seen that yet. For this page, I am trying to think of how I wanna do this, I think our example has stuff fixed on it already, but let's look at this scope in here.

[00:05:47] I guess we could look at Headings in Accessibility Insights. So the completed example has h1 for the product title, and then h2s for these major parts of the page. And so that's way helpful, the example we're gonna go and look at in code, none of these are marked up as headings, maybe the h1.

[00:06:12] But some of those subheadings can be super useful. So in my other extensions, one that I haven't shown you yet today is the Web Developer extension. It's for Chrome and Firefox, it pops up this little menu of options. And under Information > View Document Outline is where we can see our overall heading hierarchy.

[00:06:35] The HeadingsMap tool that was recommended earlier today could do something similar. So it's really helpful to just see the headings at a glance, cuz when you're going to choose what heading level, that can be super helpful. Also, just looking at the page, what are the major parts of this page that would benefit from headings?

[00:06:58] And what levels of those need to be so that they kind of fall in a nice hierarchy? So let's go fix some of those. So within this component, we've got the ProductHeader. I think a lot of those headings over on the right side are within ProductDetails. So let's go look at that.

[00:07:22] That's where the productTitle comes from. It's got the companyName, so it's like who makes the product, and then the productTitle itself. We've got ratings, which I guess one technique I could share with you is if you have a region of a page that conceptually seems like it should have a heading, but there isn't one in the design, you can add visually hidden headings.

[00:07:46] That is a thing. So for this example, if I wanted to add an h2 for Reviews, if we go back to our example, so now we have this Reviews heading here. If I wanted that to be rendered so a screen reader user would benefit from it, but I've hide it visually, I can put a screen reader only class on it.

[00:08:09] So in React, I would say className is sr-only. That's a tail-end utility class. It works really similarly to other visually hidden classes. And in React, className will become class, that's what gets rendered. So that way, if I hit Save here, let's see if there's a few others we can fix before going back over to the browser.

[00:08:34] So here's one for pricing. So there's some spans, it's wrapped in a div. I can select a tag name, and then if I wanna get the closing tag, there's no divs in between here and there, so I could do Cmd+D to select both. Change that to h2, so that gets the price 1 quantity.

[00:08:56] So this is a paragraph, but that would make for a good heading as well. I'm gonna keep it at the same level as the previous headings, and I'm just doing all the headings at once. So I think there's one more in the BuyBoxVariantSelector, that would be color. So what are the colors that are available, or which one's selected?

[00:09:22] So now we've got some h2s. That review heading that we added that was visually hidden is in there, but we don't see it. So now I can run the View Document Outline tool, it's gonna show us the whole slide page. But under the Ruffwear K9 Float Coat, we have headings.

[00:09:44] I screwed one up, or maybe two. [LAUGH] So I wanted one for the price, for the color, quantity, and size. So yeah, I don't think I quite nailed it. Let's go see what we did. So Color, that was selected color. [COUGH] I think I actually want it where the color options are.

[00:10:09] So maybe let me look at the front-end, that's always helpful. So Color, probably just this first part could be the heading. And since I'm using a lot of CSS grid and Flexbox, I can make these sit on the same line next to each other, even though the heading is a block-level element.

[00:10:28] So just because it's sitting next to something visually doesn't mean that I can't use a block-level element like a heading. So I'm gonna change the wrapping element on that one back to a div, and I will make just the color what was a span that might affect the display.

[00:10:48] So if I needed to change the layout of this, I could say flex, using tailwind, and I could say flex-row. And that should keep them next to each other, see how we do. I think there was one on price that I didn't get quite right, so let's go check that one out.

[00:11:09] It ended up being on the price itself, not on the word price. Do we even have the word? I think this is another one we have to add heading, actually. So I might change that one back and go h2 className= sr-only and Price. So now, it looks the same, cool.

[00:11:34] And our little layout fix to get these to sit next to each other appears to have worked. And the Document Outline tool, I have to relaunch it every time so that it can refresh. I wish I could. So View Document Outline, so now it's looking a little bit better.

[00:11:53] We have one that has a colon on it, so either I could make them all have colons or just not worry about it. I don't think the colon will really be announced at all, it's just like a visual detail, not super important. So the debugging tips, one is part of the slide headings around it.

[00:12:12] So our content within our little demo, we've gotten our heading structure looking better. Let's see what else we can fix. So at this point, I think our slide window with everything around the demo had zero accessibility violations. So if we have any in the demo, we should be able to surface just those.

[00:12:34] So I'm gonna go over to axe DevTools, let's see what kind of HTML issues it pulls up. So we have ARIA hidden, it contains focusable elements. So that'll be a good one to dig into. I'm gonna put this on the bottom so we can read it a little bit better.

[00:12:57] So ARIA hidden, we need to look at, we have some buttons that don't have labels in them. Let's go inspect what that is, our Menu button. So that one's pretty important, it's got some SVG in it that is not labeled. We can fix that. I think our Cart button is probably fine.

[00:13:18] So if you see a result has a number, there are multiple issues there. So if I use these little buttons, and I hit Highlight, I can go to the next one. So our little quantity selector, the plus and minus buttons need labels, both of those. Are the ARIA hidden issue that I sort of skipped by.

[00:13:43] That is our announcement carousel up at the top. So the technique that was used for that to try and hide the content that's not currently being shown, it has links in it. So we have to go and change that a little bit. Let's see what else is in here.

[00:14:02] We're missing some alt text for some of the product images. There's seven of those, and then we're missing a form label on, let's see what that was, more on the quantity selector. All right, how about some rapid-fire fixing? [LAUGH] Let's see how many we can fix. Okay, so the BuyBox Variant Selector has the adding and subtracting, I believe, I have to remember where everything is.

[00:14:37] I think it's actually in the ProductDetails. So below that, so here we go, decrementProductCount. So we could say for the remove, we could say Remove one. On the Add button, we could say Add one. And if internationalization was the concern, you could customize how these labels are generated.

[00:15:02] I guess that could be something from if you're consuming assets from the backend, if there's other languages, or I guess, depending on your strategy for that. But that is a whole other side of things that we're not gonna get too deep into right now. So our input for that quantity needed a label as well.

[00:15:23] So we've talked a lot about the label element. The aria-label attribute can work fine on form controls. I think sometimes there's a real preference for text that's on screen. If you can show text in a label, do that first, but just know that for screen reader purposes, we can use aria-label also.

[00:15:47] So for this one, I guess Quantity, it's under a heading of Quantity, maybe Product count. That's the value. So kind of take some inspiration from the variable name. So that will describe what the field is for. And then the actual value like these aria things will describe what's the number, how many items are in there.

[00:16:15] So that should work. I know we had some issues in our header, so let's go up there. That's under ProductHeader. We had two banner, two headers, basically. So there's this header element. And then within Banner, which I'm gonna scroll up to get to, this one also has role of banner.

[00:16:40] Okay, which one do we wanna keep? I think the one that wraps everything that looks like a header. I think this one could potentially go in that header. But if we really wanted to give it a region or some sort of a sectioning element, we could say role= region, and then we can give it a label.

[00:17:01] So this already had an aria-labelledby pointing to this hidden paragraph. So kind of an interesting detail about aria-labelledby is that it will still connect a label on another element, even if that element is hidden with display none. So we'll learn more about ARIA a little bit later. Okay, so we fixed that, I know we've got our Menu button had issues.

[00:17:28] Wait, we have a, let's say, Previous slide. Maybe that one wasn't coming up, but I know it's an issue. So Next Slide, that one had a label. Down in our header, we had a Menu button missing a label. I think the shopping cart had this text within the link, so it was fine.

[00:17:50] This empty aria-label, we could just delete.