Summary
I have remediated almost 100+ WordPress websites and making the WordPress menu accessible is always a challenging task.
I and also not very happy with my website’s existing design so I thought let’s create a WordPress theme that provides full customization and maximum accessibility.
The first thing that comes to mind is the mega-menu of the theme should be accessible and can be customized as per the owner’s requirements.
So Hi I am shadab saifi bringing my research code to share with you guys. Here is my step-by-step guide to make accessible WordPress mega-menu.
Give Credit
This code is free to use and modify by just adding the below HTML to the footer of your website for Credits.
<p>Mega-Menu Credit: <a href="https://halfaccessible.com/">https://halfaccessible.com/<a></p>
Step 1: Create custom_functions.php file for WordPress Mega menu
Create a custom_functions.php file in your theme or child theme and paste the below code:
file: custom_functions.php
<?php
function createMenuHierarchy($args = array())
{
$menu_name = 'header';
$locations = get_nav_menu_locations();
$menu = wp_get_nav_menu_object($locations[$menu_name]);
$menu_items = wp_get_nav_menu_items($menu->term_id);
$defaults = array(
'top-menu-id-prefix' => '',
'top-menu-classes' => '',
'top-menu-item-id-prefix' => '',
'top-menu-item-classes' => '',
'top-menu-item-anchor-classes' => '',
'dropdown-button-id-prefix' => '',
'dropdown-button-classes' => '',
'dropdown-ul-classes' => '',
'dropdown-li-classes' => '',
'dropdown-a-classes' => '',
);
$finalArgs = wp_parse_args($args, $defaults);
$modifiedMenuItems = array();
if (isset($menu_items)) {
foreach ((array) $menu_items as $menu_item) {
if (!isset($modifiedMenuItems[$menu_item->menu_item_parent])) {
$modifiedMenuItems[$menu_item->menu_item_parent] = array();
}
array_push($modifiedMenuItems[$menu_item->menu_item_parent], $menu_item);
}
}
renderAllMenuItems($finalArgs, $modifiedMenuItems, 0);
}
function renderAllMenuItems($finalArgs, $modifiedMenuItems, $hierarchyKey)
{
if ($hierarchyKey == 0) {
echo '<ul id="' . $finalArgs['top-menu-id-prefix'] . $hierarchyKey . '" class="' . $finalArgs['top-menu-classes'] . '" >';
} else {
echo '<ul class="' . $finalArgs['dropdown-ul-classes'] . '" id="drpdwn-container' . $hierarchyKey . '">';
}
foreach ($modifiedMenuItems[$hierarchyKey] as $key => $menu) {
$haschildrenClasses = isset($modifiedMenuItems[$menu->ID]) ? 'has-children' : '';
if ($hierarchyKey == 0) {
echo '<li id="' . $finalArgs['top-menu-item-id-prefix'] . $hierarchyKey . '" class="' . $finalArgs['top-menu-item-classes'] . ' ' . $haschildrenClasses . ' " >';
} else {
echo '<li class="' . $finalArgs['dropdown-li-classes'] . ' ' . $haschildrenClasses . '" >';
}
echo '<a class="' . $finalArgs['top-menu-item-anchor-classes'] . '" href="' . $menu->url . '">' . $menu->title . '</a>';
if (isset($modifiedMenuItems[$menu->ID])) {
echo '<button data-toggle-handles="drpdwn-container' . $menu->ID . '" id="' . $finalArgs['dropdown-button-id-prefix'] . $hierarchyKey . '" class="' . $finalArgs['dropdown-button-classes'] . '" >+</button>';
renderAllMenuItems($finalArgs, $modifiedMenuItems, $menu->ID);
}
echo '</li>';
}
echo '</ul>';
}
Step 2: include custom_functions.php file into your functions.php file
include(get_template_directory() . '<path>/custom_functions.php');
Step 3: Create mega-menu.js & mega-menu.css file and include them in functions.php
file: mega-menu.js
(function () {
document.querySelectorAll('button[data-toggle-handles]').forEach(function (singleHandler) {
singleHandler.setAttribute("aria-expanded", false);
singleHandler.addEventListener("click", function () {
singleHandler.setAttribute("aria-expanded", singleHandler.getAttribute("aria-expanded") == "false");
singleHandler.parentElement.classList.toggle("show");
});
});
})();
file: mega-menu.css
:root {
--backgroundColor: #212529;
--forgroundColor: #ffffff;
}
.has-children {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
align-content: center;
justify-content: flex-start;
align-items: center;
position: relative;
}
ul.top-main-menu .has-children > ul ul {
top: 100%;
}
.has-children > ul {
position: absolute;
top: calc(100% + 15px);
left: 15px;
display: none;
padding: 0;
flex-direction: column;
}
.has-children ul li {
padding: 15px;
}
.has-children ul li [data-toggle-handles] {
padding: 0 0 0 15px;
}
.has-children.show > ul {
display: flex;
min-width: max-content;
}
[data-toggle-handles] {
padding: 0;
background-color: var(--backgroundColor);
border: 0;
color: var(--forgroundColor);
}
ul.top-main-menu {
display: flex;
flex-direction: row;
flex-wrap: wrap;
align-content: flex-start;
justify-content: flex-start;
align-items: center;
background-color: var(--backgroundColor);
margin: 0 0;
list-style: none;
}
ul.top-main-menu ul {
list-style: none;
}
ul.top-main-menu > li {
padding: 0 15px 0 5px;
}
ul.top-main-menu > li > a {
padding: 0 10px 0 5px;
}
@media (max-width: 992px) {
ul.top-main-menu {
flex-direction: column;
}
ul.top-main-menu > li,
.has-children ul li {
width: 100%;
display: block;
}
.has-children.show > ul {
position: static;
}
}
ul.top-main-menu li > a {
text-decoration: none;
}
ul.top-main-menu li > a:focus,
ul.top-main-menu li > button:focus {
outline: 2px dotted var(--forgroundColor);
}
Include both files in functions.php
function theme_enqueue_scripts()
{
wp_enqueue_style('mega-menu-style', get_template_directory_uri() . '/assets/css/mega-menu.css', array(), '1.0', 'all');
wp_enqueue_script('mega-menu-script', get_template_directory_uri() . '/assets/js/mega-menu.js', array(), '1.0', true);
}
add_action('wp_enqueue_scripts', 'theme_enqueue_scripts');
Step 4: Paste below code to display mega-menu in header file
<?php
$args = array(
'top-menu-id-prefix' => 'main-menu-top',
'top-menu-classes' => 'top-main-menu',
'top-menu-item-id-prefix' => 'menu-item-top',
'top-menu-item-classes' => 'top-main-menu-item',
'top-menu-item-anchor-classes' => 'top-menu-item-anchor',
'dropdown-button-id-prefix' => 'custom-menu-handle',
'dropdown-button-classes' => 'custom-menu-toggle',
'dropdown-ul-classes' => 'custom-menu-toggle-container',
'dropdown-li-classes' => 'dropdown-li',
'dropdown-a-classes' => 'dropdown-li-a',
);
createMenuHierarchy($args); ?>
Screenshots


Final conclusion
There are lots of things to add but starting with this code will give you a space to work. The above code will auto-generate the menu no matter what hierarchy you choose.