Hem construït la base semàntica (04-01), els formularis (04-02) i la capa ARIA declarativa (04-03). Falta la part més visual del principi Perceptible, i és gairebé tota CSS: que el text tingui prou contrast, que no es depengui només del color per transmetre informació, que el contingut es pugui ampliar fins al 200% sense trencar-se, que flueixi a pantalles estretes sense scroll horitzontal, que respecti l'espaiat del text i que el focus sigui sempre visible. Són els criteris 1.4.3, 1.4.11, 1.4.1, 1.4.4, 1.4.10, 1.4.12 i 2.4.7/2.4.11 que al Mòdul 3 vam estudiar com a requisit i que ara implementem en CSS.

Ho aplicarem a la paleta de marca de Cursalia —revisant un color que no compleix i corregint-lo— i pensant molt en particular en la Sofía, que té baixa visió i navega amb el zoom al 300%.

Contingut

  1. Ratios de contrast WCAG (1.4.3 i 1.4.11)
  2. Com mesurar el contrast
  3. No dependre només del color (1.4.1)
  4. Redimensionament del text al 200% i unitats relatives (1.4.4)
  5. Reflux a 320 CSS px (1.4.10)
  6. Espaiat del text (1.4.12)
  7. Indicador de focus visible (2.4.7 / 2.4.11)
  8. Revisió de la paleta de marca de Cursalia
  9. Errors comuns i consells
  10. Exercicis
  11. Conclusió

Ratios de contrast WCAG (1.4.3 i 1.4.11)

El contrast és la diferència de luminància entre dos colors, expressada com una raó d'1:1 (nul) a 21:1 (negre sobre blanc). WCAG fixa mínims en nivell AA:

Element Ratio mínim AA Criteri
Text normal (< 24 px, o < 18.66 px si és negreta) 4.5 : 1 1.4.3
Text gran (≥ 24 px, o ≥ 18.66 px negreta) 3 : 1 1.4.3
Components d'interfície i gràfics (vores d'input, icones, límits d'un botó) 3 : 1 1.4.11

El criteri 1.4.11 (contrast no textual) és el que se sol oblidar: la vora d'un camp de formulari, la icona d'una targeta o la línia d'un gràfic de progrés també s'han de distingir del fons amb almenys 3:1. Un input que té com a única vora un gris claríssim sobre blanc és invisible per a la Sofía encara que el seu text contrasti bé.

