Las interfaces web suelen ocultar contenido oculto para mejorar la experiencia del usuario, ahorrar espacio en la pantalla o aumentar el rendimiento de la página. Los métodos tradicionales, como display: none o visibility: hidden, funcionan para ocultar contenido visualmente, pero también hacen que ese contenido sea completamente inaccesible para los lectores de pantalla y las funciones del navegador, como "Buscar en la página".
Para ocultar contenido visualmente, pero permitir que los usuarios lo busquen y que se pueda vincular directamente a través de fragmentos de URL y vínculos de "Desplazarse al fragmento de texto", puedes usar el elemento HTML <details> o el atributo hidden="until-found". Por lo general, se recomienda el elemento <details>, ya que es más fácil de implementar y mantener, pero hay algunos casos más complejos en los que <details> no es suficiente y se requiere hidden="until-found".
Por ejemplo:
- Si quieres tener control total sobre el estilo del mecanismo para mostrar u ocultar contenido
- Si los controles de la IU para mostrar u ocultar el contenido están en otra parte del DOM
- Si no quieres admitir que se oculte el contenido después de que se muestre.
Cómo implementarlo
El elemento <details> tiene texto accesible y que se puede buscar de forma predeterminada, y no se requiere ninguna implementación especial. Si es posible, prefiere usar <details> en lugar de hidden="until-found".
Si necesitas usar hidden="until-found", sigue estas instrucciones:
- Aplica el atributo: Agrega el atributo HTML
hidden="until-found"directamente a los elementos que contienen el contenido que se debe ocultar de la vista. - Sincroniza el estado de la IU: Si la interfaz tiene estados relacionados que dependen de la visibilidad del contenido (p.ej., actualizar los atributos de ARIA, activar o desactivar las clases de CSS abiertas o cerradas, o rotar los íconos de acordeón), haz lo siguiente:
- DEBES agregar un objeto de escucha de eventos para el evento
beforematch. - Registra el objeto de escucha de eventos
beforematchdirectamente en el elemento que contiene el atributohidden="until-found". Dado que el evento se propaga, también puedes usar la delegación de eventos registrando un solo objeto de escucha en un elemento superior (como un contenedor de pestañas) para administrar varias secciones ocultas a la vez. - Dentro del objeto de escucha de eventos, ejecuta la lógica para sincronizar los elementos de la IU relacionados (como cerrar otras pestañas abiertas o cambiar el estado de un botón de activación).
- DEBES agregar un objeto de escucha de eventos para el evento
Ejemplo de código
Objetivo: Renderizar un contenedor oculto en el que el contenido permanezca invisible para el usuario hasta que busque una palabra en esa sección.
Usa el elemento <details>
<details>
<summary>Click to expand</summary>
<p>This content is visually hidden.</p>
</details>
Divulgaciones mutuamente excluyentes
Cuando manejes regiones de contenido mutuamente excluyentes, como un acordeón exclusivo, usa el elemento HTML <details> nativo con un atributo name compartido.
<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>
Uso del atributo 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>
Divulgaciones personalizadas mutuamente excluyentes
Cuando manejes regiones personalizadas mutuamente excluyentes controladas por botones externos, asegúrate de que solo el panel coincidente permanezca visible. En el controlador de eventos beforematch, DEBES sincronizar los estados de ARIA relacionados, como configurar aria-expanded="true" en el botón de control.
<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');
});
});
Prácticas recomendadas para hidden="until-found"
- SÍ aplica bordes, padding y fondos a los contenedores secundarios anidados, en lugar de hacerlo directamente al elemento con el atributo
hidden="until-found". Esto evita cambios de diseño no deseados o restos visuales mientras el elemento está oculto. - NO apliques
display: none,visibility: hiddenni ninguna propiedad CSSdisplayovisibilityasociada directamente a los elementos con el atributohidden="until-found". Esto interrumpe la funcionalidad nativa y oculta de forma permanente el contenido del índice de la Búsqueda. - NO uses
hidden="until-found"para información sensible, tokens de datos internos o datos irrelevantes que no se deben exponer a través de la búsqueda. - NO uses
hidden="until-found"como reemplazo del texto "solo para lectores de pantalla" (.sr-only).
Compatibilidad con navegadores y estrategias de resguardo
NO evites hidden="until-found" debido a la falta de compatibilidad con el navegador, ya que sus beneficios de accesibilidad superan con creces el costo de implementar un resguardo.
Resguardo de hidden="until-found"
En el caso de los elementos de la IU estándar, como los acordeones o las secciones "Leer más", usa JavaScript para detectar funciones y mostrar todo el contenido si la función no es compatible.
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.
});
}
En el caso de los paradigmas de IU mutuamente excluyentes (como los paneles exclusivos personalizados en los que el contenido comparte la misma región visual), el resguardo debe extraer y mostrar todo el contenido de forma lineal debajo del área interactiva principal, usando fragmentos de anclaje de URL para permitir que los usuarios naveguen directamente a las secciones correspondientes.