The screen reader seems to be malfunctioning as soon as I include this particular code

//Finding the height of the header
        let headerHeight = document.querySelector('header');
        let height = headerHeight.offsetHeight;

        //Adjusting the #navbarNav's top margin to accommodate the header 
        let nn = document.getElementById("navbarNav");
        nn.style.top = height.toString() + "px";

let hamburger = document.getElementById("hamMenuButton");
      let shown = false;
      hamburger.addEventListener("click", function () {
          if (shown) { //if #navbarNav is showing 
              hideNN();
          } else { //if not 
              showNN();
          }
      });
      let i = document.getElementById("ham-img");
      let memberUN = document.getElementById("member-un");
      function showNN() {
          //********************This causes an issue********************
          memberUN.style.display = "none";
          shown = true;
      }

      function hideNN() {
          //********************This causes an issue********************
          memberUN.style.display = "flex";
          shown = false;
      }
header {
display: flex;
}

#hamMenuButton:focus {
border: 1px solid black;
}

.navbar-toggler {
outline: none!important;
box-shadow: none!important;
border: none!important;
}

.navbar-toggler:active,
.navbar-toggler:focus {
outline: none!important;
box-shadow: none!important;
border: 1px solid black!important;
            }

#navbarNav {
    position: fixed;
    width: 100%;
    height: 100%;
    left: 0;
    right: 0;
    bottom: 0;
    background-color: blue;
    z-index: 2;
    cursor: pointer;
}
<!doctype html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>SOF</title>

        <link href="https://cdn.jsdelivr.net/npm/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="bedcd1d1cacdcaccdfcefe8b908f908d">[email protected]</a>/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
        <script src="https://cdn.jsdelivr.net/npm/@popperjs/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="21424e534461130f180f13">[email protected]</a>/dist/umd/popper.min.js" ></script>
        <script src="https://cdn.jsdelivr.net/npm/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="50323f3f24232422312010657e617e63">[email protected]</a>/dist/js/bootstrap.bundle.min.js" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" crossorigin="anonymous"></script>
        
        <script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
        <script src="https://cdn.jsdelivr.net/npm/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="18687768687d6a36726b582936292e3628">[email protected]</a>/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
        <script src="https://cdn.jsdelivr.net/npm/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="5e3c31312a2d2a2c3f2e1e6a706a706f">[email protected]</a>/dist/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
        
    </head>
    <body>
        <header>
            <section class="dropdown my-1" id="member-un">
              <button class="dropdown-toggle" type="button" id="dropdownMenuButton" data-bs-toggle="dropdown" aria-haspopup="true" tabindex="0" aria-expanded="false">
                <p>Hello, John Smith</p>
              </button>
              <!-- The problematic code -->
              <section class="dropdown-menu dropdown-menu-right p-0" aria-labelledby="dropdownMenuButton">
                <a class="dropdown-item py-3" href="" id="drop-logout">Logout</a>
              </section>
            </section>
            
            <nav class="navbar" id="hamburger-menu">
            <button class="navbar-toggler" 
            id="hamMenuButton" 
            type="button" 
            data-bs-toggle="collapse" 
            data-bs-target="#navbarNav" 
            aria-expanded="false" 
            aria-controls="navbarNav">
                Menu
            </button>
            </nav>
        </header>
        
        <section class="collapse py-5" id="navbarNav">
            <p>Hello, John Smith</p>
        </section>
        
        <main>
        <!--Remaining code-->
        </main>
    </body>
</html>

I am currently using NVDA screen reader to assess website accessibility while utilizing Bootstrap. I am trying to implement an overlay menu activated by a hamburger button that toggles between visibility and hidden states without obscuring the header section of the site.

When the overlay menu appears, I intend to conceal the element 'member-un'. Although the functionality works as expected, introducing the lines ‘memberUN.style.display = "none";’ and ‘memberUN.style.display = "flex";’ disrupts the screen reader's ability to announce "Expanded" and "Collapsed". Any suggestions on resolving this issue?

Answer №1

Using aria-expanded with a dialog is not a common practice, and Bootstrap does not handle it.

The reason for this is that when a dialog opens, an element inside it receives focus immediately. Therefore, the status of the button would not be announced to screen readers.

Focus remains trapped inside the dialog, preventing the button from being announced further.

Even when the dialog closes and the button regains focus, it is already evident that focus has left the dialog.

Refer to the Dialog Pattern in the ARIA Authoring Practices Guide (APG)

Avoid using a dialog for navigation purposes

Hiding an element outside the dialog while it is open does not benefit screen reader users, as they are confined within the dialog.

This limitation applies to all users. Modal dialogs are meant to draw attention to their content, usually accompanied by a backdrop. Concealing something on the main page during dialog display serves little purpose.

The current code involving a navigation bar and burger icon suggests an unconventional use of modal dialogs for navigation, possibly leading to unexpected behavior.

To hide a navigation menu effectively, consider utilizing a Menu Button or the Disclosure Pattern

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Transforming data with D3.js into a string representation