/* INCORRECTE: gris sobre blanc ≈ 2.8:1, no arriba a 4.5:1 */
.text { color: #999999; background: #ffffff; }

/* CORRECTE: gris fosc sobre blanc ≈ 7:1 */
.text { color: #595959; background: #ffffff; }

Com mesurar el contrast

No s'estima "a ull": es mesura. Eines habituals (el detall del testing és del Mòdul 6):

  • DevTools del navegador: en inspeccionar text, el selector de color mostra el ratio i si passa AA/AAA.
  • WebAIM Contrast Checker: enganxes els dos colors i dona el ratio.
  • Extensions com axe DevTools o Lighthouse, que auditen la pàgina sencera.

La regla pràctica: cada parell (color de text, color de fons) de la paleta s'ha de verificar. I compte amb el text sobre imatges o degradats: si el fons varia, cal garantir el contrast a la zona més desfavorable (una capa semitransparent darrere del text ho resol).

No dependre només del color (1.4.1)

El criteri 1.4.1 exigeix que cap informació es transmeti únicament pel color. La Marta (que no hi veu) i qualsevol persona amb daltonisme perdrien aquesta dada. Sempre cal afegir un segon canal: text, icona, forma o patró.

Casos típics a Cursalia:

  • Errors de formulari (vist a 04-02): no només vora vermella → afegeix text "Error:" i una icona.
  • Enllaços dins d'un paràgraf: si només es distingeixen pel color, qui no percep aquest color no sap que són enllaços → subratlla'ls o dona'ls una altra pista visible.
  • Gràfic de progrés del curs: si "completat / en curs / bloquejat" es codifica només amb verd/groc/gris, afegeix etiqueta de text, icona o patró.
/* INCORRECTE: els enllaços només es distingeixen pel color */
a { color: #1a6feb; text-decoration: none; }

/* CORRECTE: a més del color, subratllat (segon canal visible) */
a { color: #1a6feb; text-decoration: underline; }
<!-- INCORRECTE: l'estat del curs viu només en la classe de color -->
<li class="verd">Mòdul 1</li>
<li class="gris">Mòdul 2</li>

<!-- CORRECTE: color + text + icona (tres canals) -->
<li class="completat"><span aria-hidden="true">✔</span> Mòdul 1 — Completat</li>
<li class="bloquejat"><span aria-hidden="true">🔒</span> Mòdul 2 — Bloquejat</li>

Redimensionament del text al 200% i unitats relatives (1.4.4)

El criteri 1.4.4 exigeix que el text es pugui ampliar fins al 200% sense perdre contingut ni funcionalitat. La causa número u de fallada és fixar mides de font en píxels absoluts: font-size: 16px no respon bé a la preferència de mida de l'usuari.

La solució és fer servir unitats relatives:

  • rem: relatiu a la mida base del document (la que l'usuari configura al seu navegador). Ideal per a mides de font.
  • em: relatiu a la mida de l'element pare. Útil per a espaiats proporcionals.
  • Evita px per a la tipografia i per a contenidors que hagin de créixer amb el text.
/* INCORRECTE: px absolut, ignora la preferència de l'usuari */
body { font-size: 16px; }
h1   { font-size: 32px; }

/* CORRECTE: rem/em respecten la mida base configurada */
html { font-size: 100%; }        /* respecta la preferència del navegador */
body { font-size: 1rem; }        /* ≈ 16px, però escalable */
h1   { font-size: 2rem; }        /* creix en proporció */

Si la Sofía apuja la mida de font base al 200%, amb rem tot el text creix de manera coherent. Amb px no es mouria. A més, no fixis alçades rígides en px a contenidors de text: un height: 40px en un botó fa que el text ampliat es talli; fes servir min-height i deixa que el padding respiri.

Reflux a 320 CSS px (1.4.10)

El criteri 1.4.10 (Reflux) exigeix que el contingut es pugui veure sense scroll en dues dimensions a una amplada equivalent a 320 CSS px (el que passa, per exemple, quan la Sofía amplia al 400% en un monitor de 1280 px). És a dir: hi pot haver scroll vertical (normal), però no horitzontal. El contingut s'ha de reajustar (reflux), no sortir-se'n.

Això s'aconsegueix amb disseny responsive/fluid:

/* INCORRECTE: amplada fixa que provoca scroll horitzontal en ampliar */
.cataleg { width: 1200px; }
.targeta { width: 380px; float: left; }

/* CORRECTE: graella fluida que es reajusta a una columna en pantalles estretes */
.cataleg {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 1rem;
  max-width: 100%;
}
img { max-width: 100%; height: auto; }   /* imatges que no desborden */

minmax(280px, 1fr) amb auto-fill fa que les targetes del catàleg passin de diverses columnes a una de sola sense que res se surti pel lateral. Fes servir també @media queries per reorganitzar la maqueta en amplades petites. Excepció del criteri: contingut que necessita dues dimensions (taules grans, mapes) pot requerir scroll, però és l'excepció, no la norma.

Espaiat del text (1.4.12)

El criteri 1.4.12 exigeix que, si l'usuari força certs espaiats (per millorar-ne la llegibilitat, cosa que ajuda molt a en Hugo amb dislèxia), el contingut no es trenqui ni se solapi. Els valors que ha de suportar el teu CSS:

Propietat Valor que l'usuari pot imposar
line-height (interlineat) almenys 1.5 × mida de font
Espai entre paràgrafs almenys 2 × mida de font
letter-spacing almenys 0.12 × mida de font
word-spacing almenys 0.16 × mida de font

La clau per complir-ho: no fixis alçades rígides ni facis servir overflow: hidden en contenidors de text. Si un botó o una targeta té alçada fixa, en augmentar l'interlineat el text es talla.

/* CORRECTE: base còmoda i contenidors que creixen amb el text */
p       { line-height: 1.6; margin-bottom: 1.5em; }
.targeta { min-height: 8rem; overflow: visible; }  /* min-height, no height */

Indicador de focus visible (2.4.7 / 2.4.11)

Quan la Lucía tabula amb el teclat, necessita veure on és el focus en cada moment (criteri 2.4.7, Focus visible; i 2.4.11 reforça que aquest indicador no quedi tapat). El navegador dibuixa un outline per defecte... i l'error clàssic és esborrar-lo per estètica:

/* INCORRECTE I GREU: elimina el focus sense donar res a canvi */
:focus { outline: none; }

Amb això, la Lucía queda "a cegues": tabula sense saber en quin control està. Si per disseny vols canviar l'estil del focus, substitueix-lo, mai l'eliminis sense més. L'eina moderna és :focus-visible, que mostra l'anell quan es navega amb teclat però no en fer clic amb ratolí:

/* CORRECTE: focus propi, ben visible i amb bon contrast */
:focus-visible {
  outline: 3px solid #1a6feb;   /* gruix clar */
  outline-offset: 2px;          /* separació perquè no el tapi la vora */
  border-radius: 4px;
}

Requisits de l'indicador: ha de tenir contrast suficient (mínim 3:1 respecte al que hi ha al voltant, en línia amb 1.4.11), ser gruixut i no quedar ocult darrere d'altres elements. Enllacem amb els criteris de teclat 2.4.7/2.4.11; el maneig programàtic del focus en obrir diàlegs i widgets és del Mòdul 5.

Revisió de la paleta de marca de Cursalia

Posem en pràctica tot amb la paleta de Cursalia. El color corporatiu és un blau de marca que es fa servir per a botons i enllaços. Auditem:

Ús Color text Fons Ratio Compleix AA (4.5:1)?
Botó primari #ffffff #4a9cf5 (blau clar de marca) 2.3 : 1 ❌ No
Botó primari (corregit) #ffffff #1a6feb (blau enfosquit) 4.6 : 1 ✅ Sí
Text d'ajuda gris #9a9a9a #ffffff 2.8 : 1 ❌ No
Text d'ajuda (corregit) #595959 #ffffff 7 : 1 ✅ Sí

El blau clar de marca queda bonic, però amb text blanc a sobre no arriba a 4.5:1: la Sofía no el llegeix amb comoditat. La correcció no obliga a canviar la identitat: s'enfosqueix el blau just el que cal per complir, reservant el to clar original per a fons decoratius on no hi hagi text a sobre.

/* INCORRECTE: blau de marca massa clar per a text blanc (2.3:1) */
.btn-primari { background: #4a9cf5; color: #fff; }

/* CORRECTE: blau enfosquit que compleix AA (4.6:1) mantenint la identitat */
.btn-primari {
  background: #1a6feb;
  color: #fff;
  border: 1px solid #1a6feb;   /* a més, contrast no textual de la vora: 1.4.11 */
}
.btn-primari:focus-visible {
  outline: 3px solid #0b3d91;
  outline-offset: 2px;
}

Errors Comuns i Consells

  • Fiar-se de l'ull per al contrast. Mesura'l sempre amb una eina; els grisos clars enganyen.
  • Oblidar el contrast no textual (1.4.11). Vores d'inputs, icones i línies de gràfics també necessiten 3:1.
  • Codificar informació només amb color. Afegeix sempre un segon canal: text, icona, subratllat, patró.
  • Tipografia en px. Impedeix l'escalat; fes servir rem/em i respecta la mida base de l'usuari.
  • Alçades fixes en contenidors de text. Trenquen el redimensionament (1.4.4) i l'espaiat (1.4.12): fes servir min-height i evita overflow: hidden.
  • Amplades fixes que provoquen scroll horitzontal. Dissenya amb graelles fluides i max-width: 100% per complir el reflux (1.4.10).
  • outline: none sense substitut. És dels errors més perjudicials per a qui fa servir teclat. Fes servir :focus-visible amb un anell contrastat.
  • Consell: prova la teva pàgina amb el zoom del navegador al 200% i al 400%, i recorre-la amb el teclat. Si apareix scroll horitzontal, el text es talla o perds de vista el focus, tens feina pendent.

Exercicis

Exercici 1: corregir un contrast insuficient

L'etiqueta de "descompte" de Cursalia fa servir text blanc #ffffff sobre un taronja clar #ffb066, amb un ratio d'1.8:1. Explica per què falla i proposa una correcció que mantingui el taronja com a color, indicant quin canal addicional hi afegiries.

Exercici 2: de px a unitats relatives

Refactoritza aquest CSS perquè el text escali al 200% i el botó no talli el text en ampliar-lo.

body { font-size: 14px; }
.cta {
  font-size: 18px;
  height: 36px;
  line-height: 36px;
  overflow: hidden;
}

Exercici 3: focus visible accessible

Un dissenyador ha posat :focus { outline: none; } a tota la SPA del panell de l'alumne "perquè la vora blava és lletja". Explica el problema i escriu una alternativa accessible amb :focus-visible.

Solucions

Solució 1. Falla perquè 1.8:1 està molt per sota del mínim AA de 4.5:1 per a text normal (i de 3:1 fins i tot per a text gran): la Sofía no distingeix el text del fons. Correcció: enfosquir el taronja fins a aconseguir contrast amb el text (o posar text fosc sobre el taronja clar), i no dependre només del color de l'etiqueta afegint la paraula "Descompte" o una icona:

/* Text fosc sobre el taronja clar: ≈ 6:1 */
.descompte { background: #ffb066; color: #3d2400; }
<span class="descompte"><span aria-hidden="true">🏷️</span> Descompte -20%</span>

Solució 2. Se substitueix px per rem, i l'alçada fixa per padding + min-height, traient el overflow: hidden:

body { font-size: 100%; }     /* respecta la mida base de l'usuari */
.cta {
  font-size: 1.125rem;        /* ≈ 18px, però escalable */
  min-height: 2.5rem;         /* creix si cal, no talla */
  line-height: 1.5;
  padding: 0.5rem 1rem;
  overflow: visible;
}

Ara, en ampliar al 200% o en forçar més interlineat (1.4.12), el botó creix amb el text en lloc de retallar-lo.

Solució 3. El problema: outline: none deixa la Lucía (i qualsevol que faci servir teclat) sense saber quin element té el focus, incomplint 2.4.7. En una SPA amb molts controls, és especialment greu. Alternativa: un indicador propi, visible i contrastat, només per a navegació amb teclat:

:focus-visible {
  outline: 3px solid #1a6feb;
  outline-offset: 2px;
  border-radius: 4px;
}

Es manté l'estètica (no apareix anell en fer clic amb ratolí) sense sacrificar l'accessibilitat del teclat.

Conclusió

Amb aquesta lliçó tanquem el Mòdul 4. Has implementat la cara visual de "Perceptible" en CSS: ratios de contrast 4.5:1 / 3:1 (text i no textual), no dependre només del color, text escalable amb unitats relatives fins al 200%, reflux sense scroll horitzontal a 320 CSS px, espaiat del text que no trenca la maqueta i un focus visible amb :focus-visible que mai s'elimina sense substitut. I has corregit la paleta de Cursalia perquè la Sofía, amb el seu zoom al 300%, llegeixi sense barreres.

Amb això ja tenim una base sòlida i estàtica: HTML semàntic (04-01), formularis accessibles (04-02), ARIA declarativa (04-03) i CSS accessible (04-04). Tot el que hem fet descriu què és cada cosa i com es veu, però encara no li hem donat comportament. Aquest és el salt del Mòdul 5: donar vida amb JavaScript als widgets interactius (el desplegable de filtres, l'acordió de FAQ), gestionar el teclat i el focus de manera programàtica, i fer accessible el multimèdia (vídeo i àudio) i les imatges amb l'atribut alt en profunditat. Passem de l'estructura al comportament.

© Copyright 2026. Tots els drets reservats