Le interfacce web spesso nascondono i contenuti per migliorare l'esperienza utente, risparmiare spazio sullo schermo o aumentare le prestazioni della pagina. I metodi tradizionali come display: none o visibility: hidden nascondono i contenuti visivamente, ma li rendono anche completamente inaccessibili agli screen reader e alle funzionalità del browser come "Trova nella pagina".
Per nascondere visivamente i contenuti, ma consentire comunque agli utenti di cercarli e di creare deep link tramite frammenti di URL e link "Scorri fino al frammento di testo", puoi utilizzare l'elemento HTML <details> o l'attributo hidden="until-found". In genere, l'elemento <details> è consigliato perché è più semplice da implementare e gestire, ma esistono alcuni casi più complessi in cui <details> non è sufficiente ed è necessario hidden="until-found".
Ad esempio:
- Se vuoi il controllo completo sullo stile del meccanismo di visualizzazione/nascondimento.
- Se i controlli UI per mostrare/nascondere i contenuti si trovano in un'altra parte del DOM.
- Se non vuoi supportare la possibilità di nascondere i contenuti dopo che sono stati mostrati.
Come implementare
L'elemento <details> ha un testo accessibile e disponibile per la ricerca per impostazione predefinita e non richiede un'implementazione speciale. Se possibile, preferisci l'utilizzo di <details> rispetto a hidden="until-found".
Se invece devi utilizzare hidden="until-found", segui queste istruzioni:
- Applica l'attributo: aggiungi l'attributo HTML
hidden="until-found"direttamente agli elementi contenenti i contenuti che devono essere nascosti alla vista. - Sincronizza lo stato della UI: se l'interfaccia ha stati correlati che dipendono dalla visibilità dei contenuti (ad esempio, l'aggiornamento degli attributi ARIA, l'attivazione/disattivazione delle classi CSS di apertura/chiusura o la rotazione delle icone della fisarmonica):
- DEVI aggiungere un listener di eventi per l'evento
beforematch. - Registra il listener di eventi
beforematchdirettamente sull'elemento che contiene l'attributohidden="until-found". Poiché l'evento si propaga, in alternativa puoi utilizzare la delega degli eventi registrando un singolo listener su un elemento principale (ad esempio un contenitore di schede) per gestire più sezioni nascoste contemporaneamente. - All'interno del listener di eventi, esegui la logica per sincronizzare gli elementi UI correlati (ad esempio chiudere altre schede aperte o modificare lo stato di un pulsante di attivazione/disattivazione).
- DEVI aggiungere un listener di eventi per l'evento
Esempio di codice
Obiettivo: eseguire il rendering di un contenitore nascosto in cui i contenuti rimangono invisibili all'utente finché non cerca una parola all'interno della sezione.
Utilizzo dell'elemento <details>
<details>
<summary>Click to expand</summary>
<p>This content is visually hidden.</p>
</details>
Informative che si escludono a vicenda
Quando gestisci regioni di contenuti che si escludono a vicenda, come una fisarmonica esclusiva, utilizza l'elemento HTML nativo <details> con un attributo name condiviso.
<div class="accordion-group">
<!-- The name attribute creates an exclusive disclosure group -->
<details class="disclosure" name="my-accordion">
<summary>Section 1</summary>
<p>Section 1 content</p>
</details>
<details class="disclosure" name="my-accordion" open>
<summary>Section 2</summary>
<p>Section 2 content</p>
</details>
<details class="disclosure" name="my-accordion">
<summary>Section 3</summary>
<p>Section 3 content</p>
</details>
</div>
Utilizzo dell'attributo hidden="until-found"
<!-- The browser automatically removes hidden="until-found" upon a search match -->
<div class="hidden-container" hidden="until-found">
<p>This content is visually hidden.</p>
</div>
Informativa personalizzata con opzioni che si escludono a vicenda
Quando gestisci regioni personalizzate che si escludono a vicenda controllate da pulsanti esterni, assicurati che rimanga visibile solo il riquadro corrispondente. Nel gestore di eventi beforematch, DEVI sincronizzare gli stati ARIA correlati, ad esempio impostando aria-expanded="true" sul pulsante di controllo.
<div class="custom-accordion">
<div class="controls">
<button aria-expanded="true" aria-controls="panel-1" id="btn-1">Section 1</button>
<button aria-expanded="false" aria-controls="panel-2" id="btn-2">Section 2</button>
</div>
<div id="panel-1" class="panel">
<p>Section 1 content (visible)</p>
</div>
<div id="panel-2" class="panel" hidden="until-found">
<p>Section 2 content (hidden)</p>
</div>
</div>
const accordion = document.querySelector('.custom-accordion');
accordion.addEventListener('beforematch', (e) => {
// Hide all panels and synchronize button states before the browser reveals the matched panel
accordion.querySelectorAll('.panel').forEach((panel) => {
if (panel !== e.target) {
panel.hidden = 'until-found';
}
});
accordion.querySelectorAll('button').forEach((btn) => {
const controls = btn.getAttribute('aria-controls');
btn.setAttribute('aria-expanded', controls === e.target.id ? 'true' : 'false');
});
});
Best practice per hidden="until-found"
- SÌ: applica bordi, spaziatura interna e sfondi ai wrapper secondari nidificati anziché direttamente all'elemento con l'attributo
hidden="until-found". In questo modo si evitano variazioni involontarie del layout o residui visivi mentre l'elemento è nascosto. - NON applicare
display: none,visibility: hiddeno qualsiasi proprietà CSSdisplayovisibilityassociata direttamente agli elementi con l'attributohidden="until-found". In questo modo, la funzionalità nativa viene interrotta e i contenuti vengono nascosti definitivamente dall'indice della Ricerca. - NON utilizzare
hidden="until-found"per informazioni sensibili, token di dati interni o dati irrilevanti che non devono essere esposti tramite la ricerca. - NON utilizzare
hidden="until-found"in sostituzione del testo "solo per screen reader" (.sr-only).
Supporto del browser e strategie di riserva
NON evitare hidden="until-found" a causa della mancanza di supporto del browser, poiché i vantaggi in termini di accessibilità superano di gran lunga il costo dell'implementazione di un fallback.
hidden="until-found" di riserva
Per gli elementi UI standard, come le sezioni a fisarmonica o "Leggi di più", utilizza JavaScript per il rilevamento delle funzionalità e mostra tutti i contenuti se la funzionalità non è supportata.
if (!('onbeforematch' in HTMLElement.prototype)) {
// Expand all hidden content for unsupported browsers
document.querySelectorAll('[hidden="until-found"]').forEach((el) => {
el.removeAttribute('hidden');
// MANDATORY: also update any aria references to this element.
});
}
Per i paradigmi di UI che si escludono a vicenda (come i pannelli esclusivi personalizzati in cui i contenuti condividono la stessa area visiva), il comportamento di riserva deve estrarre e visualizzare tutti i contenuti in modo lineare sotto l'area interattiva principale, utilizzando frammenti di ancoraggio dell'URL per consentire agli utenti di navigare direttamente alle rispettive sezioni.