Recently, I stumbled upon a function called "stringify" that seems like a fantastic tool for converting flat data into a Json format. If this function lives up to its potential, it could potentially save me countless hours of writing recursive code in ASP ...

Transform the JSON object into a TypeScript array

Currently working on a project that requires converting a JSON object into a TypeScript array. The structure of the JSON is as follows: { "uiMessages" : { "ui.downtime.search.title" : "Search Message", "ui.user.editroles.sodviolation.entries" : ...

What is the best way to implement conditional hook usage in React?

Having two hooks at my disposal, useLocalStorage and useQuery, I find myself wondering about conditionally utilizing one of them based on an input prop. I'm considering writing the following: const [value, setValue] = localStorage ? useLocalStorage() ...

Transferring a value via AJAX that has been modified by a previous AJAX call

In my form, users input values which are used to calculate a result. The calculation is performed through AJAX calls triggered by onchange events on the user-edited fields. This process works as expected. However, there is a hidden field that also gets up ...

Exploring the concept of generator functions in ES6

I'm grappling with understanding JS generators and why the asynchronous operations in the example below are returning undefined. I thought that using yield was supposed to wait for asynchronous calls to finish. function getUsers(){ var users; $.aj ...

Enable users to upload and run JavaScript code on the server

Currently, I am diving into the world of javascript/nodeJS with the goal of creating an ERP solution. My aim is to give ERP end-users the ability to upload their own customized scripts which can then interact with existing ERP scripts. It goes without sayi ...

The sequence of execution in React hooks with Typescript

I'm having difficulty implementing a language switching feature. On the home page of my app located at /, it should retrieve a previously set preference from localStorage called 'preferredLanguage'. If no preference is found, it should defau ...

What could be causing the Vue.js image component to malfunction?

I am having an issue. I want to create a Vue.js Component. This component displays an image, similar to the <img> tag. If you are familiar with the <img> tag, this question should be easy for you to understand. Here is the code I have: props ...

Express.js Res redirection problem occurring with Backbone.js due to failure in redirecting hashtag URLs

Issue Summary: Having trouble with Express.js redirect functionality. The problem occurs when trying to redirect after entering /#impulse, but works fine with /impulse/. Server processes the request for /#impulse before applying redirect checks, which re ...

Dealing with a throw er; uncaught 'err' event while configuring a server with nodemon

I am currently in the process of setting up my local server using node.js and nodemon. Initially, everything runs smoothly on localhost, but as soon as I refresh the page or navigate to another page, the server crashes with an 'unhandled error event&a ...

Ways to initiate JavaScript event upon clearing input form field

I'm working on creating a dynamic search feature. As the user types in the search box, JavaScript is triggered to hide the blog posts (#home) and display search results instead (the specific script for this is not shown below). However, when the user ...

Validator alert for AMP scripts

I have implemented the amp version for my content management system. Since each article has a different body, some include amp-instagram while others include amp-facebook, and so on. In order to cover all bases, I have added both amp-facebook and amp-inst ...

Error in executing Javascript function

Below is a Javascript function I created for expanding and collapsing content: function showAns(inp){ var hide="#hideAns"+inp; var show="#showAns"+inp; var ansdiv ="#ans"+inp; $(hide).click(function(){ $(ansdi ...

The html-docx-js package generates incomprehensible text

Has anyone successfully utilized html-docx-js recently? I attempted the following code snippet: var newHTML = "<!DOCTYPE html><html><head lang='en'><meta charset='UTF-8'><title>Report</title& ...

What steps do I need to take in order to successfully make a checkbox?

I am attempting to use Angularjs to set a checkbox to true. When saved, it should store an integer value (1 or 0) in my field. Below is the code snippet for the view: <input type="checkbox" ng-model="lis.SMSPromotion" id="SMSPromotion" ng-init="checke ...

Animating slides with CSS Keyframes and React, incorporating toggle slide fade out and slide fade (back) in

I am seeking a solution for toggling a box (div) with slide-out animation and then sliding back in animation (in reverse) upon button press. My requirement is to have no animations during the initial page render. While I can successfully slide the box to ...

The AJAX in Code Igniter is throwing an error due to an undefined index 'id

I'm encountering an issue when calling a function in AJAX, as it shows the error message "Undefined index: id". Strangely, if I have only one button in the view, the function works fine. However, when there are two buttons present, the error occurs. W ...

React: Show input value on button click

I have been working on a React form that displays the entered input value in a controlled input element only after the user hits the submit button, rather than updating it constantly as the user types. Here is my current solution using conditional renderin ...

ReactJS form example: utilizing two separate submit buttons to perform distinct actions on the same form

I need to implement two submit buttons in my form. Both buttons should utilize the same inputs and form validation, but trigger different actions. export default function FormWithTwoSubmits() { function handleSubmitTask1(){ } function handleSub ...

Adjusting the height property to zero in the absence of an element

I'm currently working on creating a timeline for changeLogs and populating it with data from an AngularJS controller. The issue I'm facing is that the height of the timeline "Line" is set to 6px. This means that even when there is no data in the ...