Web Accessibility for Beginners

Mainak MukherjeeMainak Mukherjee
19 min read

In this blog, we are going to discuss a very important aspect of web development and that is Web Accessibility. So if you are a developer and you want to take your knowledge to the next level, make sure to read it to the end.

Disclaimer

You will find all the code here. The live website showcasing the practical examples is available here. A lot of changes are made with respect to the code in this blog to make the website look good but don't worry since the main concepts are still present.

Make sure to keep these resources in case you have any doubts:

https://www.w3.org/WAI/standards-guidelines/wcag/ https://www.a11yproject.com/ https://developer.mozilla.org/en-US/docs/Learn/Accessibility/HTML#text_alternatives https://developer.mozilla.org/en-US/docs/Web/Accessibility/Understanding_WCAG/Perceivable https://reactjs.org/docs/accessibility.html

So with ithout further ado, let's get started.

What is Web Accessibility?

It simply means that your web application is accessible to anybody, whether with or without a disability. A web application can be a very important resource in various fields like education, government facilities, private resources, and many other aspects. So we as web developers should make our sites more accessible so that we can provide equal opportunity to people to whom life has been unfair.

Web accessibility is not only the responsibility of the developers but also of the entire team, consisting of designers, testers, and the rest.

💡
If you are unsure whether your website is accessible or not, close your eyes and behave like a blind guy. Using a screen reader, try to access your website to understand whether it is accessible or not.

Why should we care about accessibility?

In short, to give equal opportunity to all people. When we allow that, it does not only help them but also the business. Let's suppose you have made a railway ticket-booking app. Now if you have kept it accessible then not only some blind person can buy his/her ticket but also the business can make more money by not ignoring such people.

Discussing the first principle of Web Accessibility: Perceivable

What is Perceivability?

It means the ability to clearly understand something. In our context, it means that we will make our website in such a way that it can be easily understood how to work in our website.

Understanding Text Alternatives

We need to provide text alternatives to non-text elements like images, charts, diagrams, and so on. Let's understand how this can be practically useful.

Suppose a blind person visits your website. Now he/she will use a screen reader which, on navigating to different elements using the Tab key, will spell the info associated with it. Let's see how we can increase the info using code.

I will be using NextJS for this project but I am sure you will be able to understand it.

Setting Up eslint-plugin-jsx-a11y

This plugin is super helpful and will help you identify accessibility issues in your code by pointing the areas out in the JSX itself. Let's understand how to integrate it into NextJS:

First, you will need eslint which is basically automatically installed if you kept it checked while creating your next app.

Second, install eslint-plugin-jsx-a11y:

npm install eslint-plugin-jsx-a11y --save-dev

Third, make these changes in the eslintrc.json in your base project:

{
  "extends": ["next/core-web-vitals","plugin:jsx-a11y/recommended"],
  "plugins": ["jsx-a11y"]
}

Okay, now you will be able to detect such issues in your JSX. One such example here:

We need to give some alt text under <Image/> so that the screen reader is able to detect it. Keep at least empty string in case you have provided the information using other means.

Install a Screen Reader Chrome Extension

We should install a screen reader to understand how it feels using it to navigate through our website. I will use this one.

Let's see the code

Make sure to follow along and take help from the comments.

app\perceive\page.tsx

import Image from "next/image";
import React from "react";

