Topic: MDB Sidenav is failing accessibility audit
Expected behavior
All MDB components pass accessibility tests, for example using Lighthouse
Actual behavior
We've implemented the MDB sidenav and when we run an accessibility audit using Chrome's Lighthouse snapshot test, it fails. You can see the report below.
It looks like we cannot fix this ourselves. We need you in the MDB Team to include an improvement in a future release. Soon please. It's not good that our accessibility score is negatively affected by this MDB component.
If the problem originates in the way we've implemented this, please explain what we can do to make the sidenav accessible ourselves.
Google Chrome rates this problem as "SERIOUS". According to the linked info in the Lighthouse: https://dequeuniversity.com/rules/axe/4.4/aria-hidden-focus?utm_source=lighthouse&utm_medium=devtools
Thanks in advance for caring about accessibility when you are planning your next release!
Resources (screenshots, code snippets etc.)
[aria-hidden="true"] elements contain focusable descendentsFocusable descendents within an [aria-hidden="true"]
element prevent those interactive elements from being available to users of assistive technologies like screen readers. Learn more.Failing Elementsmdb-sidenav-layout > multisite-sidenav > mdb-sidenav > div.cdk-visually-hiddenmdb-sidenav-layout > multisite-sidenav > mdb-sidenav > div.cdk-visually-hidden
Layout
<mdb-sidenav-layout>
<multisite-sidenav #sidenav [user]="user" (sideNavToggled)="sidenavToggled($event)"
></multisite-sidenav>
<mdb-sidenav-content #sidenavContent>
<div class="custom-backdrop"></div>
<header>
<multisite-main-navigation
[user]="user"
[logo]="'default'"
[navLinks]="mainNavigationLinks"
(doSideNavToggle)="toggleSidenav()"
(logout)="logout()"
[loading]="loading"
[sidenavStatus]="sidenavStatus"
>
</multisite-main-navigation>
</header>
<multisite-breadcrumb></multisite-breadcrumb>
<main>
<section class="main-section">
<router-outlet></router-outlet>
</section>
</main>
<multisite-footer></multisite-footer>
</mdb-sidenav-content>
</mdb-sidenav-layout>
CONTENT
<mdb-sidenav #sidenav="mdbSidenav"
[backdrop]="false"
[backdropClass]="'custom-backdrop'"
[width]="360"
[slimWidth]="136"
[right]="true"
(sidenavHidden)="toggled('hidden', $event)"
(sidenavExpanded)="toggled('expanded', $event)"
(sidenavCollapsed)="toggled('collapsed', $event)"
>
<ul class="sidenav-menu" [ngClass]=" sidenav.slimCollapsed ? 'sidenav-slim' : 'sidenav-wide'">
<!-- SIDENAV TOP PART -->
<li class="sidenav-top-content">
<div class="sidenav-header">
<div class="content-left">
<a class="sidenav-close" (click)="toggle()" tabindex="0" *ngIf="!sidenav.slim">
<i class="fas fa-times"></i>
</a>
</div>
<div mdbDropdown class="dropdown dropstart">
<a class="nav-link dropdown-toggle" id="navbarSettingsDropdown" role="button" mdbDropdownToggle
aria-expanded="false">
<div class="content-right">
<div class="profile-info">
<p class="name h5">{{user?.fname +' ' +user?.lname}}</p>
<p class="profession h6">{{user?.profile?.job_title}}</p>
</div>
<img class="user-profile-img"
[src]="user?.picture ? user.picture : 'https://res.cloudinary.com/cebt/image/upload/v1616972586/users/avatars/default-avatar.gif' "
alt="Profile image">
<span class="click-indicator animation-pulse-infinite"></span>
</div>
</a>
<multisite-user-account-dropdown [user]="user" mdbDropdownMenu class="dropdown-menu"></multisite-user-account-dropdown>
</div>
</div>
</li>
<!--
SIDENAV BOTTOM PART
(One scrollable element - ssplit into two parts)
-->
<li class="sidenav-main-content">
<!-- TOP PART OF MAIN CONTENT -->
<div>
<div class="card-group">
<!-- Card -->
<div class="card-sidenav">
<div class="card-body">
<div class="content-left">
<div class="card-status-icon bg-success">
A
</div>
<div class="card-text text-wrap">
<p class="card-title">Course A</p>
<p class="card-value">100%</p>
</div>
</div>
<div class="content-right">
<button class="btn" aria-label="Useful name for button A">
<i class="fa-solid fa-angle-right"></i>
</button>
</div>
</div>
</div>
<!-- Card -->
<div class="card-sidenav">
<div class="card-body">
<div class="content-left">
<div class="card-status-icon bg-warning">
B
</div>
<div class="card-text text-wrap">
<p class="card-title">Course A</p>
<p class="card-value">100%</p>
</div>
</div>
<div class="content-right">
<button class="btn" aria-label="Useful name for button A">
<i class="fa-solid fa-angle-right"></i>
</button>
</div>
</div>
</div>
<!-- Card -->
<div class="card-sidenav">
<div class="card-body">
<div class="content-left">
<div class="card-status-icon bg-danger">
C
</div>
<div class="card-text text-wrap">
<p class="card-title">Course A</p>
<p class="card-value">100%</p>
</div>
</div>
<div class="content-right">
<button class="btn" aria-label="Useful name for button A">
<i class="fa-solid fa-angle-right"></i>
</button>
</div>
</div>
</div>
<a href="#">Show all cards</a>
</div>
<div class="accreditation-card bg-success">
<img src="https://iili.io/HH2EezN.png" alt="badge">
<div class="card-text text-wrap">
<p class="title text-white">Accredited until 2025</p>
<p class="sub-title text-white">New Tool</p>
</div>
</div>
</div>
<!-- BOTTOM PART OF MAIN CONTENT -->
<div>
<hr>
<div class="progress-card">
<p class="title" id="progresslabel">
Total Progress
</p>
<p class="progress-value">
68%
</p>
<div class="progress">
<div class="progress-bar" role="progressbar" style="width: 68%" aria-valuenow="68" aria-valuemin="0"
aria-valuemax="100" aria-labelledby="progresslabel"></div>
</div>
</div>
<div class="trainer-card">
<carousel [interval]="false">
<p class="trainer-title">Trainers</p>
<slide>
<div class="trainer-img">
<img src="https://iili.io/yzAHJf.png" alt="">
<div class="status-indicator"></div>
</div>
<div class="card-text">
<p class="title">Terry Tester</p>
<p class="subtitle">
Head of ...
</p>
</div>
</slide>
<slide>
<div class="trainer-img">
<img src="https://iili.io/yzAHJf.png" alt="">
<div class="status-indicator"></div>
</div>
<div class="card-text">
<p class="title">Earl E. Adopta</p>
<p class="subtitle">
UX/UI Designer
</p>
</div>
</slide>
<slide>
<div class="trainer-img">
<img src="https://iili.io/yzAHJf.png" alt="">
<div class="status-indicator"></div>
</div>
<div class="card-text">
<p class="title">John Doe</p>
<p class="subtitle">
NaN
</p>
</div>
</slide>
</carousel>
<!-- <div class="card-body bg-white">
<div class="trainer-img">
<img src="https://iili.io/yzAHJf.png" alt="">
<div class="status-indicator"></div>
</div>
<div class="card-text">
text
</div>
</div> -->
</div>
</div>
</li>
</ul>
</mdb-sidenav>
Arkadiusz Idzikowski staff answered a year ago
In v5.1.0 we added some changes that should improve the accessibility of this component.
We plan to continue working on improving this aspect, but the remaining fixes will probably require more serious changes to the HTML structure of the sidenav and we will only be able to add them in the next major update.
Please let us know if you encounter any further problems.
webshapers pro premium priority commented 8 months ago
Hello, mdb-Team! We ran into a similar issue (mdb latest version as of today). mdb is injecting a tabindex="1", which makes little sense to us. Could you please describe, WHICH changes you have added to improve the accessibility?
Rafał Seifert commented 7 months ago
HTML structure was changed: we removed li element that was not contained within list element and added attribute role listitem to item element instead. We also changed the basic example code and added attributes like role, aria-expanded, aria-label and aria-controls.
FREE CONSULTATION
Hire our experts to build a dedicated project. We'll analyze your business requirements, for free.
Answered
- User: Pro
- Premium support: Yes
- Technology: MDB Angular
- MDB Version: MDB5 4.0.0
- Device: MacBook Pro
- Browser: Chrome
- OS: MacOs
- Provided sample code: No
- Provided link: Yes
Arkadiusz Idzikowski staff commented 2 years ago
Thank you for letting us know about this problem, we will take a closer look at that and let you know what we found.
Could you please edit your post and provide an example code that you use to render the component? We would like to test that using a similar configuration.