Estilizado de Barras de Desplazamiento CSS — Referencia Completa
Las barras de desplazamiento del navegador son uno de los elementos de interfaz predeterminados más consistentemente feos en la web, y varían dramáticamente entre sistemas operativos. En Windows aparecen como barras grises y anchas que ocupan espacio de layout incluso cuando no se usan. En macOS son delgadas y solo aparecen al hacer scroll. El estilizado CSS de barras de desplazamiento te permite anular estos valores predeterminados para crear barras que coincidan con tu sistema de diseño — o para ocultarlas completamente manteniendo el contenido desplazable.
Dos APIs en competencia que debes conocer
Actualmente existen dos especificaciones CSS separadas para el estilizado de barras de desplazamiento. La API de pseudo-elementos WebKit usa una familia de pseudo-elementos ::-webkit-scrollbar y funciona en Chrome, Edge y Safari. La especificación W3C CSS Scrollbars Level 1 usa las propiedades scrollbar-color y scrollbar-width — Firefox la ha soportado desde la versión 64, y Chrome y Edge la adoptaron a partir de la versión 121. La forma correcta para código de producción es incluir ambas.
La familia de pseudo-elementos WebKit
El enfoque WebKit funciona exponiendo los sub-componentes de la barra de desplazamiento como pseudo-elementos estilizables. El pseudo-elemento ::-webkit-scrollbar apunta a la barra completa y es donde estableces el width (para barras verticales) y height (para barras horizontales). ::-webkit-scrollbar-thumb estiliza el controlador arrastrable. ::-webkit-scrollbar-track estiliza el área de pista detrás del thumb. ::-webkit-scrollbar-corner estiliza el pequeño cuadrado donde se encuentran una barra vertical y una horizontal.
Una nuance importante: para que el estilizado WebKit se aplique a un elemento, ese elemento debe tener realmente una barra de desplazamiento. El elemento necesita overflow: auto o overflow: scroll y contenido que desborde sus dimensiones.
La propiedad W3C scrollbar-color
La propiedad scrollbar-color toma exactamente dos valores de color: el color del thumb primero, luego el color de la pista. No acepta degradados y no puedes controlar estados hover o border-radius. Lo que le falta en control lo compensa con simplicidad y cumplimiento de estándares. Para recolorear simple — como hacer una barra de desplazamiento en modo oscuro sobre un fondo oscuro — es la solución más concisa.
La propiedad scrollbar-width
La propiedad scrollbar-width acepta tres valores. auto usa el valor predeterminado de la plataforma. thin produce una barra de desplazamiento más delgada, aproximadamente 8px en la mayoría de las implementaciones. none oculta la barra de desplazamiento completamente manteniendo el contenido desplazable — el elemento sigue respondiendo a eventos de rueda del mouse, teclado y táctiles, pero no aparece ninguna barra visible.
Delimitar estilos de barra de desplazamiento
Los estilos de barra de desplazamiento declarados sin selector de ámbito se aplican globalmente a todos los elementos desplazables de la página. Para delimitar un estilo a un elemento específico — como un bloque de código o una barra lateral de navegación — agrega el selector del elemento al pseudo-elemento: .code-block::-webkit-scrollbar { width: 4px; }.
Estilizado de barra de desplazamiento horizontal
Las barras de desplazamiento horizontales usan height en lugar de width en el pseudo-elemento ::-webkit-scrollbar. Todo lo demás funciona de manera idéntica a las barras de desplazamiento verticales.
Diseñar barras de desplazamiento para accesibilidad
La consideración de accesibilidad más importante es la visibilidad y el tamaño de la barra de desplazamiento. Las barras de desplazamiento muy delgadas — 2-3px de ancho — pueden ser casi invisibles y difíciles de agarrar con el mouse, especialmente para usuarios con discapacidades motoras. El criterio de éxito 2.5.5 de WCAG 2.1 recomienda que los objetivos interactivos sean de al menos 44×44 píxeles CSS.
Comportamiento en macOS vs Windows
macOS oculta las barras de desplazamiento de forma predeterminada y las muestra como superposición solo durante el scroll activo. Esto significa que la barra de desplazamiento no ocupa espacio de layout. En Windows, la barra de desplazamiento tradicional ocupa espacio de layout permanente junto al contenido. Esta diferencia tiene consecuencias reales para el layout. Usa scrollbar-gutter: stable para reservar espacio de layout para la barra en macOS.
Comportamiento de barras de desplazamiento en móviles
iOS Safari y Android Chrome manejan las barras de desplazamiento como superposiciones que aparecen brevemente durante el scroll y luego se desvanecen. El CSS personalizado de barras de desplazamiento no tiene esencialmente ningún efecto en móviles — la plataforma renderiza su propio indicador de scroll superpuesto independientemente de tu CSS.
Usar variables CSS para barras de desplazamiento temáticas
Una de las aplicaciones más prácticas de las barras de desplazamiento personalizadas es integrarlas en los tokens de tema de un sistema de diseño. Al usar propiedades CSS personalizadas para los colores del thumb y la pista, obtienes cambio automático entre modo oscuro y claro sin JavaScript.
¿Funcionan las barras de desplazamiento personalizadas en Firefox?
Firefox soporta las propiedades scrollbar-color y scrollbar-width desde la versión 64. No soporta los pseudo-elementos ::-webkit-scrollbar. Para cobertura de Firefox, siempre incluye ambas APIs.
¿Por qué no funciona mi estilo ::-webkit-scrollbar en mi elemento?
El elemento debe tener una barra de desplazamiento para estilizarla. Verifica que el elemento tiene overflow: auto o overflow: scroll y que el contenido realmente desborda las dimensiones del elemento.
¿Puedo usar degradados con scrollbar-color?
No — scrollbar-color solo acepta dos valores de color sólido. Los degradados son posibles solo mediante ::-webkit-scrollbar-thumb { background: linear-gradient(...) } en navegadores WebKit.
¿Qué es scrollbar-gutter y cuándo debo usarlo?
scrollbar-gutter controla si se reserva espacio de layout para la barra de desplazamiento incluso cuando no es visible. El valor stable reserva el espacio permanentemente, previniendo que el layout se desplace cuando el contenido cambia causando que aparezca o desaparezca una barra de desplazamiento.