Progressive Disclosure
Progressive Disclosure
8 reglasEstrategia de información, no componente; jerárquica ≠ staged
Progressive disclosure es una estrategia de arquitectura de información, no un componente de UI. Los tres tipos tienen patrones de implementación completamente distintos: Jerárquica (el usuario navega de una lista hacia el detalle de un ítem, como un inbox), Staged (la información se revela en secuencia dependiente, como un wizard que muestra el selector de Estado solo cuando el País fue elegido), y Contextual (información adicional aparece en respuesta directa a una acción puntual del usuario, como un tooltip o popover en hover). Confundir los tipos produce implementaciones incorrectas: usar un staged wizard para datos que deberían ser jerárquicos crea fricción innecesaria y confunde al usuario sobre la relación entre los datos.
Larry Tesler "Progressive disclosure" 1984 · NNg progressive disclosure 2023 · Cooper "About Face" disclosure patterns · Apple HIG disclosure design · IBM Carbon design disclosureTruncar al final de oración completa; word-count > line-clamp
La propiedad CSS -webkit-line-clamp trunca el texto exactamente en el número de líneas indicado, sin ninguna consideración del significado: el corte puede ocurrir en medio de una palabra, entre sujeto y predicado, o incluso en la sílaba de un verbo. El usuario ve "El producto incluye acceso a todas las funciones incluyendo soporte prioritario, backup autom..." y no sabe si la parte omitida es relevante para su decisión. Truncar por conteo de palabras garantiza que el corte ocurra en un límite de oración natural: el pensamiento queda completo, y el enlace "Ver más" solo promete contenido adicional, no la continuación de una idea incompleta. Si se usa line-clamp por restricciones técnicas, la solución es calcular cuántas oraciones completas caben en el espacio antes de aplicar el corte.
"Ver más" solo si oculta ≥2 items; con 1 item oculto mostrar todo
Un botón "Ver más" que revela un único ítem adicional genera fricción cognitiva desproporcionada al beneficio: el usuario hace click esperando ver contenido sustancial y encuentra apenas un elemento. Cuando el threshold de ocultado es de 0 o 1 ítem, la decisión correcta siempre es mostrar todo el contenido sin truncar. El número mínimo que justifica el affordance de "Ver más" depende del contexto (listas de comentarios: 3+, tags: 2+, filas de tabla: 5+), pero el principio universal es que el esfuerzo cognitivo del click debe ser proporcional al volumen de contenido revelado. Además, el botón debe siempre indicar el número exacto de ítems ocultos para que el usuario pueda decidir si vale el clic.
NNg "Show More" pattern 2022 · Baymard UX show more 2023 · GitHub comment collapse · Linear label overflow · Stripe activity feedMáx 3 niveles de disclosure; 4+ → reestructurar
Cada nivel de anidamiento en un árbol de disclosure agrega carga cognitiva: el usuario debe mantener en memoria dónde está en la jerarquía, cómo llegó hasta ahí, y cómo volver. Con 3 niveles es posible la navegación Categoría → Subcategoría → Ítem, que cubre la amplia mayoría de casos de uso reales. A partir del cuarto nivel, la desorientación es casi universal: los estudios de eye-tracking muestran que los usuarios pierden el rastro de la ruta. La solución cuando el modelo de información requiere 4+ niveles no es añadir más acordeones, sino reestructurar: aplanar la jerarquía, mover el 4to nivel a filtros laterales, usar breadcrumbs con navegación dedicada, o paginar el árbol.
NNg IA depth vs breadth 2022 · Miller's Law cognitive load · Material Design 3 navigation depth · Apple HIG hierarchy · Cooper "About Face" IA guidelinesAnimar con opacity+transform; nunca height; interpolate-size para auto
Animar height de 0 a auto no es posible en CSS estándar porque el navegador no puede interpolar un valor calculado con un valor de keyword. La alternativa clásica es usar opacity y transform: translateY: el panel aparece desde arriba mientras se vuelve opaco, sin que el layout cambie en absoluto. Chrome 129 introdujo interpolate-size: allow-keywords que habilita la transición real de height: auto, pero como progressive enhancement detrás de @supports. Nunca animar height con un valor fijo en píxeles: el contenido dinámico (texto que crece, imágenes cargadas) invalidará la animación. El contenedor del demo debe tener altura declarada para evitar layout shift durante la animación.
.panel {
display: grid;
grid-template-rows: 0fr;
transition: grid-template-rows .28s;
}
.panel.open { grid-template-rows: 1fr }
.panel {
max-height: 0;
transition: max-height .4s steps(1);
}
.panel.open { max-height: 200px }
aria-expanded en button; aria-controls obligatorio para JAWS
El patrón de disclosure accesible requiere dos atributos cooperantes en el elemento trigger: aria-expanded comunica al screen reader si el panel está expandido o colapsado en tiempo real, y aria-controls (apuntando al id del panel) permite que JAWS navegue directamente del trigger al contenido que controla. Sin aria-controls, JAWS lee el botón y anuncia el estado pero no puede vincular el anuncio al panel correspondiente, haciendo que el usuario pierda contexto. El panel controlado debe tener un id que coincida exactamente con el valor de aria-controls. El trigger debe ser siempre un elemento <button> nativo, nunca un <div> con role="button", para garantizar el comportamiento de teclado nativo.
<button
aria-expanded="false" ← estado actual
aria-controls="spec-panel" ← vínculo al panel
>
Ver especificaciones
</button>
<!-- Panel: id debe coincidir con aria-controls -->
<div id="spec-panel" hidden>
...contenido revelado...
</div>
// JS: actualizar aria-expanded al toggle
btn.addEventListener('click', () => {
const open = btn.getAttribute('aria-expanded') === 'true'
btn.setAttribute('aria-expanded', !open)
panel.toggleAttribute('hidden', open)
})
Foco permanece en button al expandir inline; moverlo solo en modals
Cuando el contenido se expande inline (el panel aparece en el flujo de la misma pagina, debajo del trigger), el foco debe permanecer en el boton trigger despues del click. Mover el foco automaticamente al primer elemento del panel revelado sorprende al usuario de teclado: esperaba activar el toggle y en cambio se encuentra de golpe dentro del contenido. El foco en el trigger permite al usuario leer primero, y luego presionar Tab para navegar hacia el contenido revelado. La unica excepcion son modals y drawers: como reemplazan completamente el contexto visual del usuario y capturan el flujo de teclado, el foco debe moverse al primer elemento interactuable dentro del overlay inmediatamente al abrirse.
ARIA APG focus management · W3C disclosure button pattern · Radix UI focus management · NVDA focus testing 2023 · WebAIM keyboard focus guidelinesAntipatrón: ocultar info necesaria para la decisión en disclosure
El test de si algo debe estar en un disclosure es simple: "¿Puede el usuario tomar la decisión principal sin expandir este contenido?" Si la respuesta es no, la información debe ser visible por defecto. Ocultar el precio total con impuestos, la política de cancelación, o las limitaciones del plan dentro de un accordion colapsado es un patrón oscuro: penaliza al usuario que toma decisiones informadas, perjudica la confianza, viola principios de transparencia GDPR/FTC, y aumenta las tasas de disputa post-compra. Los accordions son adecuados para especificaciones técnicas adicionales, preguntas frecuentes de soporte, o historial de eventos. Son inapropiados para cualquier información que cambie la naturaleza de la decisión que el usuario está a punto de tomar.
Baymard checkout disclosure antipatterns · NNg progressive disclosure 2023 · Nielsen "10 Usability Heuristics" · GDPR transparency requirements · FTC disclosure guidelines- R-138 Estrategia de información, no componente; jerárquica ≠ staged
- R-139 Truncar al final de oración completa; word-count > line-clamp
- R-140 "Ver más" solo si oculta ≥2 items; con 1 item oculto mostrar todo
- R-141 Máx 3 niveles de disclosure; 4+ → reestructurar
- R-142 Animar con opacity+transform; nunca height; interpolate-size para auto
- R-143 aria-expanded en button; aria-controls obligatorio para JAWS
- R-144 Foco permanece en button al expandir inline; moverlo solo en modals
- R-145 Antipatrón: ocultar info necesaria para la decisión en disclosure