Skip to content

Level up: the next 6 bugs to watch for

Accessibility with HTML, CSS, and a touch of JavaScript

Corina Murg smiling. Corina has brown hair and light skin. She is wearing a colorful beanieCorina Murg|
Published on March 2, 2024

Introduction

We continue our hunt for accessibility issues that can affect your portfolio site. We started with Fixing the 6 most common bugs. We noticed that they can be kept in check with just semantic HTML, and at times a bit of CSS or ARIA attributes. Are the next 6 bugs as easy to avoid? Yes, with one exception that might require a bit of JavaScript.

Zooming and scaling Issue number 7

<head><metaname="viewport"// remove these attributes!content="user-scalable=no, maximum-scale=1.0"/><head>

Allow zooming of at least 200%

Users with low vision need the ability to zoom in to read or view content. In fact, most of us make use of the "pinch and zoom" feature on mobile. Either one of user-scalable=no or maximum-scale=1.0 can can block this action. Just don't include them. Your site needs a meta name="viewport", but content="width=device-width, initial-scale=1" is the only necessary attribute.

Allow scaling of text

Instead of zooming in, some users might prefer to adjust the text size in their browser settings. It's important that you use relative units like em or rem for font sizes, and even in your media queries. This way, the text will scale with the browser settings.

Whether the user zooms in or scales the text, all content and functionality should remain accessible.

The title element

<head><title>Web for Everyone</title><head>

Let users know what page they are on

The content of the <title> element gets displayed in the browser's title bar or tab. It's important because:

It helps sighted users identify a certain page when they have multiple tabs open. (It's true, the favicon can play the same role and better since it's placed before the title.)

It helps screen reader users understand which page they are on. As they navigate from page to page, the title is the first element announced by the screen reader.

Do make sure each page has a unique title!

If you're building with vanilla JavaScript, add a title to each HTML file.

It gets more complicated with a Single Page Application (SPA), but each framework has specific features or libraries that allow for updating the title for each page. Research, choose a method, and implement it. (This is the one case where you might need to use JavaScript!)

Example: React custom hook to update the title
import { useEffect } from 'react';
function useDocTitle(title) {useEffect(() => {document.title = title;}, [title]);};

Then import the hook and use it in your component:

