Integrating Accessibility into Frontend Development

The CARE (Coding for Accessible and Responsive Experiences) principle should be integral to a holistic development approach.

Introduction

Accessibility should be a top priority throughout development, especially during the coding and testing phases. Like everything else in software engineering, detecting and resolving issues early on — not just bugs but any deviations from best practices — prevents expensive complications down the line.

Coding for accessibility should be viewed as another engineering principle that front-end engineers should incorporate continuously while developing. Accessibility should not be viewed as an add-on task or a final consideration but as part of a holistic effort to create efficient, functional, and accessible products.

  • DRY — Don’t Repeat Yourself
  • KISS — Keep It Simple, Stupid
  • YAGNI — You Aren’t Gonna Need It
  • CARE—Code for Accessible and Responsive Experiences ~ Accessibility should be treated as an integral part of the development process, ensuring that products are usable by as wide an audience as possible from the beginning.

The Importance of CARE: Coding for Accessible and Responsive Experiences

This principle advocates for integrating accessibility from the initial stages of web development. If you’re beginning to explore accessibility in a developer context, the Web Content Accessibility Guidelines (WCAG) serve as a fundamental starting point.

  • Developing Websites for Accessibility
  • Web Accessibility Training

Including accessibility into your coding practices widens your user base by making applications accessible to individuals with disabilities and enhancing everyone’s overall user experience.

Keeping accessibility in mind while coding

Frontend developers play a significant role in determining how applications look and function. A well-designed and properly developed interface goes a long way in ensuring that a website is accessible and provides a good user experience. This section will explain how to implement the CARE principle in styling and structuring your front-end code.

Color Contrast

The WCAG recommends a minimum color contrast ratio of 4.5:1 for normal text to ensure that text stands out against its background, which is crucial for users with visual impairments using your product.

/* Best Practice for Color Contrast */
/* Ensuring good contrast for better readability */
body {
  color: #444444; /* Dark grey text */
  background: #ffffff; /* White background */
}

Typography

Typography should be easy to read and scalable. Scalable fonts allow users to adjust text size to their devices’ needs.

/* Best Practice 1 - Ensure font-size is no smaller than 12px */
/* Best Practice 2 - Use relative size so font can be scaled */
p {
  /* Ensures min size of 12px but scales with the viewport width */
  font-size: max(12px, 2vw);
}

Responsive Coding

Responsive web applications are usable on any device, from desktops to smartphones. Media queries and relative units can help achieve a flexible and accessible layout.

/* Mobile-first CSS */
/* It's easier to scale up and add complexity for larger screens vs scaling down */
body {
  margin: 0;
  padding: 10px; /* Adequate padding for mobile devices */
  font-family: "Arial", sans-serif; /* Readable font */
  font-size: 16px; /* Default text size for readability on mobile */
}
/* Using a relative unit for line-height to ensure text readability across devices */
p {
  line-height: 1.5;
}
/* Media query for tablets and larger devices (greater than 600px) */
@media (min-width: 600px) {
  body {
    padding: 20px;
  }
  p {
    font-size: 18px;
  }
}
/* Media query for desktops and larger screens (greater than 992px) */
@media (min-width: 1024px) {
  body {
    padding: 30px;
  }
  p {
    font-size: 20px;
  }
}

Semantic HTML and ARIA (Accessible Rich Internet Applications)

Use HTML tags in accordance with their semantic meaning. This means to use each tag and its related attributes for its intended purpose and appropriately in the overall document structure.

ARIA supplements the semantics of HTML elements and helps assistive technologies navigate the page.

Example demonstrating CARE with the use of both semantic HTML and ARIA:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <!-- Viewport meta tag ensures the site is responsive. -->
    <!-- Accessible applications are responsive applications -->
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Accessibility in Technology: Frontend Practices</title>
  </head>
  <body>
    <!-- Header element for introductory content or navigational links -->
    <header>
      <!-- Navigation tags provide a way to identify groups of links -->
      <!-- aria-label describes the html element, helps users identify the purpose of this navigation block -->
      <nav aria-label="Main navigation">
        <ul>
          <!-- Descriptive link text helps users understand link purpose -->
          <li><a href="index.php">Home</a></li>
          <li><a href="accessibility-gallery.php">Accessibility Gallery</a></li>
          <li><a href="about.php">About Us</a></li>
          <li><a href="contact.php">Contact Us</a></li>
        </ul>
      </nav>
    </header>

    <!-- Main tag for the primary content of the document -->
    <main>
      <!-- Heading tags establish a hierarchy of information -->
      <!-- h1 is the highest level of heading and should be used once per page -->
      <h1>Enhancing Accessibility in Technology</h1>
      <p>
        Explore how technology can be designed to be accessible and inclusive
        for all users.
      </p>
      <!-- Section tags can be used to group related content -->
      <!-- aria-labelledby points to an element that labels the section and builds upon document structure -->
      <section aria-labelledby="accessibility-gallery-heading">
        <!-- h2 follows h1, and is used for major subheading -->
        <h2 id="accessibility-gallery-heading">
          Accessibility Innovations Gallery
        </h2>
        <!-- Image tags should include alt text for screen readers -->
        <!-- Alt text should clearly describe the image's content and purpose -->
        <img
          src="imagePath/accessibility-tech.jpg"
          alt="A demonstration of accessible technology featuring adaptive devices and software interfaces"
        />
      </section>
      <section aria-labelledby="latest-accessibility-heading">
        <!-- id used with aria-labelledby connects the section to the heading element -->
        <!-- id identifies an element in a document in relation to the document's structure -->
        <h2 id="latest-accessibility-heading">Latest in Accessibility</h2>
        <!-- <article> specifies content which is meaningful on its own -->
        <article>
          <!-- h3 is used for the header of sub-sections under h2 -->
          <h3>Accessible Design Principles</h3>
          <p>
            A deep dive into the core principles that guide the development of
            accessible technology.
          </p>
          <!-- link tags should contain intuitive text -->
          <a href="https://www.pluralsight.com"
            >Visit Pluralsight to learn more
          </a>
        </article>
      </section>
    </main>
  </body>