const Images = () => {
  return (
    <div className="min-h-screen flex justify-center items-center flex-col p-5 gap-y-[5vh]">
      {/* We are using a header here since the screen reader will be able to decipher 
          it as a header and hence speak it. This will help the blind in knowing which tab
           they are on */}
      <header className="text-2xl">
        Let&apos;s see how we can provide more information with the images
      </header>
      <div className="w-[80vw] flex-wrap flex gap-x-[5vw] gap-y-[5vh] justify-center items-center">
        <div className="w-[400px]">
          {/* The image without proper alt text so the screen reader 
              will stay silent which is bad UX for blind people */}
          <Image
            height={400}
            width={400}
            src="your_image_link"
            alt=""
          />
        </div>

        <div className="w-[400px]">
          {/* we have proper alt text so the screen reader will read that on selecting this image */}
          <Image
            height={400}
            width={400}
            src="your_image_link"
            alt="Sunrise is the one of the most beautiful nature phenomenon."
          />
        </div>

        <div className="w-[400px]">
          {/* same here as above, its just that on hovering over the image, the title will also appear */}
          <Image
            height={400}
            width={400}
            src="your_image_link"
            alt="Sunrise is the one of the most beautiful nature phenomenon."
            title="Picture of Sunrise"
          />
        </div>
        <div className="flex flex-col w-[400px]">
          {/* here what we are doing is that we have some text inside <p> whose id="image-label". Now
                  since we might not want to repeat it so we did is tell the <Image/> that it is labeled
                  by the <p>'s text using aria-labelledby and the id of <p>. Accordingly, screen reader
                  will read that out */}
          <Image
            height={400}
            width={400}
            src="your_image_link"
            aria-labelledby="image-label"
            alt=""
            title="Picture of Sunrise"
          />
          <p id="image-label">
            Sunrise is the one of the most beautiful nature phenomenon.
          </p>
        </div>
        <div className="w-[400px]">
          {/* similar as above just using figure and figcaption */}
          <figure>
            <Image
              height={400}
              width={400}
              src="your_image_link"
              aria-describedby="image-caption"
              alt=""
              title="Picture of Sunrise"
            />
            <figcaption id="image-caption">
              Sunrise is the one of the most beautiful nature phenomenon.
            </figcaption>
          </figure>
        </div>
      </div>
    </div>
  );
};

export default Images;

Let's move to our next topic.

Understanding Time-Based Media

Examples are audio only like podcasts and video basically visual+audio.

As you might have noticed the usage of transcripts and availability of captions in online courses. These help people who have a hearing problem or have a problem understanding the speech.

You also get the option to change the speed of the video and volume. All of these are accessibility features. YouTube also allows captions for better understanding.

Responsive

Web content should be properly aligned and structured so that it can be properly viewed on any device. In simple words, it should be responsive.

Distinguishable Contents

The user should be able to properly understand the content. Let's say that the text color can be properly viewed with respect to the background color. Like light grey text on a white background cannot be understood, I mean obviously. Using black text over white or vice-versa makes sense.

Discussing the second principle of Web Accessibility: Usable

What is usability?

It means that a disabled person is able to use it.

How to implement it?

Keyboard accessible

The entire website should be keyboard accessible since a person can possibly be blind and hence can't see the mouse pointer or might not be able to hold the mouse. The disabled person should be able to navigate the entire website content using Tab Key.

We will be using tabIndex so the elements are navigable using Tab. After that, the user can navigate using the Tab key. Let's make the changes in the previous code.

import Image from "next/image";
import React from "react";

const Images = () => {
  return (
    <div className="min-h-screen flex justify-center items-center flex-col p-5 gap-y-[5vh]">
      {/* We are using a header here since the screen reader will be able to decipher 
          it as a header and hence speak it. This will help the blind in knowing which tab
           they are on */}
      <h1 className="text-2xl" tabIndex={0}>
        Let&apos;s see how we can provide more information with the images
      </h1>
      <div className="w-[80vw] flex-wrap flex gap-x-[5vw] gap-y-[5vh] justify-center items-center">
        <div className="w-[400px]">
          {/* The image without proper alt text so the screen reader 
              will stay silent which is bad UX for blind people */}
          <Image
            tabIndex={0}
            height={400}
            width={400}
            src="your_image_url"
            alt=""
          />
        </div>

        <div className="w-[400px]">
          {/* we have proper alt text so the screen reader will read that on selecting this image */}
          <Image
            tabIndex={0}
            height={400}
            width={400}
            src="your_image_url"
            alt="Sunrise is the one of the most beautiful nature phenomenon."
          />
        </div>

        <div className="w-[400px]">
          {/* same here as above, its just that on hovering over the image, the title will also appear */}
          <Image
            tabIndex={0}
            height={400}
            width={400}
            src="your_image_url"
            alt="Sunrise is the one of the most beautiful nature phenomenon."
            title="Picture of Sunrise"
          />
        </div>
        <div className="flex flex-col w-[400px]">
          {/* here what we are doing is that we have some text inside <p> whose id="image-label". Now
                  since we might not want to repeat it so we did is tell the <Image/> that it is labeled
                  by the <p>'s text using aria-labelledby and the id of <p>. Accordingly, screen reader
                  will read that out */}
          <Image
            tabIndex={0}
            height={400}
            width={400}
            src="your_image_url"
            aria-labelledby="image-label"
            alt=""
            title="Picture of Sunrise"
          />
          <p id="image-label">
            Sunrise is the one of the most beautiful nature phenomenon.
          </p>
        </div>
        <div className="w-[400px]">
          {/* similar as above just using figure and figcaption */}
          <figure>
            <Image
              tabIndex={0}
              height={400}
              width={400}
              src="your_image_url"
              aria-describedby="image-caption"
              alt=""
              title="Picture of Sunrise"
            />
            <figcaption id="image-caption">
              Sunrise is the one of the most beautiful nature phenomenon.
            </figcaption>
          </figure>
        </div>
      </div>
    </div>
  );
};

