Lliçó 10 de 10 · Cas pràctic · 25 min · Revisada el 26/10/2026
Cas pràctic, exercicis i llista de comprovació
Estàs llegint una lliçó oberta. Matricula't gratis per fer els tests i els exercicis, desar el teu progrés i aconseguir el certificat.
És el moment d'aplicar el curs complet a un projecte real. Revisaràs el codi d'una aplicació de cita prèvia, corregiràs els seus errors de CSS, JavaScript i framework, i deixaràs proves automàtiques perquè no tornin. Després tens exercicis d'autoavaluació amb la seva solució i una llista de comprovació per als teus propis desenvolupaments.
Cas pràctic: la cita prèvia de l'Ajuntament de Vega Alta
L'Ajuntament de Vega Alta (municipi fictici) ha estrenat una aplicació de cita prèvia feta amb React i incrustada a la seva seu electrònica. Abans de la revisió periòdica que exigeix l'RD 1112/2018 (PDF, s'obre en una finestra nova), l'equip de desenvolupament et demana que la revisis. El flux té quatre pantalles: triar tràmit, triar oficina, triar dia i hora, i confirmar amb les dades personals. La revisió amb teclat, emulació de preferències i lector de pantalla dona aquestes troballes.
Pas 1. Focus i estils d'interacció
El full d'estils global conté *:focus { outline: none; } i els botons mostren el focus amb un box-shadow blau clar. La capçalera de la seu és sticky i fa 96 píxels, i un bàner de galetes fix ocupa la part inferior: en tornar enrere amb Maj + Tab, els botons de les hores queden sota la capçalera. Els botons dels dies del calendari fan 20 per 20 píxels i estan enganxats.
Correcció: s'elimina la regla global i es defineix un :focus-visible amb outline fosc de 3 píxels i halo clar (2.4.7, 1.4.11); s'afegeix scroll-padding-top i scroll-padding-bottom a l'html amb l'alçada de la capçalera i del bàner, i la capçalera deixa de ser fixa amb max-height: 30em (2.4.11, 1.4.10); els dies passen a min-width i min-height de 2.75rem (2.5.8, i de passada els 44 píxels de 2.5.5).
Pas 2. Colors forçats i mode fosc
Amb un tema de contrast de Windows, els botons «Següent» es converteixen en text solt i les hores disponibles (fons verd) no es distingeixen de les ocupades (fons gris). En mode fosc, el logotip de l'ajuntament desapareix.
Correcció: border: 2px solid transparent als botons; les hores ocupades passen a ser <button disabled> amb el text «ocupada» (cosa que a més resol 1.4.1 Ús del color) i, a forced-colors: active, es marquen amb GrayText; l'hora seleccionada porta una vora de 3 píxels en Highlight. Per al logotip, una versió clara en un <picture> amb prefers-color-scheme: dark.
Pas 3. Comportament en JavaScript
El selector d'oficina és un <select> que navega a la pantalla d'horaris en l'esdeveniment change: amb les fletxes, cada oficina recorreguda dispara la navegació (3.2.2). Els botons de les hores reserven en mousedown (2.5.2). La sessió caduca als 10 minuts sense avís i es perden les dades (2.2.1).
Correcció: el select s'acompanya d'un botó «Mostra els horaris»; les hores fan servir click; dos minuts abans de caducar apareix un diàleg modal amb el focus a «Allarga la sessió», i el formulari desa un esborrany per no perdre les dades.
Pas 4. Rutes, components i animació
En passar d'una pantalla a una altra, el títol de la pestanya continua sent «Cita prèvia», el focus es queda al botó que ja no existeix i el lector no anuncia res. El component <CampoTexto> aplica aria-describedby i aria-invalid al seu div exterior, així que els errors no s'anuncien. A la portada, un carrusel d'avisos gira cada 4 segons sense botó de pausa.
Correcció: un component Pagina que actualitza document.title («Tria l'oficina - Pas 2 de 4 - Cita prèvia»), fa scroll cap amunt, enfoca l'<h1> i anuncia la càrrega en una regió d'estat permanent (2.4.2, 2.4.3, 4.1.3); CampoTexto estén la resta de propietats sobre l'<input> i genera els seus id amb useId(); el carrusel s'atura amb un botó «Posa en pausa els avisos» i no gira si prefers-reduced-motion: reduce està actiu (2.2.2).
Pas 5. Evitar que torni
S'afegeix eslint-plugin-jsx-a11y en mode strict, proves de component amb vitest-axe per a cada estat de CampoTexto i del calendari, i una prova de Playwright que recorre les quatre pantalles amb @axe-core/playwright, comprova que després de cada navegació el focus és a l'<h1> i repeteix el flux amb page.emulateMedia({ forcedColors: 'active', reducedMotion: 'reduce' }). Com que hi havia 40 errors heretats a la seu, es fixa aquest nombre com a llindar màxim a la integració contínua i es redueix en cada iteració.
Exercicis d'autoavaluació
Exercici 1. Un botó de tancar fa 16 per 16 píxels CSS i no té cap altre objectiu a menys de 30 píxels. Incompleix 2.5.8?
Mostra la solució
No necessàriament. 2.5.8 admet objectius més petits de 24 per 24 si tenen prou espai: un cercle de 24 píxels de diàmetre centrat en el botó no talla cap altre objectiu ni el seu cercle. Tot i així, convé ampliar la zona activa.
Exercici 2. En mode de colors forçats, l'indicador de focus d'un web ha desaparegut completament. El CSS fa servir outline: none; box-shadow: 0 0 0 3px #ffbf47. Què canvies?
Mostra la solució
Substituir outline: none per outline: 3px solid transparent. En mode normal el contorn transparent no es veu i es veu l'ombra; en colors forçats l'ombra s'elimina i el sistema pinta el contorn amb el seu color.
Exercici 3. Una llista de documents permet esborrar-ne cadascun amb un botó «Elimina». Després d'esborrar, el lector de pantalla comença a llegir des del principi de la pàgina. Què passa i com es corregeix?
Mostra la solució
El botó que tenia el focus s'ha eliminat del DOM i el focus ha caigut al body. Abans d'eliminar la fila, mou el focus al botó «Elimina» de la fila següent (o de l'anterior si era l'última, o a l'encapçalament de la llista si queda buida) i anuncia «Document eliminat» en una regió d'estat.
Exercici 4. Un Web Component <campo-fecha> conté el seu <input> en un shadow root. Fora, l'autor escriu <label for="nacimiento"> i dona id="nacimiento" al component. El camp no té nom. Per què i quines opcions hi ha?
Mostra la solució
Les referències per id no travessen la frontera del Shadow DOM, i l'amfitrió no és un element etiquetable. Opcions: que el component rebi l'etiqueta com a atribut i la pinti dins del seu propi arbre al costat de l'<input>; convertir-lo en element associat a formulari (formAssociated amb ElementInternals) perquè l'etiqueta externa funcioni; o, com a últim recurs, aria-label.
Exercici 5. Un cercador filtra resultats mentre s'escriu i, quan només en queda un, navega automàticament a la seva fitxa. Quin criteri incompleix i quina part del comportament sí que és correcta?
Mostra la solució
La navegació automàtica és un canvi de context provocat per una entrada sense avís previ: incompleix 3.2.2 En introduir dades. Filtrar la llista mentre s'escriu és un canvi de contingut i és correcte, sempre que el nombre de resultats s'anunciï en una regió d'estat (4.1.3) després d'una breu pausa en l'escriptura.
Llista de comprovació final
- Cap regla no elimina el focus sense substitut a
:focus-visible. - L'indicador de focus fa servir
outlinei contrasta almenys 3:1. - Cap capçalera, barra o bàner fix no tapa l'element enfocat.
- Els objectius de punter fan 24 per 24 píxels CSS o tenen un espai equivalent.
- El contingut amb hover o focus es tanca amb Escape i es pot recórrer amb el punter.
- La interfície funciona amb un tema de contrast de Windows i en mode fosc.
- Les animacions respecten
prefers-reduced-motioni el moviment automàtic té botó de pausa. - Les accions s'executen amb
click, no en prémer. - Cap focus ni canvi de valor no provoca un canvi de context sense avís.
- Les sessions avisen abans de caducar i permeten allargar-les.
- El focus no cau mai al
bodyen inserir o eliminar contingut. - Cada canvi de ruta actualitza el títol, mou el focus i fa scroll cap amunt.
- Els components exigeixen el seu nom accessible i apliquen els atributs al control real.
- El linter, les proves de component i les proves e2e amb axe s'executen en cada canvi.
Per continuar aprenent
- Pautes d'Accessibilitat per al Contingut Web (WCAG) 2.2, recomanació del W3C.
- Understanding 2.4.11 Focus Not Obscured (Minimum), document explicatiu del W3C.
- forced-colors, referència de MDN amb els colors del sistema.
- prefers-reduced-motion, referència de MDN.
- ARIA Authoring Practices Guide (APG), patrons de components del W3C.
Portes 3 lliçons d'aquest curs: que no es perdin
Crea el teu compte gratis i desa el que ja has llegit i segueix el curs amb tot:
- El test d'aquesta lliçó (3 preguntes) per comprovar el que has après
- Exercicis pràctics amb pàgines reals
- El teu progrés desat: continues on ho vas deixar, des de qualsevol dispositiu
- Constància del curs amb les hores i certificat gratuït del nivell 3 quan aprovis l'examen
Entres amb el teu compte de Google o només amb el teu correu electrònic. No cal contrasenya.