Addaw, ir a inicio Donar

Lección 10 de 10 · Caso práctico · 25 min · Revisado el 26/10/2026

Caso práctico, ejercicios y lista de comprobación

Es el momento de aplicar todo el curso a un caso completo. Vas a revisar y corregir, componente a componente, la ficha de producto de una tienda en línea de calzado (ficticia). Desde el 28 de junio de 2025, el comercio electrónico está dentro del ámbito de la Ley 11/2023 (PDF, se abre en una ventana nueva), así que este tipo de página es hoy una prioridad para muchas empresas españolas. Después pondrás a prueba lo aprendido con ejercicios y te llevarás una lista de comprobación para tus propios proyectos.

Caso práctico: la ficha de producto de una zapatería en línea

La página muestra unas zapatillas de montaña. El equipo de desarrollo pide una revisión antes de una campaña. Estos son los componentes interactivos que contiene y lo que encontramos al probarlos con teclado, con NVDA y con un móvil con TalkBack.

Paso 1. Inventario: cada componente con su patrón

ComponenteQué fallaPatrón correctoCriterios
Buscador con sugerenciasLas sugerencias son <div> sin roles; al aparecer, el foco salta a la primeraCombobox de ARIA 1.2 con listbox4.1.2, 2.1.1, 3.2.2
Galería de fotosRota sola cada 3 segundos sin pausa; las miniaturas son <div> con onclickSin rotación automática; miniaturas como botones con nombre2.2.2, 2.1.1, 4.1.2
Selector de tallaCuadros clicables; la talla elegida solo cambia de color; las agotadas solo aparecen tachadasBotones de opción nativos en <fieldset>1.3.1, 1.4.1, 4.1.2
CantidadBotones «−» y «+» sin nombre; en el máximo, el «+» se deshabilita y el foco se pierdeCampo numérico con botones con nombre y región de estado4.1.2, 2.4.3, 4.1.3
«Añadir a la cesta»Es un <a href="#">; abre un panel lateral que no recibe el focoBotón que abre un diálogo modal4.1.2, 2.4.3
Pestañas Descripción, Composición y Opiniones<li onclick> sin roles ni tecladoPatrón de pestañas o secciones con encabezados1.3.1, 2.1.1, 4.1.2
Valoración mediaCinco iconos SVG sin texto alternativoTexto «4,6 de 5 estrellas (128 opiniones)»1.1.1

Paso 2. Corregir, de lo nativo a lo personalizado

La regla del curso marca el orden: primero lo que se arregla cambiando de elemento, después lo que exige un patrón APG (se abre en una ventana nueva).

  • Talla: se sustituyen los cuadros por botones de opción reales, estilizados como cuadros. La talla agotada se mantiene en la lista con disabled y con el texto «agotada» dentro de la etiqueta, no solo tachada.
  • Valoración: el texto «4,6 de 5 estrellas (128 opiniones)» se muestra junto a los iconos, que pasan a ser decorativos (aria-hidden="true").
  • «Añadir a la cesta»: pasa a ser <button type="button" aria-haspopup="dialog">. El panel lateral se implementa con <dialog> y showModal(), título «Añadido a tu cesta», botones «Seguir comprando» y «Ver la cesta», y devolución del foco al cerrar.
  • Cantidad: botones «Reducir cantidad» y «Aumentar cantidad», aria-disabled en los límites y la región de estado «Cantidad: 3».
  • Galería: se elimina la rotación automática; las miniaturas son botones («Foto 2 de 5: vista lateral») con aria-pressed en la que se muestra.
  • Pestañas: como cada sección es breve y las opiniones conviene enlazarlas desde la valoración, el equipo opta por secciones con <h2> y un enlace «Ver las 128 opiniones». Menos código y mejor en móvil.
  • Buscador: se reconstruye como combobox de ARIA 1.2: foco siempre en el campo, aria-activedescendant hacia la sugerencia resaltada y una región de estado con el número de resultados.
<fieldset>
  <legend>Talla</legend>
  <input type="radio" name="talla" id="t41" value="41">
  <label for="t41">41</label>
  <input type="radio" name="talla" id="t42" value="42" disabled>
  <label for="t42">42 (agotada)</label>
  <input type="radio" name="talla" id="t43" value="43">
  <label for="t43">43</label>