export default Images;
💡
Normally, tab indices are put on interactive elements like inputs but I have put it on the header and images since I thought for a blind person, this might be of use for better understanding the content.

Sufficient Time should be provided

The users should be provided with proper time to navigate the website and consume the web content. Old people generally take a longer time to consume the content and accordingly interact with the website. Blind people first use screen readers to first analyze the context and then interact with it. Some people just take time to understand the context. Keeping all these things in mind, we need to understand that the user should not be logged out without providing them with sufficient time.

Some banking websites and rail ticket booking websites log out the user after some time. What is needed is that they provide the information of how much time they are provided with or give the facility to the user to change the time. Some stock and news websites refresh quite frequently and in that case, it can be tough for the user. So, in that case, it is necessary to give the proper settings to the user to change the time period or simply switch to manual refresh.

Reduced or no flashing

Some disabled people have a problem with flashing and it might cause seizures. Normally, these warnings are given in games since they contain a lot of flashing animations and light effects.

We should avoid flashes or something which is very bright. We should also avoid too much animation-based content if it is not that important since some people have attention deficit disorders or can have difficulty in tracking moving objects.

Eased navigation

We should shape our content in such a way that it is easily navigable.

  • Some users use a screen reader and keyboard to navigate the website.

  • We should divide larger content into smaller content and add a heading to each.

  • The page title should also kept relevant to the content like Homepage for the landing page, Browse for the browsing tab, and so on.

  • We can also add a "skip to main content" button so that while using only the keyboard, they don't need to go through 10 items in the navbar and can simply skip to the main content.

Discussing the third principle of Web Accessibility: Understandable

We need to use proper language in our website so that it's accessible for all.

  • We need to avoid abbreviations like OMG (oh my god) or LOL (laugh out loud) since some people might not be habituated to that and will need to make a Google search.

  • No need to use bombastic or technical words. Some highly niche-specific words like sanctimony, algorithms and so on should be avoided.

  • Uncommon phrases should be avoided.

  • Multi-language functionality should be present so that people from all regions can visit the website.

Discussing the fourth principle of Web Accessibility: Robust

It simply means your website should be accessible in most of the modern browsers.

Next, we will focus on the application part of web accessibility.

Developing an accessible form

We will be using a lot of things. You will find the respective comments in the code itself.

There are certain things which we need to maintain in this form:

  • It should be completely accessible by keyboard so that even a blind person can submit the form.

  • All the interactive elements should be associated with an element to describe their context.

  • Any dynamic content appearing should be read by the screen reader so as to let the disabled person know about it.

  • Proper use of color should be maintained to give clear messages.

Here is the code (feel free to make any changes, or any doubts make sure to ask ChatGPT) :

Next, we will discuss how to make an accessible modal.

Developing an accessible modal

A modal is simply a dialog box that appears upon interacting with an element and floats above the rest of the page. It is used to display information or take information from the user without navigating to another page. We need to make it accessible while keeping in mind the below rules.

  • When the modal opens, the initial focus should go to the first focusable element of the modal.

  • The user should not be allowed to interact with the rest of the page while the modal is still open.

  • The user should be allowed to shift focus between the elements inside the modal, basically the focus should keep on revolving throughout the modal. For example, if we have a modal with a close button at the top right and cancel button at the bottom, on shifting focus using Tab when at the Can

  • The user should be able to easily navigate the modal using keyboard.

  • The user should be able to close the modal using the Esc key and the focus should return to the last element that made the modal open.

  • The aria attributes should be used to give relevant context to the modal and modal elements.

  • The modal should be outside the hierarchy of the main content area.

  • Make sure that when a button is focused

For this, we will be using PatternFly which provides built-in accessible components.

Let's install it.