</html>

When developing applications using modern frameworks such as React or Angular, ARIA becomes particularly beneficial when creating reusable components agnostic to the overall document structure.

import React from "react";

interface AccessibleButtonProps {
  label: string; // Descriptive label for the button, used for both display and accessibility.
  onClick: () => void; // Callback function that is executed when the button is clicked.
  disabled?: boolean; // Optional boolean to indicate whether the button should be disabled, defaults to false if not provided.
}

// AccessibleButton component defined with TypeScript types for props
const AccessibleButton: React.FC<AccessibleButtonProps> = ({
  label,
  onClick,
  disabled = false,
}) => {
  return (
    <button
      aria-label={label} // Provides an accessible name using aria-label
      aria-disabled={disabled ? "true" : "false"} // ARIA attribute to indicate the disabled state
      onClick={onClick} // Event handler for click events.
      style={{
        backgroundColor: disabled ? "#ccc" : "#007BFF", // Visual styling provides feedback on the disabled state.
        color: "white",
        fontSize: "16px",
        borderRadius: "5px",
        cursor: disabled ? "not-allowed" : "pointer", // Cursor style changes depending on the disabled state.
        outline: "none",
      }}
      onKeyDown={(event: React.KeyboardEvent<HTMLButtonElement>) => {
        // Keyboard accessibility: Allows the button to be activated with the Enter or Space key.
        if (!disabled && (event.key === "Enter" || event.key === " ")) {
          onClick();
          event.preventDefault(); // Prevents default action (e.g., page scrolling when pressing Space).
        }
      }}
      disabled={disabled} // Native HTML attribute to disable the button
      tabIndex={disabled ? -1 : 0} // Manages focus via keyboard: when disabled, the button is not focusable.
    >
      {label}
    </button>
  );
};

export default AccessibleButton;

Integrating Accessibility Tools into Your Development Environment

Incorporating accessibility tools into your development process helps you keep CARE front of mind. This section will provide an overview of essential tools you should consider integrating into your daily workflow to enhance the accessibility of your applications.

Linting Tools

ESLint with Accessibility Plugins: ESLint is a popular JavaScript linting tool that can help enforce coding standards and catch common accessibility issues early in development.

  • eslint-plugin-jsx-a11y is a static accessibility evaluation plugin for React

Look for linting tools that support the enforcement of semantic HTML and appropriate ARIA attribute usage. a11y linters will provide a static code check for accessibility issues.

Browser Extensions

  • WCAG Color Contrast Checker
  • Wave Web Accessibility Evaluation Tools
  • Google Lighthouse

Browser extensions provide immediate feedback on accessibility issues, making them great for quick checks and iterative improvements while developing.

Accessibility and Testing

Ensuring that web applications are accessible to all users, including those with disabilities, requires a combination of manual and automated testing strategies to catch any accessibility issues that might not be addressed during the coding phase. This section discusses the approaches and tools that can be integrated into testing workflows to enhance accessibility.

Unit and Integration Testing

Jest-Axe integrates accessibility checks into Jest unit tests, allowing developers to automatically evaluate components for accessibility issues as part of their testing routine.

import React from "react";
import { render } from "@testing-library/react";
import { axe, toHaveNoViolations } from "jest-axe";
import MyComponent from "./MyComponent";

// Use the toHaveNoViolations method for accessibility checks
expect.extend(toHaveNoViolations);

describe("MyComponent", () => {
  it("should have no accessibility violations", async () => {
    const { container } = render(<MyComponent />);
    const results = await axe(container);
    expect(results).toHaveNoViolations();
  });
});

Cypress-Axe integrates accessibility checks in Cypress integration tests, allowing developers to assess entire pages and interaction flows.

import "cypress-axe";

describe("Checkout Process Accessibility", () => {
  it("should pass accessibility checks through the checkout flow", () => {
    cy.visit("/shop"); // Navigate to the shopping page
    cy.injectAxe(); // Inject the axe-core library for accessibility testing

    // First accessibility check on the initial shop page
    cy.checkA11y();

    cy.findByText("Add to Cart").click(); // Simulate adding an item to the cart
    cy.findByText("Cart").click(); // Navigate to the cart page

    // Second accessibility check after interactions on the cart page
    cy.checkA11y(); // Perform another accessibility check

    cy.findByText("Checkout").click(); // Navigate to the checkout page
    cy.wait(500); // Wait for page interactions to complete

    // Final accessibility check on the checkout page
    cy.checkA11y(); // Perform final accessibility check
  });
});

Manual testing

By engaging with the application as users with disabilities might, developers can better understand the practical challenges and learn to code solutions that address these issues preemptively. Here’s a quick checklist that should be used in conjunction with the other strategies already addressed.

Manual accessibility checklist:

  • Keyboard navigation

    Ensure all interactive elements like links, buttons, and form controls are navigable using the Tab key.

  • Responsiveness

    Verify that applications are both usable and display correctly on all devices.

  • Interaction

    Interactive content should be intuitive and predictable; focused elements should not change the context or update the page. Users should have sufficient time to interact with the content and be notified of time limits. Applications should provide clear error and confirmation feedback.

Conclusion

The CARE (Coding for Accessible and Responsive Experiences) principle should be integral to a holistic development approach. Incorporating accessibility from the initial stages of the development process to testing reinforces the principle. It keeps accessibility as not just an add-on or afterthought but an essential aspect of software development.