Frontend magic: how to add accessibility to your daily routine
Ever stopped to think about how everyone experiences the digital world? Well, that's where digital inclusion comes in, and it's huge. It's not just about getting tech into everyone's hands; it's about creating experiences that everyone can enjoy.
Many countries have rules about making digital services easy for everyone to use. But it's more than just ticking a legal box. It's about being part of a team that really gets the importance of including everyone. This article by our frontend developer Katarina Kondareva is gonna dive into why we need to put accessibility front and center, and how it's not just for the devs – designers, content creators, managers, everyone's in this together.
Making our digital products accessible means they can reach more people, including those with disabilities. Stick around, and let's explore how we can make accessibility a part of your daily routine and workflow as a frontend developer.
Introduction
In our digital age, digital inclusion has become a cornerstone of technological development. It's not just about ensuring access to technology for all; it's about crafting experiences that everyone can seamlessly engage with, regardless of their abilities or circumstances.
Thus, incorporating accessibility into your workflow is a significant and meaningful process. Establishing an accessibility-focused mindset within your team is a vital task in today's world. This article delves into the reasons why prioritizing accessibility is essential and how to seamlessly integrate it into your processes. While the primary focus is on development teams, the principles discussed in this article are broadly applicable to all teams, including designers, content producers, and management at various stages of the development lifecycle.
Firstly, it's crucial to acknowledge that our products and services must comply with legal standards. Many regions have established laws and guidelines concerning digital accessibility. Adherence to these standards is not only a legal requirement but also helps in avoiding legal repercussions.
Yet, legal compliance might seem somewhat remote from the day-to-day routine of developers. Instead, cultivating an inclusive culture and fostering an organizational ethics that values diversity and inclusivity can be more impactful. This approach naturally extends to the products and services developed by teams. Ensuring digital products are accessible broadens their reach, including to those with disabilities, and demonstrates social responsibility.
Legal and Ethical Imperatives
Compliance with legal standards in digital products and services is non-negotiable.
The EU's Legislative Framework
- EU Web Accessibility Directive (Directive 2016/2102): Mandates WCAG 2.1 Level AA compliance for public sector digital assets in EU states.
- European Accessibility Act (Directive 2019/882): Expands this requirement to most private entities by July 28, 2025, covering a wide range of digital services and products.
In practice, it means the necessity of adhering to the WCAG 2.1 standards.
WCAG (Web Content Accessibility Guidelines), is a set of recommendations designed to make web content more accessible to a wide range of people with disabilities, including auditory, cognitive, neurological, physical, speech, and visual disabilities.
The guidelines are divided into three levels of conformance A, AA, and AAA where AAA is the most stringent level, and are organized around four main principles, often referred to by the acronym POUR, namely Perceivable, Operable, Understandable, Robust.
The POUR Principles of Accessibility
Accessibility revolves around four POUR principles:
- Perceivable: Information must be presentable in ways perceivable by all senses.
- Operable: Interfaces must be usable without any barrier.
- Understandable: Content should be clear and comprehensible.
- Robust: Content must be interpretable by a wide array of platforms, including assistive technologies.
Incorporating Accessibility in Workflows
To deliver software of the best quality we should keep in mind and confirm that Definition of Done for any User Story in our backlogs include the following
- security checks,
- accessibility tests,
- and other tests (performance, functional, behavioral).
Making accessibility testing a routine part of the workflow is vital for legal compliance, code quality, and efficiency. It helps us
- To comply with the law.
- To achieve better code quality
- To avoid spending time on separate accessibility stories
- To improve the development process both timewise and cost wise.
Addressing accessibility issues during the design and development phases is usually less expensive and time-consuming than retrofitting accessibility after a product is launched.
General Guidelines
- Be aware of common accessibility issues.
- Adhere to the POUR principles both in design and implementation.
- Regularly perform accessibility tests including contrast checks, high zoom, keyboard, and screen reader compatibility tests.
- Utilize accessibility testing tools.
- Use the semantic markup and HTML native elements wherever possible.
- Test regularly new and updated components.
Handling Common Accessibility Challenges
- Semantic Markup: Ensure proper use of HTML elements for headings, sections, and navigation.
- Element Order: Maintain a logical order in the DOM for screen readers.
- Links: Use clear, descriptive link text and provide screen reader warnings for new tabs or document links.
- Forms and Inputs: Label inputs clearly and use ARIA attributes for enhanced accessibility.
- Focus Management: Ensure logical focus order and keyboard navigability for interactive elements.
- ARIA Usage: Apply ARIA roles judiciously, prioritizing native HTML semantics.
Some rules and examples to follow to avoid common accessibility problems:
Semantic markup.
When semantic markup is not used and the page’s semantic structure is implied only visually, such as by making text larger and bolder to look like a heading, the page’s semantic meaning is lost.
Rules:
- Identify section headings and heading hierarchy using markup. Use HTML heading elements (h1 through to h6) to identify headings.
- Identify page sections and landmarks. Use semantic elements to define different parts of a web page.
- If a specific landmark role is used more than once on a web page, it should have a unique label.
- Use the HTML native elements whenever possible. For example, choose <button> instead of <div role="button"/> element.
- When multiple <nav>s are used, we must label each of them with the attribute aria-label.
- Identify lists using markup. Use unordered list markup (ul and li) for lists where there is no logical order implied, including navigation lists and menus.
- Mark up data tables using table markup.
- Confirm there is only one <main> per page
Order of elements
Screen readers read page content in a linear order, which is defined by the order that content appears in the source code (the Document Object Model) at a given time. When visual positioning is used to change the order for display purposes, the logical order is lost when read by a screen reader.
Rules: Make sure that content is announced in a logical order.
Testing Tip: Check the DOM of the page. Check the Accessibility tree. Test with keyboard. Listen to the page as it’s read by a screen reader to verify the sequence.
Links
Make sure links are recognizable.
- Ensure the link text makes sense. Avoid generic link texts such as “click here”, “read more” if there are many links on the page with the same texts. Other ambiguous link texts include “more”, “continue”...
- Any link that opens in a new tab or window should give screen reader users warning by setting the aria-label attribute on the anchor link.
<a href=”#” target=”_blank” aria-label=”Download the report, opens in a new tab”>Download</a>
Links pointing to documents (e.g. pdf) should open in a new tab.
Forms and inputs
Rules:
- Provide labels to identify form text inputs.
<label for="name">Name:</label>
<input id="name" type="text" autocomplete="name">
- Use aria-label or aria-labelledby for hidden labels.
<input type="text" name="search" aria-label="Search">
<button type="submit">Search</button>
OR
<input type="text" name="search" aria-labelledby="searchbtn”>
<button id="searchbtn" type="submit">Search</button>
- Avoid relying on placeholder text to label an input field. It disappears as the user starts typing.
- Don’t rely only on color and * symbol for required fields. Use aria-required instead which causes screen readers to announce "required" along with the label text.
<input id="name3" type="text" autocomplete="name" aria-required="true">
You can also use html required attribute:
<input id="name4" type="text" autocomplete="name" required>
- Apply aria-invalid="true" attribute if field validation failed or if required field was left empty. This aria attribute causes the screen reader to announce "invalid" when the field gets the focus.
Focus
The focus order must be logical and clickable elements can be focused with the keyboard.
Rules:
- Structure HTML so that focus moves in a logical order.
- If an element can be clicked, it must also be focusable using the keyboard.
- If a control is hidden but available to receive focus, such as a “skip to main content” link, then it should become visible when it receives focus.
- Style focus state using CSS.
- Set explicitly tabindex="0" or tabindex="-1" for custom elements.
- Tabindex should be set to -1 if the element must not be focusable. Inactive control should have initially tabindex=-1.
ARIA
ARIA (Accessible Rich Internet Applications): A technical specification for making dynamic web content more accessible. ARIA is a powerful tool for enhancing accessibility but should be used judiciously. Overuse or incorrect use can make an application less accessible. The best practice is to use native HTML elements whenever possible, as they carry built-in semantic meaning and accessibility features, and to apply ARIA enhancements to make complex, dynamic content accessible.
Rules of use
- Use HTML elements whenever possible
- Avoid changing native semantics of an HTML element. For example, avoid this code <h2 role=tab>heading tab</h2>
- Confirm that all interactive ARIA controls can be reached and used with the keyboard.
- Do not use aria-hidden="true" on a focusable element.
- Keep in mind that applying aria-hidden to a parent/ancestor of a visible interactive element makes all children of such a parent (including the interactive element) hidden from screen readers. Avoid this error.
- Aria-hidden can be applied only if an interactive element cannot be seen or interacted with as long as it's not focusable.
- If an interactive element is hidden using display:none or visibility:hidden (css is either applied on the element itself, or on any of the element's ancestors), it won't be focusable, and it will also be removed from the accessibility tree. Aria-hidden=”true” is redundant in this case.
- Use aria-label or aria-labelledby
a. on the <nav>, and <main> elements
b. on interactive elements such as <a>, <button>
c. on <aside>
- Don’t use aria-label or aria-labelledby on <footer>, <section>, <article>, or <header> or on any heading element, any non-interactive content such as p, legend, li, or ul, a span or div unless its given a role.
React and Next.js Accessibility Features
React and Next.js offer specific tools and practices to support accessibility.
- Utilize React's "as" pattern for component flexibility and correct semantic markup.
- Implement useRef hook in React for managing focus.
- Next.js offers integrated ESLint support for accessibility and ships Image Components with a required alt prop.
React “as” pattern
The "as" pattern in React serves as a method for abstracting component structures. It allows you to dynamically change the HTML element or React component that is used to render a part of your component. Pattern is also known as "render as another component" or "render as a different HTML tag."
Let’s check an example of abstracting Components using “as” Pattern.
Here we have a CardTitleComponent. Depending on the case and design, we may need to render the Card title as <h2> or <h3> or in some cases as a simple <div> element. Rather than writing complex conditional checks or duplicating code to create multiple similar components, the "as" pattern allows us to pass a property to the component. This property specifies the desired rendering element, streamlining the component's adaptability and reducing code redundancy.
The component will be rendered as h2 if we pass heading_type equal to h2, or as h3 if heading_type is h3, and so on.
- Create a component.
CardTitleComponent.tsx
- Use a component.
Card.tsx
where heading_type can be set “h2”, “h3”, etc.
useRef hook in React for managing focus
To programmatically set focus within your code, you should utilize the useRef hook in React. This hook allows you to create a ref object which can be attached to a JSX element. By assigning this ref object to the ref attribute of the desired DOM node in your JSX, you can directly interact with and manipulate that node. This approach is particularly useful for managing focus, among other DOM-related operations.
Example:
Accessibility in Next.js
Next.js comes with an integrated ESLint experience. By default, Next.js includes eslint-plugin-jsx-a11y to help catch accessibility issues early.
Additionally, tools like ESLint and Prettier can be utilized for further code quality improvements.
Furthermore, the Next.js Image Component has been updated to include a mandatory alt prop, reinforcing accessibility standards.
Accessibility Testing Tools
Available testing tools for Accessibility checks can be broadly divided into automated and manual tools.
Automated testing
We would absolutely recommend to always start with automated tools and to test any new functionality with tools, such as Lighthouse Accessibility Audit, Dev Tools Accessibility trees, and why not try out different browser extensions that can test color contrast and other accessibility issues for you.
We strongly advise you to always start with automated tools. Tools like the Lighthouse Accessibility Audit and browser Dev Tools Accessibility trees are helpful. Additionally, try out various browser extensions that assess color contrast and other accessibility concerns. These tools can help identify fundamental issues, such as color contrast violations, absent text alternatives, and problems with markup or improper use of ARIA attributes.
Storybook
One of the great testing tools is an accessibility addon for Storybook.
First, ensure you have a Storybook up and running for your project
Then run npm install @storybook/addon-a11y
In Storybook main.js (or main.ts) add the following code to config:
And check the Accessibility tab in your Stories.
(image credit: https://storybook.js.org/addons/@storybook/addon-a11y)
Storybook a11y addon powered by Deque’s axe-core catches up to 57% accessibility WCAG issues and is thus a powerful tool to use.
Manual testing
Although automated tools are great for initial accessibility checks, practical experience shows they are not entirely sufficient. Manual testing is essential to assess aspects such as meaningful structure, correct tabbing sequence, and the visibility of focus indicators. Therefore, it is recommended to complement automated testing with manual methods, focusing on keyboard navigation and screen reader compatibility, to ensure a thorough evaluation of accessibility.
Testing with keyboard
- Keyboard testing check
- Visible focus on all interactive elements
- Tab order
- Links, forms, buttons
- Opening and closing menus, pop-ups, modals
How to test (basic commands)
- TAB focuses on next interactive (link or button or
- form element)
- SHIFT+TAB focuses on the previous.
- ENTER activates links.
- SPACE activates buttons
- ENTER submits a form
- ENTER activates buttons outside of forms
- ESC should close modals and popups and most
- custom menus
Screen reader
It's important to thoroughly test your components with screen readers for optimal accessibility. While the Chrome Screen Reader extension is a useful tool, it is advisable to use the VoiceOver utility, especially with Safari, for a more comprehensive evaluation. Additionally, for mobile testing, use VoiceOver (VO) on iOS devices and TalkBack on Android. These tools provide a realistic experience of how users with visual impairments interact with your components, ensuring better accessibility across platforms.
Settings of VO Utility
- Set a voice for each language you need for testing
- Speech —> Verbosity: Medium
- Set “Web —> Navigate web pages by: DOM” as ON
- Check that Visuals —> Panels and menus —> Ensure “Show caption panel” is ON
How to test with VO
- Turn on/off Comd+F5 (Mac)
- Ctrl + Opt: VO modifier keys
- VO + Right Arrow: Move the reading cursor to the next item
- VO + Left Arrow: Move the reading cursor to the previous item.
- VO + Shift + Down Arrow / Up Arrow: Go into/out of objects (like iframes, menus,
- application regions, etc.)
- VO + Space: Activate the focused element
- VO + A: Start reading from the current location of the screen reader cursor
- Ctrl: Stops/Starts reading
High zoom testing
Users with visual impairments often rely on screen magnification to interact with digital content. High zoom testing ensures that your website or application remains usable and legible under magnification.
- Zoom up to 200% to test that all content scales smoothly.
- Here responsive design should help us to solve these issues with zooming.
- Text and links should break into multiple lines.
- Check that no content runs off the screen.
- There should be no overlap.
- Control that all links, buttons, forms, and menus still function with the zoomed content.
Conclusion
By embracing these practices and guidelines, we contribute to a more inclusive and accessible digital landscape, foster diversity and make our products legally compliant.