npm install @patternfly/react-core --save

The documentation does not clearly mention how to apply the CSS in react/next so make sure to have this CSS file imported in your main component file.

First, install these things:

npm install @patternfly/patternfly sass

Then create a globals.scss and make sure to import it in the root component file. Paste this code in that:

@import "~@patternfly/patternfly/patternfly.css";
@import "~@patternfly/patternfly/sass-utilities/_all.scss";

Now you should be good. Make sure to follow along and try to do it yourself, take help from the comments. Also ask doubts to ChatgPT.

Here's the code:

parent folder\components\AccessibleModal.tsx

"use client"
import React, { useEffect, useRef } from "react";
import { createPortal } from "react-dom";
interface Props {
  isModalOpen: boolean;
  onCloseModal: () => void;
}
const AccessibleModal: React.FC<Props> = ({ isModalOpen, onCloseModal }) => {
  const closeButtonRef = useRef<null | any>(null);
  const opensModalButtonRef = useRef<null | any>(null);
  const lastButtonRef = useRef<null | any>(null);

  const onCloseAndRefocus = () => {
    //when the modal is open and the Esc key is pressed, we need to close the modal
    //and return the focus to the modal open button(basically from where the modal
    //was initiated)
    onCloseModal();
    opensModalButtonRef.current?.focus();
  };

  const onKeyDown = (e: KeyboardEvent) => {
    if (e.key === "Escape" && isModalOpen) {
      //when the user presses Escape key and modal is open then run this function
      onCloseAndRefocus();
    }

    const firstInteractiveElementInModal = closeButtonRef.current; //targetting the first
    //interactive element in the modal that is the close button
    const lastInteractiveElementInModal = lastButtonRef.current;
    //targetting the last interactive element in the modal and that is the no button
    if (e.key === "Tab") {
      if (e.shiftKey && e.target === firstInteractiveElementInModal) {
        //basically if Tab+Shift is pressed and current focus is on the first element then
        //move to the last element
        e.preventDefault();
        lastInteractiveElementInModal?.focus();
      } else if (e.target === lastInteractiveElementInModal) {
        //if only Tab is pressed and current focus is on the last element then move to the
        //first element
        e.preventDefault();
        firstInteractiveElementInModal?.focus();
      }
    }
  };

  useEffect(() => {
    const rootElement = document.getElementById("root");
    rootElement?.setAttribute("aria-hidden", isModalOpen.toString());
    //the root element does not need to spoken about by the screen reader when the modal is open
    //and hence it is ignored by the accessbility tree, don't get the wrong idea, its still
    //in the document, its just being ignored by the screen reader

    if (isModalOpen) {
      opensModalButtonRef.current = document.activeElement; // this is to
      //refer to the modal button which opens the modal, this useEffect callback
      //will run whenever the isModalOpen changes and if the isModalOpen is true
      //means the modal just got opened and hence the current element in focus is
      //the modal button
      closeButtonRef.current?.focus(); //in the JSX we have associated the ref with
      //the close button and hence using javascript, we can focus the element whenever
      //the modal opens, that is bringing the focus inside the modal
    }

    document.addEventListener("keydown", onKeyDown); //whenever a key will be pressed, this
    //onKeyDown function will be called

    return () => {
      document.removeEventListener("keydown", onKeyDown);
    }; //when the component unmounts,
    //remove the event listener
  }, [isModalOpen]);

  return (
    <>
      <style>
        {`
              button:focus{
                color:red !important;
                // this is to make sure that when a button is focused, that is clearly understood
              }
            `}
      </style>
      {isModalOpen &&
        // we are using createPortal from react-dom so as to create
        //create a different DOM element wrt to root div
        //check the html souce code on the page after rendering the modal
        //also the react docs for more info
        createPortal(
          <div className="pf-v5-c-backdrop">
            <div className="pf-v5-l-bullseye">
              <div
                className="pf-v5-c-modal-box pf-m-sm"
                role="dialog"
                aria-modal="true"
                aria-labelledby="modal-title-modal-basic-example-modal"
                aria-describedby="modal-description-modal-basic-example-modal"
              >
                <div className="pf-v5-c-modal-box__close">
                  <button
                    className="pf-v5-c-button pf-m-plain"
                    type="button"
                    aria-label="Close"
                    ref={closeButtonRef} //passing the ref for associating the close button to it
                    onClick={onCloseAndRefocus} //close modal on clicking the close button
                    //and also refocus to the modal button
                  >
                    <i className="fas fa-times" aria-hidden="true"></i>
                  </button>
                </div>
                <header className="pf-v5-c-modal-box__header">
                  <h1
                    className="pf-v5-c-modal-box__title"
                    id="modal-title-modal-basic-example-modal"
                  >
                    Accessible Modal
                  </h1>
                </header>
                <div
                  className="pf-v5-c-modal-box__body"
                  tabIndex={0}
                  id="modal-description-modal-basic-example-modal"
                >
                  <p>We are trying to create an accessible modal</p>
                  <p>Have you tried doing it on your own?</p>
                </div>
                <footer className="pf-v5-c-modal-box__footer">
                  <button className="pf-v5-c-button pf-m-primary" type="button">
                    Yes
                  </button>
                  <button
                    className="pf-v5-c-button pf-m-link"
                    type="button"
                    ref={lastButtonRef} //need to mark the last button to cycle the focus
                    //within the modal when its open
                  >
                    No
                  </button>
                </footer>
              </div>
            </div>
          </div>,
          document.body
        )}
    </>
  );
};

