---
title: "How to Make Your Angular Projects More Accessible"
date: "2024-12-17"
slug: "essential-tips-for-creating-accessible-forms-in-angular"
author: "Dany Paredes"
canonical: "https://danywalls.com/essential-tips-for-creating-accessible-forms-in-angular"
description: "When we build apps, we usually focus on delivery rather than covering other aspects like Accessibility and Testing (but testing will be covered in another post). Today, I want to talk about Accessibility. Most of the time, we think accessibility is j..."
---

When we build apps, we usually focus on delivery rather than covering other aspects like **Accessibility** and Testing (but testing will be covered in another post). Today, I want to talk about **Accessibility**. Most of the time, we think accessibility is just to help people with disabilities use our product, but it actually improves the experience for all users.

In December, I spent some time learning about Accessibility, and I highly recommend taking these free courses.

* Learn Accessibility: [**https://web.dev/learn/accessibility**](https://web.dev/learn/accessibility)
    
* Build more accessible Angular apps [https://codelabs.developers.google.com/angular-a11y#3](https://codelabs.developers.google.com/angular-a11y#3)
    

This weekend, I took time to test the skills I learned by building a small form that includes accessibility from the start, including form setup and validation. Let's do it!

I wanted to create the "Letter to Santa" form where my son can send his name, email, and a message to Santa Claus, but I want to build an accessible form with clear and accessible validations and a notification when the message has been successfully sent.

Finally, I got a form like this:

![](/images/posts/essential-tips-for-creating-accessible-forms-in-angular/2f039a39-33d7-4_63463.png)

---

The main goal of the form is to collect information from users. If forms are not accessible, we exclude a significant portion of people, such as users with visual or motor impairments, or those affected by a temporary accident or with their hands busy.

I started improving accessibility by using semantic HTML elements like `<header>`, `<main>`, and `<footer>`, and organizing content hierarchically with headings (`<h1>` to `<h6>`). This helps screen readers navigate the page correctly and also improves SEO.

```html
<header>
  <h1>Write Your Letter to Santa</h1>
</header>
<main>
  <h2>Fill Out the Form</h2>
</main>
<footer>
</footer>
```

The main goal of the form is to collect information from users. If forms are not accessible, we exclude a significant portion of people, such as users with visual or motor impairments, or those affected by a temporary accident or with their hands busy.

I started improving accessibility by using semantic HTML elements like `<header>`, `<main>`, and `<footer>`, and organizing content hierarchically with headings (`<h1>` to `<h6>`). This helps screen readers navigate the page correctly and also improves SEO.

```html
<label for="name">Name</label>
<input id="name" name="name" required type="text" />
```

But forms are more than just input and label; they need validations or error messages that should only appear when relevant, such as after a field has been interacted with (`touched`) or when the form is submitted. But how do I notify the user with a message?

First, the notifications should be announced by screen readers using `aria-live` with a visually clear design for users who do not use assistive technologies and avoid unnecessarily interrupting the user.

> Learn more about [aria-live](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Live_Regions) and [roles](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles)

There are different ARIA roles to use with the notifications for specific scenarios, using `role="alert"` for critical or high-priority messages, such as errors. It automatically interrupts the user and announces the content immediately, or `role="status"` for non-critical updates, such as confirmations or status changes.

```html
    <div class="error" role="alert">
      <p>Name is required.</p>
    </div>
```

But how are those messages announced? You have `assertive`, which stops the current message, or `polite`, which waits to announce by screen readers without interruption.

```html
@if ((nameCtrl.invalid && nameCtrl.touched) || (nameCtrl.invalid && isSubmitted)) {
  <div class="error" role="alert">
    <small>Name is required.</small>
  </div>
}
```

For example, `aria-live="polite"` waits to announce the content after completing its current task. It is perfect for notifications like when a message has been sent:

```json
    @if (messageSent) {
      <div class="notifications" role="status" aria-live="polite">
        <p>{{ message }}</p>
      </div>
    }
```

But what happens when I want content only for screen readers? We can create a utility class like `.visually-hidden` for content that is only meant to be accessible to screen readers and not visible to sighted users.

```css
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}
```

It helps to ensure that essential information is conveyed to users relying on screen readers without affecting the visual layout.

```html
<span class="visually-hidden">Error:</span>
<p>Name is required.</p>
```

Another key point is also is the color, with adequate contrast, the text should have sufficient contrast with its background according but most easy way is using the [color-contrast-checker extensio](https://chromewebstore.google.com/detail/color-contrast-checker/gbfgefkhkofclanlcgnhlbmfgjjomock?hl=en)n.

```css
input.ng-invalid.ng-touched {
  border-color: #e74c3c; 
  background-color: #fdecea; 
}
```

Perfect we can build our form ready with accesibility!! Hey hold a second ? What happend if tomorrow @[Jörgen de Groot](@Alt148) add a new feature , how I can control he don’t break the accesibility ?

The `es-lint` is your friend, first add using the schematics:

```bash
ng add @angular-eslint/schematics
```

The es-lint provide a set of accessiblity rules like `accessibility-label-has-associated-control` to ensures that every `label` element has an associated form control (similar to `accessibility-label-for` but stricter).

```xml
<!-- Incorrect -->
<label>Email</label>

<!-- Correct -->
<label for="email">Email</label>
<input id="email" type="email">
```

or `accessibility-table-scope`, requires data table headers (`<th>`) to have a `scope` attribute, improving navigation for screen readers.

```xml
<!-- Incorrect -->
<th>Name</th>

<!-- Correct -->
<th scope="col">Name</th>
```

Feel free to read more about accesibility es-lint, add these rules to the file (`.eslintrc.json`), adjusting the severity (`"warn"`, `"error"`, etc.) as needed:

```json
{
  "overrides": [
    {
      "files": ["*.component.html"],
      "extends": ["plugin:@angular-eslint/template/recommended"],
      "rules": {
         "@angular-eslint/template/accessibility-elements-content": "error",
        "@angular-eslint/template/accessibility-valid-aria": "error",
        "@angular-eslint/template/accessibility-label-has-associated-control": "warn",
        "@angular-eslint/template/accessibility-table-scope": "error",
        "@angular-eslint/template/accessibility-role-supports-aria": "warn",
        "@angular-eslint/template/accessibility-click-events-have-key-events": "warn",
        "@angular-eslint/template/accessibility-no-positive-tabindex": "error",
        "@angular-eslint/template/accessibility-media-has-caption": "warn",
        "@angular-eslint/template/accessibility-valid-tabindex": "error",
        "@angular-eslint/template/accessibility-input-label": "warn"
        "@angular-eslint/template/accessibility-role-has-required-aria": "error"
      }
    }
  ]
}
```

After run `npm run lint` tada!! we have a linter for our code!

![](/images/posts/essential-tips-for-creating-accessible-forms-in-angular/31097a16-b806-4_63463.png)

## Recap

I hope when you start to create your next project, keep in mind these tips to simplify your accesibility and take care to improve our apps for all users.

_Photo by [Alphabag](https://unsplash.com/@alphabag?utm_source=unsplashx&utm_medium=referral) on [Unsplash](https://unsplash.com/?utm_source=unsplashx&utm_medium=referral)_

