Thinking about accessibility—a few tips to  make a difference
Tags: ux, react, productivity, a11y
Published: 2021-06-20 06:47:29

While conducting an interview session, I asked a candidate about what web accessibility is, the answer was, "Isn't it about aria-label?". It made me smile. It wasn't an unexpected answer. I have experienced the same replies many times while bringing this topic up casually over a cup of coffee chat. 

I know where the root problem lies. I believe it's the lack of awareness and knowledge about accessibility in general. It's a mindset that we consider accessibility as an **optional thing**. Web accessibility is rarely seen as a part of acceptance criteria when writing Jira tickets.

Well, being a web developer, we can change this mindset. We can educate ourselves, spread awareness, share the guidelines. Together we can make the web more inclusive and accessible.

With the motivation aside, It's time to look into a few tips that can quickly get you up and running with accessibility in mind. After all, it's not that scary as you might have thought. Time to make a difference. 

---
## Table of contents
- [Use Semantic elements](#use-semantic-elements-where-possible)
- [Don't use divs for creating a button](#dont-use-divs-for-creating-a-button)
- [Use 'skip to main content' link](#use-skip-to-main-content-link)
- [Don't forget the focus state](#dont-forget-the-focus-state)
- [Never miss the 'alt' tag on your image](#never-miss-the-alt-tag-on-your-image)
- [Link text should describe the purpose of the link](#link-text-should-describe-the-purpose-of-the-link)
- [No ARIA is better than Bad ARIA](#no-aria-is-better-than-bad-aria)
- [Implementing your custom UI widgets](#implementing-your-custom-ui-widgets)
- [Use ‘lang’ attribute to define the language of the page, and element](#use-lang-attribute-to-define-the-language-of-the-page-and-element)
- [Use jest-axe to automate your a11y tests](#use-jestaxe-to-automate-your-a11y-tests)
- [Use CSS to highlight the accessibility issues](#use-css-to-highlight-the-accessibility-issues)
- [Using Icon only as button](#using-icon-only-as-button)
- [VisuallyHidden React component](#visuallyhidden-react-component)
- [Color contrast](#color-contrast)
- [Accessibility checklist](#accessibility-checklist)
- [Learn to operate VoiceOver on your Mac](#learn-to-operate-voiceover-on-your-mac)
- [Use a11y eslint plugin as your dev dependency](#use-a11y-eslint-plugin-as-your-dev-dependency)
- [Use ARIA live regions to announce dynamic changes in the page](#use-aria-live-regions-to-announce-dynamic-changes-in-the-page)
- [Zoom up the page to 200% and see if you can still use the website](#zoom-up-the-page-to-200-and-see-if-you-can-still-use-the-website)
- [Chrome/FireFox extensions](#chromefirefox-extensions)
- [Read articles on accessibility, follow blogs/newsletters](#read-articles-on-accessibility-follow-blogsnewsletters)
- [It’s not only about the UI](#its-not-only-about-the-ui)

---

### Use semantic elements where possible
  - [Semantic elements](https://developer.mozilla.org/en-US/docs/Glossary/semantics) are the ones that convey meaning to both the browser and the developer.  
  - They have some [intrinsic role](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles) associated with them. 
  - Screen readers would announce their role to help visually impaired users navigate a page.
  - The [VoiceOver rotor](https://support.apple.com/en-au/guide/voiceover/mchlp2719/mac) in mac can list available `landmarks`, `links`, `headings` if the semantics elements are used.
  - Improves the page search ranking [SEO](https://developer.mozilla.org/en-US/docs/Glossary/SEO).
  - References: 
    - [Semantic elements](https://developer.mozilla.org/en-US/docs/Glossary/semantics)
    - [Accessibility Through Semantic HTML](https://24ways.org/2017/accessibility-through-semantic-html/)

### Don't use divs for creating a button
  - `div` is not a semantic element, it doesn't convey anything to the browser. It's also non-interactive.
  - Adding a `role="button"` is **not** enough; it won't make it keyboard accessible.
  - You need to add `tabindex="0"` to make it focusable.
  - The **button** element gets you all the aforementioned features for free. 
  - References: [Use button instead of divs](https://web.dev/use-semantic-html/#use-button-instead-of-div)

### Use 'skip to main content' link 
  - For users with some motor disabilities, it can be hard to navigate every link item before reaching the `main` content block.
  - Using the `skip to main content` link allows the users to skip the long navigation links, and land straight to the main content.
  - Put the `skip to main content` link at the top of the page, so that it can receive focus when the `Tab` key is hit.
  - References: 
    - [Skip Navigation links](https://webaim.org/techniques/skipnav/)
    - [Implementing skip to content link](https://www.a11ymatters.com/pattern/skip-link/)
    - [WCAG Guidelines](https://www.w3.org/TR/WCAG20-TECHS/G1.html)

### Don't forget the focus state
  - Focus indicator helps users figure out where they are on the page.
  - It also benefits the users with short-term memory to discover where the focus is located.
  - If you're setting `outline: none` for the focus state, make sure to style this state to make focus clear and visible.
  - Aid in keyboard navigation as you can see a focus ring around interactive elements when tabbing.
  - You can style the focus ring to improve aesthetics; it doesn't have to be ugly.
  - Can use [:focus-visible](https://developer.mozilla.org/en-US/docs/Web/CSS/:focus-visible)
  - References: 
    - [Indicating-focus-to-improve-accessibility](https://hacks.mozilla.org/2019/06/indicating-focus-to-improve-accessibility/)
    - [Designing usable focus indicators](https://www.deque.com/blog/give-site-focus-tips-designing-usable-focus-indicators/)
    - [Tips for focus styles](https://www.nicchan.me/blog/tips-for-focus-styles/)
    - [Style hover, focus, active state](https://zellwk.com/blog/style-hover-focus-active-states/)

### Never miss the 'alt' tag on your image
- Every image that has a semantic meaning should have a non-empty alt attribute value.
- If the image is used for presentational purposes only (Background gradient), you need to pass `alt="" ` value. 
- Skipping the `alt` tag is **not** an option at all.
- References: 
    - [Five Golden Rules for Image alt](https://abilitynet.org.uk/news-blogs/five-golden-rules-compliant-alt-text)
    - [Image Accessibility checklist](https://www.a11yproject.com/checklist/#images)

### Link text should describe the purpose of the link
- It's like your promise to the users. Screen reader users rely on some shortcuts to bring up the links available on your page.
- Link text shouldn't be ambiguous. For example, `click here` as link text conveys no meaning. Use meaningful description text.
- Shouldn't be too long. Long text can be hard to comprehend/remember and might miss conveying the actual purpose of a link.
- References: [link text purpose (WCAG)](https://www.w3.org/WAI/WCAG21/Techniques/general/G91.html)

### No ARIA is better than Bad ARIA
  - Assistive technologies rely on the aria roles of the elements to convey semantics. It's kind of a promise.
  - Using a bad `aria` role can cause more harm than good. So choose it wisely.
  - Moreover, you don't need to use a `role` while using semantic elements. Mostly all semantic elements have implicit roles.
  - References:
    - [No ARIA is better than Bad ARIA](https://www.w3.org/TR/wai-aria-practices-1.1/#no_aria_better_bad_aria)
    - [ARIA Design Pattern Examples](https://w3c.github.io/aria-practices/examples/)

### Implementing your custom UI widgets
 - If you're implementing your own custom UI widget (e.g [Modal](https://www.w3.org/TR/wai-aria-practices-1.1/#dialog_modal)/[Tabs](https://www.w3.org/TR/wai-aria-practices-1.1/#tabpanel)), I'll highly recommend reading [WAI-ARIA Authoring Practices](https://www.w3.org/TR/wai-aria-practices-1.1/#intro) and [WCAG Techniques](https://www.w3.org/WAI/WCAG21/Techniques/#introduction). 
 - This will help you to make informed decisions and avoid basic a11y issues. 
 - Take inspiration from open source libraries that take pride in keeping accessibility as their core feature. [Reach UI](https://reach.tech/), [Chakra UI](https://chakra-ui.com/), [Mentine](https://mantine.dev/guides/ssr/), [Reakit](https://reakit.io/) are some of the examples.
 - References
    - [WAI-ARIA Authoring Practices Guide](https://www.w3.org/TR/wai-aria-practices-1.1/#intro) 
    - [WCAG Techniques](https://www.w3.org/WAI/WCAG21/Techniques/#introduction).

### Use 'lang' attribute to define the language of the page, and element
- Make sure to use `<html lang='prefered-language-of-your-users'>`. For example, `<html lang="en">` would set the language to `English`.
- Allow assistive technologies such as screen readers to invoke the correct pronunciation.
- References: 
  - [language tag syntax mdn](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/lang#language_tag_syntax)
  - [WCAG guidelines](https://www.w3.org/WAI/standards-guidelines/act/rules/html-page-lang-b5c3f8/)

### Use jest-axe to automate your a11y tests
- If you're using jest, it's easy to automate the findings of basic a11y issues via [jest-axe](https://github.com/nickcolley/jest-axe).
- For example, in React, you can create a test utility function like the following:

```javascript
 import { axe } from 'jest-axe';

 /*
 * @param {object} ui element
 * @param {object} axeOptions jest-axe options
 */
const testA11y = async (element, axeOptions = {}) => {
  const container = React.isValidElement(element)
    ? render(element).container
    : element;

  const results = await axe(container, axeOptions);

  expect(results).toHaveNoViolations();
};

  // And now can use it to test your component in jest like:
  it('should have no basic a11y issues', async () => {
    await testA11y(<YourReactComponent />);
  });
```

 - References: [jest-axe](https://github.com/nickcolley/jest-axe).

### Use CSS to highlight the accessibility issues 
- For example, you can create a CSS selector to draw attention towards the issues. For example, draw a red outline if an image is missing an alt tag. 
- And if a developer misses a rule, it would be clearly visible. Check the following examples:
```css

  /* All img tag must have alt attribute. For decorative images, provide empty value (alt="") */
  img:not([alt]) {
    outline: 2px dotted red;
    error: All img elements should have alt attribute;
  }

  /* For tabpanl UI, the <ul> element should have the role of "tablist" */
  .tab ul:not([role="tablist"]) { outline: 0.5em solid red; }

  /* A elements that don't have a class get default styles */
  a:not([class]) {
   text-decoration-skip-ink: auto;
  }
```

### Using Icon only as button
- As Icon button has no visible text associated; it's important to make sure the assistive technologies has a way to announce its name.
- There are multiple ways to do so. let's one example as suggested by [Sara Soudein](https://www.sarasoueidan.com/blog/accessible-icon-buttons/)

```html
 
 <!-- Using visually hidden text, accessible to screen reader -->
  <button> 
   <svg aria-hidden="true" focusable="false" ...>
        <!-- svg content -->
    </svg>
   <span class="sr-only">Menu</span>
  </button> 

```
  and the 'sr-only' would be: 
  ```css
  .sr-only:not(:focus):not(:active) {
   clip: rect(0 0 0 0); 
   clip-path: inset(100%); 
   height: 1px; 
   overflow: hidden; 
   position: absolute; 
   white-space: nowrap; 
   width: 1px; 
 }
``` 
You can explore other techniques in this great article referenced below:
- References: [Accessible Icon Buttons](https://www.sarasoueidan.com/blog/accessible-icon-buttons/)


### VisuallyHidden React component
- You can easily create a reusable react component using the aforementioned sr-only css. It can also be a part of your component library.

 ```javascript
 /**
 * This component will visually hide the content in the DOM, keeping it accessible
 * for the screen reader user.
 */
 import srOnly from '';
 const VisuallyHidden = ({ as: Component = 'span', children }) => (
   <Component className={srOnly}>{children}</Component>
 );
 
 // And then you can use it like: 
 <VisuallyHidden as="h1">I am visually hidden h1 tag</VisuallyHidden>
```

### Color contrast
 - It's important to make sure that your UI has a minimum contrast ratio as described in [WCAG guidelines](https://www.w3.org/TR/WCAG21/#contrast-minimum).
 - Not meeting the color contrast ratio can cause users to perceive your text incorrectly. 
 - If you are a developer, you can collaborate in the design process, and enforce this constraint before working on implementing the actual UI.
  - References: 
    - [Color contrast WebAim](https://webaim.org/articles/contrast/)
    - [WCAG color contrast guidelines](https://www.w3.org/TR/WCAG21/#contrast-minimum)
    - [Accessible colors checker](https://accessible-colors.com/)

### Accessibility checklist
- The following checklists can come in handy when you visually want to keep track of accessibility standards in your app:
    - [accessibility checklist from a11yproject team](https://www.a11yproject.com/checklist) can be handy when it comes to keeping things in check.
    - [accessibility checklist from a11yEngineer](https://www.a11yengineer.com/)

### Learn to operate VoiceOver on your Mac
 - Learning Mac's [VoiceOver](https://dequeuniversity.com/tips/learn-voiceover) tool is super easy. A few shortcuts and you shall be able to operate it in no time. 
 - Try using VoiceOver along with a keyboard to browse your website. You will be amazed to see how good or bad your accessibility ranking it.

### Use a11y eslint plugin as your dev dependency
 - Nothing is better than having a development tool that could warn you when your UI has some basic a11y issues. 
 - If your project uses React, [eslint-plugin-jsx-a11y](https://github.com/jsx-eslint/eslint-plugin-jsx-a11y) is a must-have dev dependency to help you along.

### Use ARIA live regions to announce dynamic changes in the page
  - Use [aria-live](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Live_Regions) to let the screen reader knows about the new content that would appear as of some user actions.
  - Assistive technologies will announce dynamic changes in the content of a live region.
  - Example would be an alert/notification that would appear when an action is completed.
  - This is important to remember when you're creating a SPA (single page application) where content changes without a full page reload.
  - References: 
    - [ARIA live regions (mdn docs)](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Live_Regions)
    - [Using aria-live](https://bitsofco.de/using-aria-live/)

### Zoom up the page to 200% and see if you can still use the website
 - Many users would zoom up your page to 200% or more, and your app should still be functional.
 - Content shouldn't overlap and your page should still be usable. 
 - Make sure interactive elements are still functional.
 - References: 
   - WCAG [Resize Text -- Level AA](https://www.w3.org/WAI/WCAG21/quickref/?versions=2.0#resize-text) success criteria requirement.

### Chrome/FireFox extensions
- The following web extensions can help you identify a few of your web accessibility issues right from your browser:
    - [WebAim](https://chrome.google.com/webstore/detail/wave-evaluation-tool/jbbplnp)
    - [AxeDevtool](https://chrome.google.com/webstore/detail/axe-devtools-web-accessib/lhdoppojpmngadmnindnejefpokejbdd)
    - [Heading map](https://chrome.google.com/webstore/detail/headingsmap/flbjommegcjonpdmenkdiocclhjacmbi?hl=en)

### Read articles on accessibility, follow blogs/newsletters
- The main issue behind so many inaccessible web apps is the lack of knowledge and awareness about the accessibility guidelines.
- You can invest some time learning about these standards and then sharing these with your teammates. You need to take the first step.
- I would recommend the following resources if you want to level your accessibility knowledge: 
    - [Sara Soudein blog](https://www.sarasoueidan.com/blog/)
    - [Scott O'Hara blog](https://www.scottohara.me/)
    - [Léonie Watson blog](https://tink.uk/)
    - [Marcy sutton blog](https://marcysutton.com/)
    - [Manuel Matuzovic blog](https://www.matuzo.at/blog/)
    - [HTML Hell](https://www.htmhell.dev/)
    - [Ire Aderinokun articles](https://bitsofco.de/tag/accessibility/)
    - [A11yProject](https://www.a11yproject.com/)
    - [WebAim](https://webaim.org/)
    - [Deque University](https://dequeuniversity.com/)
    - [Inclusive Components by Heydon Pickering](https://inclusive-components.design/)
    - [A11yweekly newsletter](https://a11yweekly.com/)


### It's not only about the UI
It's not just the UI elements or usage of assistive technologies that correspond to accessibility, it's also about your other web core vitals:
- Run [lighthouse](https://developers.google.com/web/tools/lighthouse/) check and see how well your app is performing overall.
- Use [code-splitting and lazy loading](https://dev.to/aman_singh/lazy-loading-react-components-no-rocket-science-ejn) where possible to avoid sending unnecessary JavaScript.
- Don't make too many requests on your first page load.
- Think about [progressive enhancement](https://developer.mozilla.org/en-US/docs/Glossary/Progressive_Enhancement) and server-side rendering.

--- 

## Conclusion
Starting a web developer career has become more of knowing about React, VueJS, and AngularJS. The advent of these frameworks has made creating a complex UI so easy that we've forgotten about accessibility guidelines. No doubt our developer experience has improved, but we have paid the cost of forgetting about vanilla JavaScript fundamentals, HTML native elements, and accessibility.

It's the time we resurrect these existing standards and lay down our app using the principles that would make it inclusive and accessible. Accessibility is not optional, and as a developer, it's our sole responsibility to make sure it won't go unattended.