export default AccessibleModal;

app\modal\page.tsx

"use client";

import React, { useState } from "react";
import "@patternfly/react-core/dist/styles/base.css";
import { Button } from "@patternfly/react-core";
import AccessibleModal from "@/components/AccessibleModal";

const ModalPage = () => {
  const [isModalOpen, setIsModalOpen] = useState(false);

  const onCloseModal = (): void => {
    setIsModalOpen(false);
  };

  return (
    <div className="main h-screen flex justify-center items-center">
      <Button
        variant="primary"
        ouiaId="Primary"
        onClick={() => {
          setIsModalOpen(true);
        }} //open the modal on clicking open modal
      >
        Show Modal
      </Button>
      {isModalOpen && (
        <AccessibleModal
          isModalOpen={isModalOpen}
          onCloseModal={onCloseModal}
        />
      )}
    </div>
  );
};

export default ModalPage;

Now your assignment is to do the same thing using a library called react-focus-lock . Next we will learn about the Skip to Main Content button.

How to make a Skip To Main Content Button?

Now this is quite important. Suppose a disabled person visits your website and can't use the mouse, probably blind or has some nervous problem. He/she can only use the keyboard. Now there are a lot of unnecessary tabs present at the top and the user would have to move through all of them before coming to the main content. And that's a Bad UX.

To solve that, we can keep an element at the top(intially outside the viewport) and when the user will try navigating with Tab, as soon as the focus will be on that element(focus will come since its part of the DOM), it will appear in the viewport plus the screen reader will also mention it. On clicking it, the focus will directly shift to the main content and hence skipping all the unnecessary tabs.

As you can see at the top, lot of tabs are there. To avoid that, when the user navigates into the viewport using the tab key, the skip button will get focused and appear on the screen.

The best part is that for a normal user, it is not a distraction since until and unless the user only uses keyboard for navigating the content, it won't appear.

Heres the code:

parent folder\components\SkipToMain.tsx

import Link from "next/link";
import React from "react";

const SkipToMain = () => {
  return (
    <Link
      href="#topic" //Will Take the focus to the element with id="topic" 
      className="skip absolute z-[100] w-fit rounded-full mx-auto left-0 right-0 top-[-100px] focus:translate-y-[200px] transition"
      aria-labelledby="skip-btn"
    >
      <button
        id="skip-btn"
        className="px-8 py-2 rounded-full bg-gradient-to-b from-blue-500 to-blue-600 text-white focus:ring-2 focus:ring-blue-400 hover:shadow-xl transition duration-200"
      >
        Skip to Main Content
      </button>
    </Link>
  );
};

export default SkipToMain;

You can call and render it in any page but for this example, lets assume that it is going be used for the home page.

app\page.tsx

"use client";

import { motion } from "framer-motion";
import React from "react";

import Navbar from "@/components/ui/navbar-menu";
import SkipToMain from "@/components/SkipToMain";

