Building an Accessible Popup using jQuery

In this tutorial, we will guide you through the process of building accessible popups using the power of jQuery. We will focus on implementing keyboard accessibility, managing focus, leveraging ARIA attributes, and following best practices to ensure that your popups are usable and inclusive.

So, let’s dive in and learn how to create accessible popups that enhance user experience and make your website more inclusive!”

Setting Up the HTML Structure

To start building our accessible popup, we need to set up the HTML structure. We’ll define the markup for the popup container and add trigger elements that will open the popup when interacted with.

<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Poppu tutorial</title>
    <link rel="stylesheet" href="style.css">
    <!-- jquery -->
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
</head>
<body>
    <div class="container">
        <!-- Trigger button for the modal -->
        <button id="modalTrigger" aria-haspopup="dialog" aria-expanded="false">Open Modal</button>
        
        <!-- Modal container -->
        <div id="modalContainer" role="dialog" aria-modal="true" aria-labelledby="modalTitle" aria-describedby="modalDescription">
          <!-- Modal content -->
          <div id="modalContent">
            <h2 id="modalTitle">This is My Modal Title</h2>
            <p id="modalDescription">
                This is my modal description. It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout.
            </p>
            <!-- Add your modal content here -->
            <button id="modalClose" aria-label="Close Modal">Close</button>
          </div>
        </div>
    </div>
    <script src="custom.js"></script>
</body>

Attributes used and their purpose:

  1. aria-haspopup="dialog": This attribute is applied to the trigger button (modalTrigger). It indicates that activating the button will display a dialog or a modal popup.
  2. aria-expanded="false": This attribute is also applied to the trigger button (modalTrigger). It indicates the current state of the modal, where “false” means that the modal is initially hidden or collapsed.
  3. role="dialog": This attribute is applied to the modal container (modalContainer). It specifies the role of the element as a dialog or a modal window.
  4. aria-modal="true": This attribute is also applied to the modal container (modalContainer). It indicates that the modal is a top-level window and should be treated as a modal dialog by assistive technologies.
  5. aria-labelledby="modalTitle": This attribute is applied to the modal container (modalContainer). It references the element with the ID “modalTitle” (<h2 id="modalTitle">) to provide an accessible name or label for the modal.
  6. aria-describedby="modalDescription": This attribute is also applied to the modal container (modalContainer). It references the element with the ID “modalDescription” (<p id="modalDescription">) to provide a description or additional information about the modal.
  7. aria-label="Close Modal": This attribute is applied to the close button (modalClose). It provides an accessible name or label for the button, specifying that it is used to close the modal.

These ARIA attributes help improve the accessibility of the modal by providing additional information and context for assistive technologies, such as screen readers, to understand the purpose and behavior of the modal. They ensure that users with disabilities can navigate and interact with the modal effectively.

It’s important to use ARIA attributes appropriately and according to their intended purpose to ensure the accessibility of your web content.

Popup Functionality using jQuery

$(document).ready(function () {
    var modalTrigger = $("#modalTrigger");
    var modal = $("#modalContainer");
    var firstFocusableElement;
    var lastFocusableElement;
  
    function showPopup() {
      modal.addClass("show"); // Add class to show the modal
      modal.attr("aria-hidden", "false"); // Set aria-hidden to false
  
      // Find the first and last focusable elements inside the modal
      var focusableElements = modal.find(
        'a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])'
      );
      firstFocusableElement = focusableElements.first();
      lastFocusableElement = focusableElements.last();
  
      modal.on("keydown", trapFocus);
  
      // Shift keyboard focus to modal content
      var modalContent = $("#modalContent");
      modalContent.attr("tabindex", "0");
      modalContent.focus();
    }
  
    function closeModal() {
      modal.removeClass("show"); // Remove class to hide the modal
      modal.attr("aria-hidden", "true"); // Set aria-hidden to true
      modal.off("keydown", trapFocus); // Remove event listener for focus trapping
      modalTrigger.focus(); // Set focus back to the trigger button
  
      // Show ARIA alert for screen readers that the modal is closed
      var modalClosedAlert = $("<div>")
        .text("Modal closed")
        .addClass("sr-only")
        .attr("role", "alert");
      modal.append(modalClosedAlert);
      setTimeout(function () {
        modalClosedAlert.remove();
      }, 1000);
    }
  
    function trapFocus(event) {
      if (event.keyCode === 9) {
        // Trap focus within the modal on "Tab" key press
        if (event.shiftKey) {
          if ($(document.activeElement).is(firstFocusableElement)) {
            event.preventDefault();
            lastFocusableElement.focus();
          }
        } else {
          if ($(document.activeElement).is(lastFocusableElement)) {
            event.preventDefault();
            firstFocusableElement.focus();
          }
        }
      }
  
      if (event.keyCode === 27) {
        // Close modal on "Escape" key press
        closeModal();
      }
    }
  
    modalTrigger.on("click", showPopup);
    $("#modalClose").on("click", closeModal);
  });
  

The code provided sets up an accessible popup using jQuery. Here’s a description of how the code works:

  1. The code is wrapped within a $(document).ready() function to ensure that the code executes after the document has finished loading.
  2. The variables modalTrigger and modal are assigned jQuery objects representing the trigger button and the modal container, respectively.
  3. The showPopup() function is defined to handle the opening of the modal. When the function is called, it adds the “show” class to the modal container and sets the aria-hidden attribute to “false” to indicate that the modal is visible.
  4. Inside the showPopup() function, the first and last focusable elements within the modal are identified using the focusableElements selector. The first element is stored in the firstFocusableElement variable, and the last element is stored in the lastFocusableElement variable.
  5. The keydown event listener is attached to the modal using the modal.on("keydown", trapFocus) syntax. This event listener calls the trapFocus() function, which manages the keyboard focus trapping within the modal.
  6. The trapFocus() function checks for key events. If the “Tab” key is pressed, it traps the focus within the modal by checking the current active element and shifting the focus to the first or last focusable element accordingly. If the “Escape” key is pressed, it calls the closeModal() function to close the modal.
  7. The closeModal() function is defined to handle the closing of the modal. It removes the “show” class from the modal container, sets the aria-hidden attribute to “true”, removes the keydown event listener, and sets the focus back to the modal trigger button. It also appends a visually hidden ARIA alert to announce the closure of the modal to screen readers.
  8. The modalTrigger is assigned a “click” event listener that triggers the showPopup() function when clicked. Similarly, the “click” event listener is attached to the element with the ID “modalClose” to call the closeModal() function when clicked.

Style the popup

Finally some basic styling of our popup.

/* Styles for the modal container */
#modalContainer {
    /* Set modal properties */
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background-color: rgba(0, 0, 0, 0.5); /* Semi-transparent background */
    display: none; /* Hide initially */
  }
  #modalContainer.show {
    display: block; /* Show when the #modalContainer.show class is added */
  }
  
  /* Styles for the modal content */
  #modalContent {
    /* Set modal properties */
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    background-color: #ffffff;
    padding: 20px;
  }
  
  /* Styles for the close button */
  #modalClose {
    /* Set close button properties */
    position: absolute;
    top: 10px;
    right: 10px;
  }
  .sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border-width: 0;
  }

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top