How to Make Squarespace 7.1 Folder Menus Web-Accessible
There are a lot of great and necessary reasons to make your dropdown menu web-accessible, including ensuring your website is ADA-compliant to avoid possible legal ramifications and making sure that all differently-abled users have easy access to your website’s navigation when using keyboard navigation. Unfortunately, the Squarespace 7.1 platform does not innately come with web-accessible dropdown functionality via the mouse and the keyboard.
Accessible dropdown menus should include an open-on-click functionality, proper ARIA and role attributes for screen readers, and conventional keyboard triggers that make them easily accessible to people with disabilities.
If you are interested in learning the details of web-accessible dropdown menus, keep reading. If you would rather skip straight to the free code snippet, click here.
What makes a dropdown menu web-accessible?
1. Menu appears on click
Click menus in general provide a much better user experience than hover menus for all users. Specifically for people with motor disabilities that may struggle with accurately controlling mouse movements, click menus give users more control over opening and closing dropdown menus without accidentally closing them if the mouse leaves the menu. This is something commonly referred to as “The Diagonal Problem” in UX design, which occurs when a user attempts to select a menu item by moving the mouse from the top-level link to a link in the dropdown folder. By implementing click menus (menus that appear on click), you can eliminate these accessibility issues.
The code snippet provided in this article gives you the option between the menus opening on mouse hover or on click so that you can decide for yourself which is the best option.
2. Create accessible keyboard actions
When keyboard users navigate through a menu, there are a few conventional keyboard functions that they expect to have. Here are the four keyboard actions that a click menu should have:
Initially Pressing the Tab key navigates through the top-level menu items
This gives users the freedom to skip over dropdown menus they are not interested in.
Pressing the enter key or space key opens the dropdown menu of the currently focused item or redirects to the currently focused link
This gives users the option to open dropdown menus they are interested in instead of them having to navigate through every menu item using the “Tab” key, which is typically how accessible hover menus operate. If the currently focused item is a link, the user can redirect to that page.
Pressing the tab key when a menu is open will navigate through the dropdown menu options
This allows users to search through the currently open menu options. If they press the “Tab” key when the last menu item in the dropdown is focused, navigation will continue to the next top-level menu item.
Pressing the escape key will close the menu and return focus to the top-level menu
This gives users the option to exit a dropdown menu and return to the top-level menu options if they decide they no longer want to search through the rest of the menu options.
Holding down the Shift key while pressing the Tab key
This traverses the menu items backwards
3. Include appropriate ARIA attributes for screen readers
Accessible Rich Internet Applications (ARIA) is a set of HTML attributes that make web applications and websites accessible for people with disabilities. When aria attributes are present, screen readers typically used by people with sight impairments are able to convey to the user what an element represents, whether it can be interacted with, and what action the element will trigger when interacted with.
In the context of dropdown or flyout menus that can be opened on click, there are three aria attributes that need to be present in order for the menu to be accessible:
aria-controls
This corresponds to the menu that the corresponding parent item opens.
aria-expanded
This signifies to the user if the dropdown menu is currently expanded, or “open”. When the menu is closed, this should be set to false. When the menu is open, this should be set to “true.”
aria-haspopup="true"
This signifies to the user that the currently focused interactive element (the parent menu item) opens a menu when selected.
Code snippets and instructions
Things to know before using this solution:
The solution offered in this article works on all 7.1 templates.
You must have a Squarespace Business plan or higher in order to add custom code to your site
If your site uses any mega menu plugin, this solution WILL NOT be compatible. If you are interested in a Squarespace 7.1 mega menu that meets web-accessibility requirements including opening on click or optimized hover and accessible via all keyboard controls, check out the mega menu plugin available in my store instead of using the code found in this article.
When dealing with custom code, it is not guaranteed that it will be compatible with other custom code snippets or plugins you have on your site, so if it ends up not working, simply remove the code from your site.
7.1 Code Snippets
Menu Options
The below code snippet contains a menu option that you can customize to make the menus appear on either click or hover. Add this code snippet to your site’s header code injection via Settings > Advanced > Code Injection > Header.
Appear on click or hover: You can choose to make the menus appear on mouse click or mouse hover by changing the value of “appearOn” to either “hover”, or “click”.
<!-- Start: Launch Hub Studio - Accessible Dropdown Menu Options --> <script> var accessibleMenuOptions = { appearOn: "click" //"hover" or "click" }; </script> <!-- End: Launch Hub Studio - Accessible Dropdown Menu Options -->
CSS and JS Code
Add this code snippet to your site’s header code injection right below the menu options you just added.
<!-- Accessible Dropdown Menu Styles --> <style> .header-nav-item--folder.appearOnHover .header-nav-folder-content { pointer-events: all; visibility: hidden } .header-nav-folder-title:after{ content:"\25be"; font-size:1rem; display:inline-block; margin-left:3px } .header-nav-folder-title.open:after{ transform:rotate(180deg) } .header-nav-item.header-nav-item--folder.appearOnClick:hover .header-nav-folder-content{ opacity:0; pointer-events:none!important } .header-nav-item--folder.appearOnClick .header-nav-folder-content{ opacity:0; pointer-events:none; transition:all .2s } .header-nav-folder-content.showDropdown{ opacity:1!important; pointer-events:auto!important; visibility: visible!important } .header-nav-folder-content.showDropdown .header-nav-folder-item{ pointer-events:auto } .header-nav-folder-title:before{ content:""; position:absolute; bottom:-2px; left:50%; height:3px; width:100%; opacity:0; background:currentColor; transform:translateX(-50%); transition:all .4s; z-index:999999 } .header-nav-folder-title.open:before,.header-nav-folder-title:hover:before{ opacity:1; transition:all .4s } body:not(.sqs-edit-mode-active) .header-nav-item--folder.appearOnHover .header-nav-folder-content { transition: opacity 0s linear .35s,visibility 0s linear .35s,z-index 0s linear .35s,max-height 0s linear .35s,max-width 0s linear .35s; -moz-transition: opacity 0s linear .35s,visibility 0s linear .35s,z-index 0s linear .35s,max-height 0s linear .35s,max-width 0s linear .35s; -webkit-transition: opacity 0s linear .35s,visibility 0s linear .35s,z-index 0s linear .35s,max-height 0s linear .35s,max-width 0s linear .35s; visibility: hidden; } body:not(.sqs-edit-mode-active) .header-nav-item--folder.appearOnHover:hover .header-nav-folder-content { transition: opacity .1s linear .35s,visibility .1s linear .35s,z-index .1s linear .35s,max-height 0s linear .35s,max-width 0s linear .35s !important; -webkit-transition: opacity .1s linear .35s,visibility .1s linear .35s,z-index .1s linear .35s,max-height 0s linear .35s,max-width 0s linear .35s !important; -moz-transition: opacity .1s linear .35s,visibility .1s linear .35s,z-index .1s linear .35s,max-height 0s linear .35s,max-width 0s linear .35s !important; z-index: 10; visibility: visible; max-width: 150% !important; } @media(min-width:799px) { .header-nav-item--folder:not(.preloaded) *, .no-transition, .no-transition * { -webkit-transition: none !important; -moz-transition: none !important; -ms-transition: none !important; -o-transition: none !important } } </style> <!-- Accessible Dropdown Menu Styles --> <!-- Accessible Dropdown Menu Script --> <script> document.addEventListener("DOMContentLoaded",function(){try{var e=document.querySelectorAll(".header-nav-folder-content"),t=document.querySelectorAll(".header-nav-item--folder"),r=document.querySelectorAll(".header-nav-folder-title");!function(){var e=r.length;for(let t=0;t<e;t++){var n=r[t];n.getAttribute("href"),n.setAttribute("tabindex","0"),n.setAttribute("aria-expanded","false"),n.setAttribute("aria-haspopup","true"),n.setAttribute("role","button");var l="menu_"+t;n.nextElementSibling.setAttribute("id",l),n.setAttribute("data-controls",l),null!=accessibleMenuOptions&&void 0!=accessibleMenuOptions?"click"!=accessibleMenuOptions.appearOn?n.closest(".header-nav-item").classList.add("appearOnHover"):"click"==accessibleMenuOptions.appearOn&&n.closest(".header-nav-item").classList.add("appearOnClick"):n.closest(".header-nav-item").classList.add("appearOnHover")}}();for(let n=0;n<t.length;n++){var l=t[n];l.addEventListener("click",function(e){var t=e.currentTarget;("click"==accessibleMenuOptions.appearOn||0==e.detail||-1==e.pointerId||1!=e.mozInputSource&&void 0!=e.mozInputSource)&&null==e.target.closest(".showDropdown")&&null==e.target.closest(".header-nav-folder-item")&&(Array.from(t.querySelector(".header-nav-folder-content").classList).includes("showDropdown")?closeAllMenus():(closeAllMenus(),t.querySelector(".header-nav-folder-content").classList.add("showDropdown"),t.querySelector(".header-nav-folder-title").setAttribute("aria-expanded","true"),t.querySelector(".header-nav-folder-title").classList.add("open"))),0==e.detail||-1==e.pointerId||1!=e.mozInputSource&&void 0!=e.mozInputSource?t.querySelector(".header-nav-folder-content").classList.add("no-transition"):t.querySelector(".header-nav-folder-content").classList.remove("no-transition")}),l.addEventListener("mouseenter",function(e){e.target.querySelector(".header-nav-folder-content").classList.remove("no-transition")})}var o=document.querySelector("body");function a(e){for(var t=e,r=[];t;)r.unshift(t),t=t.parentNode;return"none"==getComputedStyle(e).display||r.filter(function(e){return void 0!=e.style&&"none"==getComputedStyle(e).display}).length>0}"click"==accessibleMenuOptions.appearOn&&o.addEventListener("click",function(e){if(!1==Array.from(o.classList).includes("sqs-edit-mode-active"))for(let r=0;r<t.length;r++)t[r],null==document.querySelector(".showDropdown")||void 0!=e.target.closest(".header-nav-item--folder")||Array.from(e.target.classList).includes("header-nav-folder-content")||void 0!=e.target.closest(".header-nav-folder-content")||closeAllMenus()}),document.querySelector("#header"),closeAllMenus=function(){for(let t=0;t<e.length;t++){var n=e[t];n.classList.remove("showDropdown")}for(let l=0;l<r.length;l++){var n=r[l];n.classList.remove("open"),n.setAttribute("aria-expanded","false")}};var s=document.querySelectorAll(".header-display-desktop .header-nav-list a");for(let d=0;d<s.length;d++)s[d].addEventListener("focus",function(e){e.target.closest(".header-nav-folder-content")&&!Array.from(e.target.closest(".header-nav-folder-content").classList).includes("showDropdown")&&e.target.closest(".header-nav-folder-content").previousElementSibling.focus()});let i={};onKeyDownEvent=function(){document.addEventListener("keydown",function(e){i[event.key]=!0;var t=function e(t=document){return[...t.querySelectorAll('a[href], area[href], button, input:not([disabled]), textarea, select, details, iframe, [tabindex]:not([tabindex="-1"])')].filter(e=>!e.hasAttribute("disabled")&&!e.getAttribute("aria-hidden"))}(),r=!1,n=document.activeElement,l=Array.from(n.classList),o=n.closest(".header-nav-item--folder");if(null!=o)var s=o.querySelector(".header-nav-folder-title"),d=Array.from(s.classList);else var s=null;switch(e.key){case" ":l.includes("header-nav-folder-title")&&(n.click(),r=!0);break;case"Tab":if(i.Shift||e.shiftKey){((function e(t){if(null!=t.closest(".header-nav-folder-content"))return t==Array.from(t.closest(".header-nav-folder-content").querySelectorAll("a")).shift()})(n)||l.includes("header-nav-folder-title"))&&closeAllMenus();var c=Array.from(t).indexOf(document.activeElement);for(let u=c-1;u>=0;u--)if(!a(t[u])&&null==t[u].closest(".header-menu-nav")){null!=t[u].closest(".header-nav-folder-content")&&null==document.querySelector(".header-nav-folder-title.open")&&(t[u].closest(".header-nav-item").querySelector(".header-nav-folder-title").focus(),r=!0);break}}else if(null!=n&&l.includes("header-nav-folder-title")&&!l.includes("open")){if(null!=n.parentNode.nextElementSibling)n.parentNode.nextElementSibling.querySelector("a").focus();else{var c=Array.from(t).indexOf(document.activeElement);for(let f=c+1;f<t.length;f++)if(!a(t[f])&&null==t[f].closest(".header-menu-nav")&&null==t[f].closest(".header-nav-list")){"IFRAME"==t[f].nodeName?setTimeout(function(){t[f].focus()},100):t[f].focus(),closeAllMenus();break}}r=!0}else null!=n&&!l.includes("header-nav-folder-title")&&function e(t){if(null!=t.closest(".header-nav-folder-content"))return t==Array.from(t.closest(".header-nav-folder-content").querySelectorAll("a")).pop()}(n)&&d.includes("open")&&closeAllMenus();break;case"Esc":case"Escape":!1==Array.from(document.querySelector("body").classList).includes("sqs-edit-mode-active")&&null!=document.querySelector(".header-nav-folder-title.open")&&(document.querySelector(".header-nav-folder-title.open").focus(),closeAllMenus(),r=!0)}r&&!1==Array.from(document.querySelector("body").classList).includes("sqs-edit-mode-active")&&e.preventDefault(),e.stopImmediatePropagation()})},onkeyUpMenu=function(){document.addEventListener("keyup",e=>{delete i[e.key]})},onKeyDownEvent(),onkeyUpMenu();var c=window.scrollY;window.addEventListener("scroll",function(){document.querySelector("header#header").getBoundingClientRect().top<0&&closeAllMenus(),Math.abs(window.scrollY-c)>150&&(c=window.scrollY)}),setTimeout(function(){t.forEach(function(e,t){e.classList.add("preloaded")})},400)}catch(u){console.log(u)}}); </script> <!-- Accessible Dropdown Menu Script -->
If you enjoyed this tutorial, subscribe to my email list to make sure you don’t miss out on other Squarespace tips and tricks!