</fieldset>

Paso 3. Volver a probar como al principio

La segunda pasada repite exactamente las pruebas iniciales: teclado (una parada por grupo de tallas, flechas para elegir, Escape en el diálogo), lector de pantalla (cada control con nombre, rol y estado) y puntero (objetivos de 24 por 24 píxeles CSS como mínimo y nada que exija arrastrar). Resultado: los siete problemas quedan resueltos y, de paso, la página tiene menos JavaScript que antes, porque varias de las correcciones consistieron en volver al HTML nativo.

Ejercicios de autoevaluación

1. Una barra de herramientas de un editor tiene ocho botones de formato, todos con tabindex="0", y además responde a las flechas. ¿Qué cambiarías?

Ver solución

Aplicar roving tabindex de forma completa: tabindex="0" solo en el botón activo y -1 en los demás, actualizándolo al moverse con flechas o al hacer clic. El contenedor lleva role="toolbar" y un nombre. Así la barra es una sola parada de Tab.

2. En un buscador de municipios, al escribir «Car» aparecen sugerencias y el foco pasa automáticamente a «Cartagena». ¿Qué problema hay y cómo se corrige?

Ver solución

La persona pierde la posibilidad de seguir escribiendo y oye un anuncio inesperado. El foco del DOM debe quedarse en el campo (role="combobox"); solo Flecha abajo resalta opciones, mediante aria-activedescendant, e Intro acepta.

3. Un interruptor cambia su texto de «Activar avisos» a «Desactivar avisos» y además lleva aria-checked. ¿Es correcto?

Ver solución

No. El lector diría, por ejemplo, «Desactivar avisos, activado», que es contradictorio. Con role="switch" el nombre es fijo («Avisos») y el estado lo comunica aria-checked.

4. En el árbol de carpetas de un gestor documental, cada archivo PDF se anuncia como «contraído». ¿Qué atributo sobra y dónde?

Ver solución

Sobra aria-expanded en los nodos hoja (los archivos). Ese estado solo debe estar en los nodos que tienen hijos.

5. El filtro de precio de una tienda es un deslizador de dos mandos que solo se mueve arrastrando. Propón dos alternativas que cumplan 2.5.7.

Ver solución

Por ejemplo: permitir hacer clic o tocar en la pista para mover el mando más cercano a ese punto, y ofrecer dos campos numéricos («Precio mínimo», «Precio máximo») junto al deslizador. Además, cada mando debe responder a las flechas para cumplir 2.1.1.

6. Un listado de facturas de solo lectura tiene role="grid", pero las flechas no hacen nada. ¿Qué recomiendas?

Ver solución

Quitar role="grid" y dejar una <table> nativa con sus cabeceras. Un listado que solo se lee no necesita navegación por celdas, y el rol sin teclado impide leer la tabla con normalidad.

Lista de comprobación

  • Cada acción es un <button> y cada navegación un <a href>.
  • Antes de crear un control, se ha descartado el equivalente nativo.
  • Cada control tiene un nombre que se entiende fuera de contexto e incluye el texto visible.
  • Los estados (aria-expanded, aria-pressed, aria-selected, aria-checked) se actualizan en cada cambio.
  • Cada widget compuesto es una sola parada de Tab y se recorre con flechas.
  • El teclado de cada componente coincide con su patrón de la APG.
  • Los menús, desplegables y diálogos se cierran con Escape y devuelven el foco.
  • El foco nunca se pierde al eliminar, deshabilitar u ocultar elementos.
  • Los combobox mantienen el foco en el campo y anuncian el número de resultados.
  • Los controles de valor exponen valor y límites, y se pueden fijar sin arrastrar.
  • El contenido que aparece con el puntero o el foco es descartable, señalable y persistente.
  • Nada se mueve más de 5 segundos sin un control para pausarlo.
  • Los objetivos miden al menos 24 por 24 píxeles CSS o tienen separación suficiente.
  • Se ha probado cada componente con teclado, con un lector de pantalla y en un móvil.

Para seguir aprendiendo

Comprueba lo que has aprendido

Esta lección se puede leer libremente. Para hacer su test de 3 preguntas, los ejercicios prácticos con páginas reales, guardar tu avance y optar al examen y al certificado, matricúlate en el curso.