import useDocTitle from '../hooks/useDocTitle';
function About() {useDocTitle("About | Web for Everyone");// rest of the component}

Keyboard navigation

Home
Resources
About

Allow keyboard-only users to navigate a page

Not everyone can use a mouse! People who are blind or have low vision, as well as those without fine motor skills, rely on a keyboard to navigate the web.

Make sure all interactive elements on your site are reachable and usable with a keyboard.

How to test:

Press the Tab key to move forward, Shift + Tab to move backward, through the interactive elements on the page. Each element should receive focus and you should see an outline around it. More about how to style the outline in the next section.

If you used semanic HTML tags like <button>, <a> or <input>, this will happen automatically.

If you used <div> or <span>, and forgot the tabindex attribute, the element will be skipped.

Press Enter to activate the element. It should trigger the expected action. For a button the Space bar will also work.

Again, if you used semantic HTML tags, this will happen automatically. With <div> or <span>, these event listeners have to be added explicitly.

Visible focus

// do not remove the outline unless you add another visual cluebutton:focus {outline: none;}

Let sighted keyboard users know where they are on the page

It is important that the element that receives focus changes its appearance. This way the user knows exactly where the focus is and which element will be activated if they press the Enter or Space key.

Most browsers have a default focus style, the focus ring. For example, the default focus style in Chrome is a double, black and white outline. You can choose to override it and create one that matches your design, but it's important to keep it visible.

Here are a couple of options you have:

  • Create a custom focus outline

  • Change the brightness (shade) of the element's background color

Example one: Create a custom focus outline

button:focus-visible {outline: 2px solid color;outline-offset: 2px;}

Define an outline that is 2 pixels thick, solid, and of the color of your choice.

The color and the style can match your design, but make sure you have a contrast ratio of at least 3.0:1 between the outline and the background color of the element, as well as between the outline and the background of the page.

Use outline-offset to set the space between the outline and the edge of the element.

It's not required, but it does improve accessibility and focus visibility. Plus, when used, you only have to worry about the contrast ratio between the outline and the background of the page.

For you to test: Use the Tab key to navigate to the button below and see the custom focus outline in action.

Why :focus-visible and not :focus?

Both are pseudo-classes used to style elements that are focused, but one is smarter than the other. Before we talk about the difference between them, let's talk about the two scenarios in which browsers apply default focus styles:

when elements are focused via keyboard navigation, regardless of the type of element (button, link, input, etc.)

when it is beneficial to the user, regardless of navigation method. For example, for a mouse user it's helpful to see the focus when clicking on an input field, but there is no added value from it when clicking on a button. This behavior improves everyone's experience, without cluttering the interface for mouse users.

When you override the default focus styles using the :focus pseudo-class, your custom styles will apply to all focus events, regardless of how they were triggered (mouse click or keyboard navigation). It's not the end of the world, of course, but we can do better!

:focus-visible is the better choice. It mimics the default behavior of the browser: it applies to all elements reached via keyboard and only to certain elements reached via mouse click. For example, it will add the focus when the user clicks on an input field. Quite smart, right?

Example two: Change the brightness to show focus

One of the most important accessibility guidelines is to ensure that color alone is not used to convey information. This applies to the focus state as well.

For example, changing the background color of a button from blue to green when it receives focus (assuming the outline was removed) is not recommended. Users who are color blind would not be able to tell the difference.

Instead, rely on a change in brightness to indicate focus.

It could be with that same color, like a change from a light blue to a darker blue. Or, it could be with a different color, like a change from light blue to dark gray. These are great options when you have a family of interactive elements nested together.

For you to test: Use the Tab key to navigate through the buttons below and notice the change in the background's shade.

Two things to rememeber:

  When comparing the default state and the focused state, the contrast ratio between the background colors should be at least 3.0:1.

  In each state, the contrast ratio between the background color and the text should be at least 4.5:1.

Did you know? You can emulate vision deficiencies in DevTools!

  • Open Dev tools and click on the three dots in the top right corner

  • Go to More tools and then Rendering

  • Scroll to the bottom and select Emulate vision deficiencies

  • Choose the deficiency you want to emulate (like the type of color blindness) and see how your site looks to users with that deficiency.

Headings in logical order

<h1>The most important heading</h1>. . .<h2>The second heading in line</h2>. . .<h3>The third heading in line</h3><h2>The second heading in line</h2>. . .<h3>The third heading in line</h3>. . .

Help screen reader users understand the structure of a page

When trying to find information on a page, most screen reader users rely on headings. Pressing the H key allows them to visit each heading and get an idea about the structure and the content of the page.

A few rules to follow with headings:

  • Choose meaningful headings that describe the content of a section.

  • Use <h1> at the start of your content.

  • Don't skip heading levels. Use <h1> to <h6> in descending order.

  • Don't use headings for decorative purposes. If you need a word or a phrase to look bigger or bolder on page, use CSS. Do not use heading tags if a heading is not needed.

Did you know?

Automated tools like Google's Lighthouse or axe DevTools can help with headings too!

For the first rule, you will need to rely on your own judgement, but the tools can easily catch if you missed any of the other rules.

What next?

You did it! You now know how to avoid 12 accessibility issues.

Continue to practice and make accessibility a habit. As your coding skills expand, so will the complexity of the sites you build. That means that the accessibility issues you encounter will become more complex too. But you don't have to be alone in this journey.

There are many resources available to help you, and the accessibility community is always ready to answer your questions. Plus, in a larger company, you might have a dedicated accessibility team to support you, or a designer who has already considered accessibility in the design phase.

Equally important, spread the word and share your knowledge with others. Because together we can build a web for everyone.


Ready to learn more about accessibility? Explore Web for Everyone's Blog.