Addaw, anar a la pàgina d'inici Donar

Lliçó 7 de 10 · 12 min de lectura · Revisada el 26/10/2026

Caselles, interruptors, fitxers i altres controls especials

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.

Un formulari real no està fet només de quadres de text. Té caselles per acceptar condicions, interruptors de preferències, un botó per adjuntar el certificat d'empadronament, un control lliscant per triar un import, un comptador de caràcters al camp d'observacions. Cadascun d'aquests controls té la seva semàntica, el seu comportament de teclat i els seus anuncis, i cadascun es trenca d'una manera característica quan es redissenya. En aquesta lliçó els repassem amb la mateixa regla que aplicarem als selects i calendaris a la lliçó següent: primer el control natiu, i només si no n'hi ha prou, el patró complet de l'ARIA Authoring Practices Guide (s'obre en una finestra nova) (APG). Els components interactius genèrics (menús, pestanyes, diàlegs) es tracten al curs N3-C5.

Caselles i botons d'opció amb estil propi

La petició més habitual del disseny és «vull que les caselles tinguin el nostre estil». La resposta accessible gairebé mai no és construir-les amb <div>: és conservar l'<input> natiu i vestir-lo. Hi ha tres maneres, de menys a més feina:

  1. accent-color: una sola propietat CSS que canvia el color de caselles, botons d'opció, controls lliscants i barres de progrés natius. Funciona a tots els navegadors actuals i no toca la semàntica.
  2. appearance: none sobre el mateix <input> i dibuix de l'estat amb CSS. El control continua sent natiu: rep el focus, respon a la barra espaiadora i anuncia «marcat» o «no marcat».
  3. Input visualment ocult (amb la tècnica d'ocultació visual, mai amb display: none ni visibility: hidden) i un element decoratiu al costat que es pinta segons :checked i :focus-visible de l'input.

Exemple

Incorrecte: una casella que només existeix per al ratolí.

<div class="check" onclick="this.classList.toggle('on')"></div>
<span>Accepto la política de privadesa</span>

Correcte: nativa, amb el color corporatiu i l'etiqueta associada.

<input type="checkbox" id="privacidad" name="privacidad" required>
<label for="privacidad">He llegit i accepto la
  <a href="/privacidad">política de privadesa</a> (obligatori)</label>

<style> input[type="checkbox"] { accent-color: #1a4fa0; } </style>

Recorda el comportament de teclat que donen de franc els controls natius i que qualsevol substitut ha de reproduir: a les caselles, Tab va d'una a l'altra i la barra espaiadora marca o desmarca; als botons d'opció, Tab entra al grup (a l'opció marcada o a la primera) i les fletxes mouen la selecció dins del grup. Els botons d'opció s'agrupen pel seu atribut name: si cadascun té un name diferent, deixen de comportar-se com a grup.

Grups de caselles obligatoris

L'atribut required en una casella vol dir que aquella casella s'ha de marcar; no serveix per a «tria almenys una opció». Per a aquest cas, indica la regla a la <legend> («Idiomes en què pots atendre (tria'n almenys un)»), valida amb JavaScript i, si falla, mostra el missatge al costat del grup i vincula'l al <fieldset> amb aria-describedby. Com que el suport de les descripcions en grups varia entre lectors, el resum d'errors de la lliçó de validació continua sent la xarxa de seguretat.

Interruptors

Un interruptor (switch) representa una cosa que està activada o desactivada i que fa efecte immediatament, com «Rebre avisos per SMS» a l'àrea personal. Una casella, en canvi, és una elecció que s'envia amb el formulari. Si el control aplica el canvi quan es prem, fes servir el rol switch:

<button type="button" role="switch" aria-checked="false" id="sms">
  Avisos per SMS
</button>
<p role="status" id="sms-estado"></p>

<script>
  const sw = document.getElementById('sms');
  sw.addEventListener('click', () => {
    const on = sw.getAttribute('aria-checked') === 'true';
    sw.setAttribute('aria-checked', String(!on));
    document.getElementById('sms-estado').textContent =
      !on ? 'Avisos per SMS activats' : 'Avisos per SMS desactivats';
  });
</script>

El lector anuncia «Avisos per SMS, interruptor, desactivat». El text del botó no canvia: el que canvia és l'estat. La confirmació a role="status" és opcional, però útil quan el canvi es desa al servidor. Visualment, mostra l'estat també amb text («Sí» / «No») o amb la posició del comandament, no només amb el color. El patró complet és a l'APG.

Error freqüent

Un botó que canvia el seu text d'«Activa els avisos» a «Desactiva els avisos» i a més porta aria-pressed. El lector anuncia «Desactiva els avisos, botó d'alternança, premut» i ningú no sap si els avisos estan actius o no. Tria una sola estratègia: o un nom fix amb estat (role="switch" o aria-pressed), o un text que canvia sense estat.

Adjuntar fitxers

A les seus electròniques, adjuntar documents forma part de gairebé qualsevol tràmit, i és un dels punts on més sol·licituds s'abandonen. L'<input type="file"> natiu és accessible amb teclat i lector de pantalla; els problemes arriben amb les zones d'«arrossega aquí els teus fitxers».

  • Arrossegar no pot ser l'única via: hi ha d'haver un botó de selecció que funcioni amb teclat (2.1.1 Teclat) i, pel 2.5.7 Moviments d'arrossegament (AA), una alternativa amb un sol punter sense arrossegar.
  • L'atribut accept filtra el selector de fitxers, però no explica res. Els formats i la mida màxima s'escriuen a l'ajuda del camp i s'associen amb aria-describedby.
  • El progrés de la pujada es mostra amb <progress> etiquetat i s'anuncia en poques fites (inici, final, error) amb una regió d'estat, no a cada percentatge.
  • Cada fitxer pujat apareix en una llista amb el seu nom i un botó «Elimina» que digui quin elimina.
  • Els errors són concrets: «El fitxer pesa 12 MB i el màxim és 10 MB», no «Fitxer no vàlid».
<label for="padron">Certificat d'empadronament</label>
<p id="padron-ayuda">PDF, JPG o PNG. Màxim 10 MB.</p>
<input type="file" id="padron" name="padron"
       accept=".pdf,.jpg,.jpeg,.png" aria-describedby="padron-ayuda">

<ul id="adjuntos">
  <li>padron-2026.pdf (240 kB)
    <button type="button">Elimina <span class="visualmente-oculto">padron-2026.pdf</span></button>
  </li>
</ul>
<p role="status" id="adjuntos-estado"></p>

Controls lliscants, quantitats i comptadors

Controls lliscants

L'<input type="range"> natiu es pot fer funcionar amb fletxes, però anuncia números sense context («25000»). Afegeix aria-valuetext amb el valor llegible («25.000 euros») i actualitza'l quan canviï. I com que afinar un valor exacte amb un control lliscant és difícil per a moltes persones, en imports o terminis ofereix al costat un camp de text sincronitzat. Un control lliscant fet a mà exigeix el patró slider de l'APG, amb aria-valuenow, aria-valuemin i aria-valuemax.

Selectors de quantitat

Els botons «−» i «+» del carretó necessiten un nom complet («Redueix la quantitat de Motxilla escolar blava»), un objectiu d'almenys 24 × 24 píxels i, després de prémer-los, un anunci del nou valor en una regió d'estat si el focus no és sobre el camp. Permet també escriure la quantitat directament.

Comptadors de caràcters

Indica el límit a la descripció del camp («Màxim 500 caràcters») i mostra el que queda. No anunciïs cada pulsació: actualitza el text visible al moment, però envia l'anunci a la regió activa amb un petit retard, quan la persona deixa d'escriure, o en creuar llindars. Evita també que maxlength retalli en silenci un text enganxat: és preferible deixar escriure de més i mostrar un error clar amb el que sobra.

Punt clau

Cada control especial té un control natiu que ja resol la major part de la feina: checkbox, radio, file, range, <progress>. La teva feina és vestir-lo, explicar-lo (formats, límits, valor llegible) i anunciar amb mesura el que canvia sense moure el focus.

Prova-ho tu

Busca un formulari amb caselles o interruptors personalitzats (les preferències de galetes de molts webs són un bon candidat). Recorre'l només amb teclat: arribes a cada control amb Tab? La barra espaiadora canvia l'estat? Inspecciona'n un al tauler Accessibility del navegador: quin rol i quin estat exposa?

Resum

  • Per donar estil a caselles i botons d'opció, conserva l'input natiu: accent-color, appearance: none o ocultació visual, mai display: none.
  • required en una casella obliga a marcar aquella casella; «almenys una» es valida per script i s'explica a la <legend>.
  • Un interruptor d'efecte immediat fa servir role="switch" amb aria-checked i un nom que no canvia.
  • Pujar fitxers exigeix un botó a més de l'arrossegament, formats i mida explicats, progrés anunciat amb mesura i errors concrets.
  • Controls lliscants amb aria-valuetext i camp alternatiu; comptadors que no anuncien cada tecla ni retallen en silenci.

Portes 7 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.