Formularios
Los formularios son una forma de interacción con el usuario muy importante, por ejemplo, para registros, contacto o cualquier tipo de envío de información.
Resumen para unos formularios accesibles:
- Todos los campos activos deben ser accesibles mediante la tabulación del teclado.
- Añade la información que se relaciona con todo el formulario antes del inicio del formulario.
- Todos los los controles de formulario (input, textarea, select) deben tener asociado un label, o en su defecto, el atributo
aria-label
que especifique claramente el propósito del campo. - Resalta los campos cuando se haga foco sobre ellos.
- Los campos obligatorios deben quedar claramente marcados (asterisco, texto descriptivo, etc.) y tener el atributo
aria-required
. [Criterio 3.3.2 ↗️] - Ofrece espacio suficiente entre campos y zonas pulsables amplias. (mínimo 44px por 44px) [Criterio 2.5.8 - Tamaño objetivo ↗️]
- Ofrece tiempo suficiente para completar un formulario (caducidad de sesión).
- Usa autocompletado cuando sea posible con el atributo
autocomplete
. [Criterio 1.3.5 - Identificar propósito de entrada ↗️] - Cuando se envíe los datos de un formulario, informa al usuario de la acción realizada, para formularios complejos, es útil mostrar una página de confirmación de la información facilitada antes de enviarla.
- Ofrece ayuda e información complementaria para rellenar campos que puedan ser complejos, utiliza el atributo
aria-describedby
. [Criterio 3.3.2 ↗️] - No uses el botón reset.
- Utiliza los elementos fieldset y legend para describir grupos de control de formulario. [Criterio 1.3.1 ↗️]
Gestión de errores
Identifica dónde están los errores y describe el problema en un lenguaje que la gente entienda [Criterio 3.3.1 ↗️], estos deben ser visibles y perceptibles usando colores, iconos y texto. [Criterio 1.4.1 - Uso del color ↗️]
Ofrece sugerencias para corregir un error de entrada. [Criterio 3.3.3 ↗️]
Escriba mensajes de error para ser lo más específico posible, en lugar de usar mensajes genéricos. [Criterio 3.3.1 ↗️]
Evita poner enlaces dentro del texto del mensaje de error.
Label
La etiqueta <label>
representa el título del elemento de control asociado.
Asociando el label
Las etiquetas <label>
deben asociarse de forma implícita o explícita a los distintos controladores de formulario (input, textarea, select).
Asociación implícita
La etiqueta <label>
engloba a su control asociado.
Ejemplo de label con asociación implícita:
<label>Nombre:
<input type="text" id="nombre" name="nombre" />
</label>
Asociación explícita
Debemos añadir el atributo for=''
con el id del control asociado a la etiqueta <label>
.
Ejemplo de label con asociación explícita:
<label for="nombre">Nombre:</label>
<input type="text" id="nombre" name="nombre" />
Recuerda que el id
debe ser único en cada página, si el formulario es dinámico y no puedes controlar sus identificadores, utiliza la asociación implícita.
Asociación con aria-label
Podemos reemplazar la etiqueta <label>
por un atributo aria-label
.
Ejemplo de label con atributo aria-label
:
<input type="text" aria-label="Nombre" id="nombre" name="nombre" />
No es aconsejable prescindir de label
, ya que aporta información una información visual.
Asociación con aria-labelledby
En ciertos casos, como un buscador, podemos prescindir del label y asociar el botón de búsqueda mediante aria-labeledby
Ejemplo de label con atributo aria-labelledby
:
<input type="text" name="buscar" aria-labelledby="boton-buscar">
<button id="boton-buscar" type="submit">Buscar</button>
Diferencias entre aria-label y aria-labelledby
Con aria-label
estás definiendo un label al elemento.
Con aria-labelledby
estás definiendo un label mediante una id que enlaza un texto/campo visible fuera del elemento.
Ayuda / descripción de campos de formulario
Se recomienda proporcionar ayuda/información en los campos que puedan ofrecer dudas o restricciones de formato.
Placeholder
Con los placeholder mostraremos un texto dentro de los campos input
o textarea
, recuerda que un placeholder no reemplaza a un label.
<label for="name">Nombre completo: </label>
<input
type="text"
name="name"
id="name"
placeholder="Escriba su nombre y apellidos"
/>
Con css es posible modificar el estilo del placeholder, debajo te mostramos un ejemplo:
::placeholder {
/* Chrome, Firefox, Opera, Safari 10.1+ */
color: red;
opacity: 1; /* Firefox */
}
Ayuda dentro del label
Otra opción es ofrecer ayuda dentro de nuestro label, te mostramos un ejemplo el formato requerido:
<label for="expire">Fecha de caducidad (MM/AAAA): </label>
<input type="text" name="expire" id="expire" />
Ayuda fuera del label, aria-describedby
Podemos hacer uso del atributo WAI-ARIA aria-labelledby
o aria-describedby
, para ofrecer información complementaria del campo.
<!-- aria-labelledby -->
<label id="expLabel" for="expire" tabindex="-1">Fecha de caducidad:</label>
<span>
<input
type="text"
name="expire"
id="expire"
aria-labelledby="expLabel expDesc"
/>
<span id="expDesc" tabindex="-1">MM/AAAA</span>
</span>
<!-- aria-describedby -->
<label id="expLabel" for="expire">Fecha de caducidad:</label>
<span>
<input
type="text"
name="expire"
id="expire"
aria-labelledby="expLabel"
aria-describedby="expDesc"
/>
<span id="expDesc">Usa el formato MM/AAAA</span>
</span>
Input y textarea
Los elementos input deben llevar su type correspondiente.
Ejemplo de algunos tipos de inputs:
<input type="button" />
<input type="checkbox" />
<input type="color" />
<input type="date" />
<input type="datetime-local" />
<input type="email" />
<input type="file" />
<input type="hidden" />
<input type="image" />
<input type="month" />
<input type="number" />
<input type="password" />
<input type="radio" />
<input type="range" />
<input type="reset" />
<input type="search" />
<input type="submit" />
<input type="tel" />
<input type="text" />
<input type="time" />
<input type="url" />
<input type="week" />
Inputmode
El inputmode
es un atributo que proporciona una sugerencia a los navegadores para decidir qué teclado por pantalla mostrar cuando un usuario ha seleccionado un campo input/textarea.
<input type="text" inputmode="" />
<textarea inputmode="" />
<!-- Numérico -->
<input type="text" inputmode="numeric" />
<!-- Teléfono -->
<input type="text" inputmode="tel" />
<!-- Decimal -->
<input type="text" inputmode="decimal" />
<!-- Email -->
<input type="text" inputmode="email" />
<!-- URL -->
<input type="text" inputmode="url" />
<!-- Buscador -->
<input type="text" inputmode="search" />
Emulando con WAI-ARIA
Tanto input como textarea se pueden emular mediante WAI-ARIA, aunque siempre es recomendable usar el elemento nativo.
<!-- campo input simple -->
<div id="txtboxLabel">Código postal:</div>
<div
role="textbox"
contenteditable="true"
aria-placeholder="5-digit zipcode"
aria-labelledby="txtboxLabel"
></div>
<!-- campo textarea -->
<div id="txtboxMultilineLabel">Comentarios:</div>
<div
role="textbox"
contenteditable="true"
aria-multiline="true"
aria-labelledby="txtboxMultilineLabel"
aria-required="true"
></div>
Fieldset y legend
Usa la etiqueta <fieldset>
para englobar los distintos apartados, y a su vez la etiqueta <legend>
para añadir un título.
<fieldset>
<legend>Información personal</legend>
<!-- campos de información personal -->
</fieldset>
Checkbox y radio button
- Agrupa los radiobutton o checkbox dentro de un fieldset.
- Añade un legend para proporcionar una descripción para la agrupación, esta debe ser corta y descriptiva.
<fieldset>
<legend>¿Cuál es tu color preferido?</legend>
<div class="checkbox column">
<input id="rojo" type="checkbox" name="color" value="rojo" />
<label for="rojo">Rojo</label>
<input id="azul" type="checkbox" name="color" value="azul" />
<label for="azul">Azul</label>
<input id="verde" type="checkbox" name="color" value="verde" />
<label for="verde">Verde</label>
</div>
</fieldset>
- Como alternativa al fieldset, podemos usar WAI-ARIA, añadiendo al div contenedor los atributos
role="group"
yaria-labelledby
.
<div role="group" aria-labelledby="color_head">
<h4 id="color_head" class="bold">¿Cuál es tu color favorito</h4>
<div class="row">
<input id="rojo" type="checkbox" name="color" value="rojo" />
<label for="rojo">Rojo</label>
<input id="azul" type="checkbox" name="color" value="azul" />
<label for="azul">Azul</label>
<input id="verde" type="checkbox" name="color" value="verde" />
<label for="verde">Verde</label>
</div>
</div>
Switch
Switch con botones
En el caso de crear un switch con la etiqueta <button>
, debemos incluir el atributo role="switch"
y aria-checked
con el valor "true, false o mixed"
, dependiendo de su estado.
<div>
<button type="button" id="toggle_label" aria-labelledby="toggle_label" aria-checked="false" role="switch">
<span>Modo oscuro</span>
</button>
<label for="toggle_label">Moso oscuro</label>
</div>
Switch con input
Si usamos un <input>
del tipo checkbox, debemos añadir una etiqueta <label>
<label for="toggle">
<input type="checkbox" name="toggle" id="toggle" />
Modo oscuro
</label>
Select
- Utiliza el atributo
title
para proporcionar ayuda contextual en los controles del formulario. - Proporciona un orden de tabulación lógico mediante
tabindex
cuando el orden por defecto no es suficiente. - Añade el atributo
optgroup
para agrupar elementos option dentro de un elemento select.
Botón reset
Con el tiempo ha ido cayendo en desuso, uno de los motivos es la facilidad con la que puede ser pulsado por error y vaciar todos los campos.
Imagina estar rellenando un formulario con muchos campos y por error pinchar en el botón reset 💀; por ese motivo, si lo añadimos, debemos añadir un mensaje de confirmación para evitar sustos.
Los que sí debemos ofrecer, es la opción a que el usuario pueda restablecer el valor por defecto de campos de opción como radiobutton o checkbox.