export default function Home() {
  //...some code here

  return (
    <>
      <SkipToMain />
      <Navbar />
      <style>
        {/* proper styling to help identify the focused element */}
        {`
            *:focus{
              outline-color:red;
            }

            .nav{
              a:focus{
                outline:2px solid red !important;
              }
            }

            div:focus{
              outline:none;
              border:2px solid red !important;
            }
          `}
      </style>
      <div className="h-screen flex justify-center items-center">
        {/* some code */}
        <p
          id="topic"
          className="m-auto"
          tabIndex={0}
          aria-label="Web Accessibility"
        >
          Web Accessibility
        </p>
      </div>
    </>
  );
}

And here's the code for the Navbar component.

parent folder\components\ui\navbar-menu.tsx

import { Fragment, useState } from "react";
import { Disclosure, Menu, Transition } from "@headlessui/react";
import { Bars3Icon, BellIcon, XMarkIcon } from "@heroicons/react/24/outline";
import Link from "next/link";

const navigation = [
  { name: "These", href: "/" },
  { name: "Are", href: "/" },
  { name: "Useless", href: "/" },
  { name: "Tabs", href: "/" },
  { name: "Make", href: "/" },
  { name: "Sure", href: "/" },
  { name: "To", href: "/" },
  { name: "Skip", href: "/" },
];

interface NavItem {
  name: string;
  href: string;
}

function classNames(...classes: any[]) {
  return classes.filter(Boolean).join(" ");
}

export default function Navbar() {
  const [current, setCurrent] = useState<number>(-1);

  return (
    <Disclosure as="nav" className="nav bg-gray-800 fixed z-50 w-full">
      {({ open }: any) => (
        <>
          <div className="mx-auto w-full px-2 sm:px-6 lg:px-8">
            <div className="relative flex h-16 items-center justify-between">
              <div className="absolute inset-y-0 left-0 flex items-center sm:hidden">
                {/* Mobile menu button*/}
                <Disclosure.Button className="relative inline-flex items-center justify-center rounded-md p-2 text-gray-400 hover:bg-gray-700 hover:text-white focus:outline-none focus:ring-2 focus:ring-inset focus:ring-white">
                  <span className="absolute -inset-0.5" />
                  <span className="sr-only">Open main menu</span>
                  {open ? (
                    <XMarkIcon className="block h-6 w-6" aria-hidden="true" />
                  ) : (
                    <Bars3Icon className="block h-6 w-6" aria-hidden="true" />
                  )}
                </Disclosure.Button>
              </div>
              <div className="flex flex-1 items-center justify-center sm:items-stretch">
                <div className="hidden sm:ml-6 sm:block">
                  <div className="flex space-x-4">
                    {navigation.map((item, i) => (
                      <Link
                        onClick={() => {
                          setCurrent(i);
                        }}
                        key={item.name}
                        href={item.href}
                        className={classNames(
                          i === current
                            ? "bg-gray-600 text-white"
                            : "text-gray-300 hover:bg-gray-700 hover:text-white",
                          "rounded-md px-3 py-2 text-sm font-medium"
                        )}
                        aria-current={i === current ? "page" : undefined}
                      >
                        {item.name}
                      </Link>
                    ))}
                  </div>
                </div>
              </div>
            </div>
          </div>

          <Disclosure.Panel className="sm:hidden">
            <div className="space-y-1 px-2 pb-3 pt-2">
              {navigation.map((item, i) => (
                <Disclosure.Button
                  key={item.name}
                  as="a"
                  href={item.href}
                  className={classNames(
                    i === current
                      ? "bg-gray-900 text-white"
                      : "text-gray-300 hover:bg-gray-700 hover:text-white",
                    "block rounded-md px-3 py-2 text-base font-medium"
                  )}
                  aria-current={i === current ? "page" : undefined}
                >
                  {item.name}
                </Disclosure.Button>
              ))}
            </div>
          </Disclosure.Panel>
        </>
      )}
    </Disclosure>
  );
}

Make sure to install the dependencies used here:

npm install @headlessui/react @heroicons/react

You can also use PatternFly 's component to, make the Skip Buttonno issues with that.

Wrapping Up

I hope whatever was discussed in this blog made sense to you. And if it did, make sure to like and subscribe to my newsletter. I am also planning to add the testing part in this blog itself. And btw, in case you are more of a visual learner, make sure to see the Web Accessibility series from Anuj Singla's YT channel.

With this, thank you for reading and we will meet in the next blog.

0
Subscribe to my newsletter

Read articles from Mainak Mukherjee directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Mainak Mukherjee
Mainak Mukherjee