Cargando...

Accesibilidad con CSS

Ya envías layouts, motion y trucos del toolkit moderno. La accesibilidad en CSS es la capa que la gente siente: ¿ven dónde está el foco del teclado? ¿pueden leer el texto? ¿una animación giratoria les marean? Esta sesión no es un volcado de HTML (landmarks, alt, ARIA). Son los hábitos de estilo que mantienen usables el foco, el contraste y el movimiento.

El foco debe seguir visible

Quien navega con teclado recorre enlaces y controles con Tab. Si el anillo de foco desaparece, se pierde. Prefiere :focus-visible para que los clics de ratón se queden tranquilos y el foco de teclado se note alto:

Visible keyboard focus with :focus-visible

css
:root {
--focus-ring: #2563eb;
}

a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible {
outline: 3px solid var(--focus-ring);
outline-offset: 3px;
}

.text-link:focus:not(:focus-visible) {
outline: none;
}

:focus-visible apunta a los casos en que el anillo ayuda (casi siempre teclado). Combínalo con un anillo de alto contraste y un poco de outline-offset para que no choque con los bordes.

Nunca outline: none sin reemplazo

Quitar el outline por defecto está bien solo cuando ofreces un estilo de foco personalizado más claro. Un *:focus { outline: none; } a pelo es la trampa clásica:

Replace outline — do not erase focus

css
/* Bad: keyboard users lose the only cue */
.bad-button:focus {
outline: none;
}

/* Good: custom ring that still shows focus */
.good-button:focus-visible {
outline: none;
box-shadow: 0 0 0 3px #fff, 0 0 0 6px #0f766e;
}

Si apagas el outline del navegador, otra cosa debe marcar el control enfocado: box-shadow, color de borde o un cambio de fondo que siga siendo obvio en cualquier tema.

El contraste es una decisión CSS

Los colores de marca se ven nítidos en el mockup y se apagan en el móvil al sol. Trata los pares primer plano / fondo como decisiones de accesibilidad, no solo decoración:

Contrast-safe text and surface tokens

css
:root {
--surface: #0f172a;
--text: #f8fafc;
--muted: #cbd5e1;
--accent: #38bdf8;
--accent-text: #0c4a6e;
}

.hero {
background: var(--surface);
color: var(--text);
}

.hero .lede {
color: var(--muted);
}

.hero .cta {
background: var(--accent);
color: var(--accent-text);
font-weight: 700;
}

Busca contraste fuerte en el texto de cuerpo y los botones. Los grises decorativos pueden ir más suaves en etiquetas secundarias, pero el copy y los controles principales deben seguir legibles. Comprueba los pares con un medidor de contraste antes de publicar la paleta.

Respeta el movimiento reducido

Las animaciones y los transforms grandes pueden incomodar. Envuelve el movimiento no esencial en prefers-reduced-motion:

Gate motion with prefers-reduced-motion

css
.banner {
transition: transform 0.4s ease, opacity 0.4s ease;
}

.banner.is-shown {
transform: translateY(0);
opacity: 1;
}

@media (prefers-reduced-motion: reduce) {
.banner,
.banner.is-shown {
transition: none;
transform: none;
}

.spinner {
animation: none;
}
}

Quien pide al sistema operativo menos movimiento debe llegar al estado final de la UI — solo sin el viaje. Mantén cambios esenciales de opacity o layout; quita giros infinitos y deslizamientos grandes.

Alto contraste y forced-colors

Algunos entornos sustituyen tu paleta (Alto contraste de Windows / forced-colors). Suaviza decoraciones frágiles y conserva bordes reales:

Stay usable under forced-colors

css
.card {
border: 1px solid #e2e8f0;
background: #fff;
box-shadow: 0 8px 24px rgb(15 23 42 / 12%);
}

@media (forced-colors: active) {
.card {
border: 1px solid CanvasText;
background: Canvas;
box-shadow: none;
color: CanvasText;
}

.card a {
color: LinkText;
}
}

Palabras de color del sistema como Canvas, CanvasText y LinkText ayudan a que los controles sigan visibles cuando el usuario — no tu guía de marca — manda en los colores.

Lista de comprobación del lado CSS

📊 CSS accessibility habits

Practice CSS habit Avoid
Keep focus findable :focus-visible + strong ring / shadow outline: none with no replacement
Readable type High-contrast text/background tokens Light grey on white for body copy
Kind motion @media (prefers-reduced-motion: reduce) Endless spins for everyone
Survive high contrast Real borders; forced-colors tweaks Shadow-only “edges”
Reachable controls Comfortable padding / hit area Tiny icon-only targets with no focus style

HTML sigue siendo dueño de landmarks, etiquetas y texto alt. CSS decide si esos controles siguen siendo perceptibles una vez estilizados.

Enlaces de salto y focus-within

Un enlace de salto (skip link) salta la barra repetida. Estilízalo para que aparezca al enfocarse. :focus-within también puede resaltar todo un grupo cuando un hijo tiene el foco:

Skip link + focus-within group

css
.skip-link {
position: absolute;
left: 1rem;
top: -3rem;
padding: 0.5rem 0.75rem;
background: #111827;
color: #fff;
border-radius: 0.375rem;
z-index: 20;
}

.skip-link:focus-visible {
top: 1rem;
outline: 3px solid #fbbf24;
outline-offset: 2px;
}

.nav:focus-within {
box-shadow: inset 0 0 0 2px #2563eb;
}

El enlace de salto permanece fuera de pantalla hasta el foco y entonces se hace obvio. El anillo del nav ayuda cuando Tab cae en un enlace hijo dentro de la barra.

Pruébalo tú

  1. Añade un anillo :focus-visible a enlaces y botones; recorre la página con Tab y confirma que siempre ves el foco.
  2. Elige un par de bajo contraste y corrígelo con texto más oscuro o una superficie más profunda.
  3. Envuelve una transition o animation en prefers-reduced-motion: reduce y cambia el ajuste del SO (o la emulación de DevTools).
  4. Bajo emulación de forced-colors, asegúrate de que las tarjetas sigan mostrando un borde real.
  5. Estiliza un skip link que solo aparezca con foco de teclado.

Errores frecuentes

  • outline: none (o outline: 0) global sin estilo de foco personalizado
  • Colores de marca bonitos que fallan el contraste en texto de cuerpo y botones primarios
  • Animaciones grandes para todos sin puerta prefers-reduced-motion
  • Ocultar un control enfocable solo con opacity: 0 mientras sigue recibiendo Tab
  • Tratar esta lección de CSS como sustituto completo del HTML semántico y ARIA

Resumen

  • Mantén el foco de teclado visible — prefiere :focus-visible y no borres el outline sin una señal más fuerte
  • Trata el contraste de color como requisito para texto y controles
  • Honra prefers-reduced-motion y endurece estilos para forced-colors
  • Estiliza skip links y usa :focus-within donde el grupo necesite una señal compartida
  • Siguiente: Resumen CSS y siguientes pasos (summary) — cierra el curso antes del mini proyecto

🧠 Pon a Prueba tu Conocimiento

Listo para Empezar

Pon a Prueba tu Conocimiento

Ponte a prueba con este cuestionario interactivo y descubre qué tan bien entiendes el tema

❓
7
Preguntas
🎯
70%
Para Aprobar
♾️
∞
Tiempo
🔄
∞
Intentos

📝 Instrucciones

  • Lee cada pregunta cuidadosamente
  • Selecciona la mejor respuesta para cada pregunta
  • Puedes repetir el quiz tantas veces como quieras
  • Tu progreso se mostrará en la parte superior