{"id":174,"date":"2024-08-13T12:57:29","date_gmt":"2024-08-13T12:57:29","guid":{"rendered":"https:\/\/www.accessibilita.digital\/?p=174"},"modified":"2024-08-23T12:15:18","modified_gmt":"2024-08-23T12:15:18","slug":"menu-navigazione-dropdown-accessibile","status":"publish","type":"post","link":"https:\/\/www.accessibilita.digital\/menu-navigazione-dropdown-accessibile\/","title":{"rendered":"Come realizzare un men\u00f9 di navigazione con dropdown accessibile"},"content":{"rendered":"<p>Questa tipologia di guida \u00e8 pensata e dedicata agli <b>sviluppatori web<\/b> che, come me, si trovano in certi casi a non sapere bene come progettare un certo componente, come i men\u00f9 di navigazione o gli accordion, giusto per fare due esempi molto diffusi.<\/p>\n\n<h2>Men\u00f9 di navigazione e dropdown<\/h2>\n<p>Il men\u00f9 di navigazione \u00e8 probabilmente <b>l\u2019elemento pi\u00f9 usato all\u2019<\/b><b>interno di un sito web<\/b>. Dopotutto, permette all\u2019utente di navigare all\u2019interno del sito e <b>raggiungere le pagine principali<\/b>, o almeno quelle che si vuole mettere in evidenza.<\/p>\n<p>Questi men\u00f9 sono solitamente posizionati <b>in alto<\/b> (nell\u2019header), <b>a lato<\/b> (aside) o <b>in fondo<\/b> (footer). Potrebbero essere presenti anche delle navigazioni contestuali, ad esempio inserite in una <b>barra fissa<\/b> che segue lo scorrimento della pagina.<\/p>\n<h2>Cosa sapere per l&#8217;accessibilit\u00e0<\/h2>\n<p>In termini di accessibilit\u00e0, le informazioni principali che dobbiamo conoscere sono le seguenti:<\/p>\n<ul>\n<li>Il <b>tag contenitore<\/b> dovrebbe essere un <b>&lt;nav&gt;<\/b><\/li>\n<li><b>Se sono presenti pi\u00f9 landmark di navigazione<\/b>, ognuno <b>deve avere una propria label<\/b>, tramite uso di <b>aria-label<\/b> o <b>aria-labelledby<\/b>. Per landmark si intende quel tipo di elementi che hanno un ruolo specifico, quindi potrebbe essere un &lt;nav&gt; ma anche un &lt;div role=\u201dnavigation\u201d&gt;<\/li>\n<li>In generale, la label pu\u00f2 contenere <b>solo il testo descrittivo<\/b> omettendo la parola \u201cnavigazione\u201d, in quanto gli screen reader leggeranno gi\u00e0 questa parola. Quindi, un &lt;nav aria-label=\u201dPrincipale\u201d&gt; dovrebbe venire letto dagli screen reader gi\u00e0 come \u201cNavigazione principale\u201d<\/li>\n<li>I <b>link<\/b> inseriti nel men\u00f9 devono avere un <b>testo descrittivo<\/b> e dovrebbero evitare voci come \u201cScopri di pi\u00f9\u201d, \u201cLeggi tutto\u201d e simili<\/li>\n<\/ul>\n<p>La <b>struttura HTML suggerita<\/b> per creare un men\u00f9 di navigazione prevede i seguenti elementi:<\/p>\n<pre class=\"language-css\"><code>nav &gt; ul &gt; li &gt; a<\/code><\/pre>\n<p>Possiamo vedere gli esempi di <a href=\"https:\/\/getbootstrap.com\/docs\/5.3\/components\/navbar\/\" rel=\"nofollow noopener\">Navbar<\/a> creati da Bootstrap per avere un\u2019idea base.<\/p>\n<h2>Pulsanti di apertura (dropdown)<\/h2>\n<p>Un altro elemento importante che spesso fa parte degli elementi di navigazione \u00e8 il <b>pulsante di apertura<\/b>, che io generalmente chiamo \u201chandler\u201d, e pu\u00f2 essere usato per attivare o disattivare il men\u00f9. Pensiamo al caso di un men\u00f9 che si apre <b>a tendina<\/b> (come i <a href=\"https:\/\/getbootstrap.com\/docs\/5.3\/components\/dropdowns\/\" rel=\"nofollow noopener\">dropdown<\/a> o soluzioni simili) oppure al caso di una navigazione che viene <b>nascosta da mobile<\/b>, e che viene aperta solo dopo aver attivato il pulsante.<\/p>\n<p>Questa strada prevede di avere un elemento, che generalmente \u00e8 un &lt;button&gt; ma potrebbe essere anche un &lt;input type=\u201dcheckbox\u201d&gt; senza attributo \u201cname\u201d, il quale permette di <b>catturare il click<\/b> o l\u2019azione dell\u2019utente e scegliere se <b>mostrare o nascondere<\/b> il men\u00f9.<\/p>\n<p>Ecco un <b>esempio semplificato<\/b>, preso da un caso reale di un sito web che ho sviluppato e che usa <b>WordPress e Bootstrap Italia<\/b>:<\/p>\n<pre class=\"language-markup\"><code>&lt;nav aria-label=\"Principale\" class=\"navbar navbar-expand-lg main-nav has-megamenu\" id=\"menu-principale\"&gt;\r\n    &lt;ul class=\"navbar-nav dl-menu nav-list nav-list-primary\" data-element=\"menu\"&gt;\r\n        &lt;li class=\"nav-item dropdown\"&gt;\r\n            &lt;button class=\"dropdown-toggle\" data-bs-toggle=\"dropdown\" aria-expanded=\"false\" id=\"mainNavDropdownDesktopHandler1\" data-focus-mouse=\"false\" aria-label=\"Apri\/chiudi men\u00f9 di: Chi siamo\" data-bs-target=\"mainNavDropdownDesktop1\"&gt;\r\n            &lt;span class=\"text\"&gt;Chi siamo&lt;\/span&gt;\r\n            &lt;svg role=\"img\" class=\"icon icon-xs ms-1\"&gt;&lt;use href=\"sprites.svg#it-expand\"&gt;&lt;\/use&gt;&lt;\/svg&gt;\r\n            &lt;\/button&gt;\r\n            &lt;div id=\"mainNavDropdownDesktop1\" class=\"dropdown-menu link-list-wrapper\"&gt;\r\n                &lt;ul aria-labelledby=\"mainNavDropdownDesktop1\" class=\"link-list\"&gt;\r\n                    &lt;li&gt;&lt;a class=\"list-item\" href=\"#\"&gt;Testo del link 1&lt;\/a&gt;&lt;\/li&gt;\r\n                    &lt;li&gt;&lt;a class=\"list-item\" href=\"#\"&gt;Testo del link 2&lt;\/a&gt;&lt;\/li&gt;\r\n                &lt;\/ul&gt;\r\n            &lt;\/div&gt;\r\n        &lt;\/li&gt;\r\n    &lt;\/ul&gt;\r\n&lt;\/nav&gt;<\/code><\/pre>\n<p>In questo esempio possiamo trovare gli elementi principali che ci interessano:<\/p>\n<ul>\n<li>Il <b>&lt;nav&gt;<\/b> con attributo <b>aria-label<\/b> e con le relative classi di Bootstrap<\/li>\n<li><b>&lt;ul&gt; e &lt;li&gt;<\/b> con le relative classi Bootstrap, in particolare la classe \u201cdropdown\u201d per l\u2019elemento &lt;li&gt;<\/li>\n<li>Il <b>&lt;button&gt;<\/b> che viene usato come attivatore del men\u00f9 a tendina (dropdown) tramite <b>Javascript<\/b>, molto importante da tenere presente \u00e8 l\u2019uso dell\u2019attributo <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/Accessibility\/ARIA\/Attributes\/aria-expanded\" rel=\"nofollow noopener\">aria-expanded<\/a>, che viene usato per indicare alle tecnologie assistive se questo elemento di controllo \u00e8 stato azionato o meno e se quindi gli elementi collegati vengono mostrati oppure no<\/li>\n<li>Il <b>sottomen\u00f9<\/b> contenuto in un &lt;div&gt; che contiene i link del nostro men\u00f9 di navigazione, che in questo caso \u00e8 quindi di secondo livello<\/li>\n<\/ul>\n<p>Se volessimo replicare una struttura simile <b>senza l\u2019uso di Bootstrap<\/b>, quindi per una soluzione completamente <b>custom<\/b>, dovremmo replicare almeno il comportamento che modifica il valore dell\u2019attributo <b>aria-expanded<\/b> e poi mostrare o nascondere il men\u00f9. Molto banalmente potremmo fare una cosa del genere in Javascript e in CSS:<\/p>\n<pre class=\"language-markup\"><code>&lt;nav aria-label=\"Contestuale\"&gt;\r\n    &lt;button onclick=\"toggleMenu(this)\" data-menu-id=\"menu-1\" aria-expanded=\"false\"&gt;Apri\/chiudi men\u00f9 1&lt;\/button&gt;\r\n    &lt;ul id=\"menu-1\"&gt;\r\n        &lt;li&gt;&lt;a href=\"#\"&gt;Link 1&lt;\/a&gt;&lt;\/li&gt;\r\n        &lt;li&gt;&lt;a href=\"#\"&gt;Link 2&lt;\/a&gt;&lt;\/li&gt;\r\n    &lt;\/ul&gt;\r\n    &lt;button onclick=\"toggleMenu(this)\" data-menu-id=\"menu-2\" aria-expanded=\"false\"&gt;Apri\/chiudi men\u00f9 2&lt;\/button&gt;\r\n    &lt;ul id=\"menu-2\"&gt;\r\n        &lt;li&gt;&lt;a href=\"#\"&gt;Link 3&lt;\/a&gt;&lt;\/li&gt;\r\n        &lt;li&gt;&lt;a href=\"#\"&gt;Link 4&lt;\/a&gt;&lt;\/li&gt;\r\n    &lt;\/ul&gt;\r\n&lt;\/nav&gt;\r\n\r\n&lt;style&gt;\r\nnav ul { display:none; }\r\ninput[type=\"checkbox\"]:checked ~ ul { display:block; }\r\n.d-none { display:none; }\r\n.d-block { display:block; }\r\n&lt;\/style&gt;\r\n\r\n&lt;script&gt;\r\nfunction toggleMenu(element) {\r\n    let selector = \"#\" + element.dataset.menuId;\r\n    let menu = document.querySelectorAll(selector)[0];\r\n\r\n    if (element.getAttribute('aria-expanded') == 'true') {\r\n        \/\/ Menu is already open, let's close it\r\n        menu.classList.add('d-none');\r\n        menu.classList.remove('d-block');\r\n        element.setAttribute('aria-expanded', false);\r\n    } else {\r\n        \/\/ Menu is closed, let's open it\r\n        menu.classList.add('d-block');\r\n        menu.classList.remove('d-none');\r\n        element.setAttribute('aria-expanded', true);\r\n    }\r\n}\r\n&lt;\/script&gt;<\/code><\/pre>\n<p>Ora, chiaramente l\u2019esempio \u00e8 molto basilare ma \u00e8 utile per capire il concetto: <b>mostriamo o nascondiamo<\/b> il men\u00f9 quando il pulsante viene azionato e modifichiamo l\u2019attributo <b>aria-expanded<\/b>.<\/p>\n<h2>L&#8217;uso di aria-expanded<\/h2>\n<p>Per selezionare il men\u00f9 corretto tramite Javascript, facciamo uso di un <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Learn\/HTML\/Howto\/Use_data_attributes\" rel=\"nofollow noopener\">data-attribute<\/a>, che \u00e8 un attributo HTML che <b>non ha valore semantico<\/b> ma \u00e8 molto utile per passare dei valori a Javascript.<\/p>\n<p>La modifica dell\u2019aria-expanded richiede per forza di cose l\u2019uso di <b>Javascript<\/b>, ma in ogni caso potremmo optare anche per una soluzione con un <b>checkbox<\/b> invece del button, e mostrare il men\u00f9 quando questo checkbox \u00e8 selezionato:<\/p>\n<pre class=\"language-markup\"><code>&lt;nav aria-label=\"Contestuale\"&gt;\r\n    &lt;div class=\"menu-wrapper\"&gt;\r\n        &lt;input id=\"menu-1-handler\" class=\"visually-hidden\" type=\"checkbox\" onchange=\"toggleAriaExpanded(this)\" aria-expanded=\"false\"&gt;\r\n        &lt;label for=\"menu-1-handler\"&gt;&lt;span class=\"visually-hidden\"&gt;Apri\/chiudi men\u00f9 1&lt;\/span&gt;&lt;\/label&gt;\r\n        &lt;ul id=\"menu-1\"&gt;\r\n            &lt;li&gt;&lt;a href=\"#\"&gt;Link 1&lt;\/a&gt;&lt;\/li&gt;\r\n            &lt;li&gt;&lt;a href=\"#\"&gt;Link 2&lt;\/a&gt;&lt;\/li&gt;\r\n        &lt;\/ul&gt;\r\n    &lt;\/div&gt;\r\n    &lt;div class=\"menu-wrapper\"&gt;\r\n        &lt;input id=\"menu-2-handler\" class=\"visually-hidden\" type=\"checkbox\" onchange=\"toggleAriaExpanded(this)\" aria-expanded=\"false\"&gt;\r\n        &lt;label for=\"menu-2-handler\"&gt;&lt;span class=\"visually-hidden\"&gt;Apri\/chiudi men\u00f9 2&lt;\/span&gt;&lt;\/label&gt;\r\n        &lt;ul id=\"menu-2\"&gt;\r\n            &lt;li&gt;&lt;a href=\"#\"&gt;Link 3&lt;\/a&gt;&lt;\/li&gt;\r\n            &lt;li&gt;&lt;a href=\"#\"&gt;Link 4&lt;\/a&gt;&lt;\/li&gt;\r\n        &lt;\/ul&gt;\r\n    &lt;\/div&gt;\r\n&lt;\/nav&gt;\r\n\r\n&lt;style&gt;\r\nnav ul { display:none; }\r\ninput[type=\"checkbox\"]:checked ~ ul { display:block; }\r\n&lt;\/style&gt;\r\n\r\n&lt;script&gt;\r\nfunction toggleAriaExpanded(element) {\r\n    if (element.getAttribute('aria-expanded') == 'true') {\r\n        element.setAttribute('aria-expanded', false);\r\n    } else {\r\n        element.setAttribute('aria-expanded', true);\r\n    }\r\n\r\n    \/\/ Or, with jQuery (we need to include its files first tho):\r\n    let ariaExpanded = jQuery(element).attr('aria-expanded');\r\n\r\n    if (ariaExpanded == 'true') {\r\n        jQuery(element).attr('aria-expanded', false);\r\n    } else {\r\n        jQuery(element).attr('aria-expanded', true);\r\n    }\r\n}\r\n&lt;\/script&gt;<\/code><\/pre>\n<p>In questo secondo esempio, usiamo Javascript solo per <b>impostare aria-expanded in modo dinamico<\/b>, e CSS per nascondere i menu &lt;ul&gt; di default, mostrandoli solo quando il checkbox viene selezionato. L\u2019evento <b>onchange<\/b> ci serve proprio per capire quando viene modificato lo stato del checkbox.<\/p>\n<p>Ho anche inserito una variante alternativa di codice Javascript fatta con <b>jQuery<\/b>, framework che viene spesso usato quando si lavora con <b>WordPress<\/b>, cos\u00ec da fornire un caso pi\u00f9 completo.<\/p>\n<h2>Link utili<\/h2>\n<ul>\n<li>MDN: <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/Accessibility\/ARIA\/Roles\/navigation_role\" rel=\"nofollow noopener\">Aria Navigation Role<\/a><\/li>\n<li>Bootstrap: <a href=\"https:\/\/getbootstrap.com\/docs\/5.3\/components\/navbar\/\" rel=\"nofollow noopener\">Navbar<\/a><\/li>\n<li>Bootstrap: <a href=\"https:\/\/getbootstrap.com\/docs\/5.3\/components\/dropdowns\/\" rel=\"nofollow noopener\">Dropdowns<\/a><\/li>\n<li>MDN: <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Learn\/HTML\/Howto\/Use_data_attributes\" rel=\"nofollow noopener\">Data attributes<\/a><\/li>\n<\/ul>\n<h2><span id=\"leggi-anche\">Leggi anche<\/span><\/h2>\n<ul>\n<li><a href=\"https:\/\/www.accessibilita.digital\/come-sviluppare-un-sito-web-accessibile\/\">Come sviluppare un sito web accessibile<\/a><\/li>\n<li><a href=\"https:\/\/www.accessibilita.digital\/come-realizzare-una-navigazione-a-briciole-di-pane-breadcrumbs-accessibile\/\">Come realizzare una navigazione a briciole di pane (breadcrumbs) accessibile<\/a><\/li>\n<li><a href=\"https:\/\/www.accessibilita.digital\/come-realizzare-un-componente-leggi-di-piu-read-more-accessibile\/\">Come realizzare un componente Leggi di pi\u00f9 (read more) accessibile<\/a><\/li>\n<li><a href=\"https:\/\/www.accessibilita.digital\/come-creare-popup-e-modali-accessibili\/\">Come creare popup e modali accessibili<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Questa tipologia di guida \u00e8 pensata e dedicata agli sviluppatori web che, come me, si trovano in certi casi a non sapere bene come progettare un certo componente, come i men\u00f9 di navigazione o gli accordion, giusto per fare due esempi molto diffusi. Men\u00f9 di navigazione e dropdown Il men\u00f9 di navigazione \u00e8 probabilmente l\u2019elemento [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":258,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[],"class_list":["post-174","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.accessibilita.digital\/wp-json\/wp\/v2\/posts\/174"}],"collection":[{"href":"https:\/\/www.accessibilita.digital\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.accessibilita.digital\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.accessibilita.digital\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.accessibilita.digital\/wp-json\/wp\/v2\/comments?post=174"}],"version-history":[{"count":5,"href":"https:\/\/www.accessibilita.digital\/wp-json\/wp\/v2\/posts\/174\/revisions"}],"predecessor-version":[{"id":259,"href":"https:\/\/www.accessibilita.digital\/wp-json\/wp\/v2\/posts\/174\/revisions\/259"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.accessibilita.digital\/wp-json\/wp\/v2\/media\/258"}],"wp:attachment":[{"href":"https:\/\/www.accessibilita.digital\/wp-json\/wp\/v2\/media?parent=174"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.accessibilita.digital\/wp-json\/wp\/v2\/categories?post=174"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.accessibilita.digital\/wp-json\/wp\/v2\/tags?post=174"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}