Barras de desplazamiento

Estilar las scrollbars de una página


Una necesidad bastante común en un sitio web, es la de estilar o dar estilo a las barras de desplazamiento del navegador (o de una de las secciones o partes de la página) para que estén más acorde con el diseño del sitio, ya que las barras de progreso por defecto del sistema muchas veces no encajan con el «look and feel» del sitio web.

Para ello, tenemos una serie de propiedades interesantes que veremos a continuación, y que son las que deberían utilizarse en primer lugar.

Dar estilo a las barras de progreso

Para dar estilo a las barras de progreso tenemos las siguientes propiedades en el estándar:

Propiedad Descripción
scrollbar-color Le da color a la barra de desplazamiento. Primer parámetro a la barra y segundo al fondo.
scrollbar-width Le da un tamaño a la barra de desplazamiento. Los valores soportados son auto, thin y none.
scrollbar-gutter Reserva espacio (evita desplazamientos inesperados al mostrar/ocultar la barra).

Veamos un ejemplo de estas propiedades aplicadas a una sección de texto:

.container {
  width: 350px;
  height: 75px;
  background: #111;
  padding: 1rem;
  border: 4px solid black;
  color: #fff;
  overflow-y: scroll;

  scrollbar-color: deeppink #222;
  scrollbar-width: thin;
}
<div class="container">
  <p>Esto es un ejemplo donde va a aparecer una barra de desplazamiento, para que podamos ver como se le puede dar estilo personalizado.</p>
</div>

La propiedad scrollbar-gutter

La palabra gutter hace referencia a un «canal», espacio o hueco que se puede configurar a la hora de crear barras de desplazamiento.

Valor Descripción
auto La barra de desplazamiento ocupa un margen cuando overflow está en auto o scroll y el contenido se desborda.
stable Dicho margen también está presente cuando overflow es hidden. Ideal para evitar cambios en el diseño.
both-edges Reserva espacio también en el borde opuesto a la barra de desplazamiento. Ideal para mantener diseño simétrico.

La última opción, both-edges, realmente es un valor que se puede añadir a las anteriores para indicar esa característica.

Veamos algunos ejemplos:

.element-1 {
  scrollbar-color: deeppink indigo;
  scrollbar-width: thin;
  scrollbar-gutter: auto;
}

.element-2 {
  scrollbar-color: deeppink indigo;
  scrollbar-width: thin;
  scrollbar-gutter: stable both-edges;
}

Estilar barras de progreso (legacy)

Lo que hemos visto anteriormente es la forma oficial para estilar una barra de desplazamiento. Sin embargo, en muchas situaciones nos puede parecer insuficiente, ya que necesitamos mayor personalización.

Existen mecanismos de personalización más avanzados que explicaremos a continuación, sin embargo, el gran problema de estos mecanismos es que están desarrollados por y para el motor webkit (Safari), y por extensión blink (Chrome y Edge), pero al no ser estandares, no funcionan ni planean funcionar en servo (Firefox).

El punto bueno, es que son mucho más personalizables (y complejos) que las propiedades anteriores. Si aún así te interesa utilizarlos, veamos una explicación.

Para utilizar estos mecanismos de personalización debemos utilizar unos pseudoelementos propios de los navegadores basados en webkit o blink. Estos pseudoelementos se escriben prefijados de ::-webkit- y funcionan de una forma particular.

Cuidado al utilizar los pseudoelementos ::-webkit-, no puedes usarlos con Nesting ni unirlos a otros fragmentos de código. Deben ser individuales ya que el navegador los procesa de forma aislada.

Scrollbar con ::-webkit-scrollbar

Comencemos con el pseudoelemento ::-webkit-scrollbar, que nos permite dar estilo a la barra de desplazamiento en conjunto. Antes de comenzar, examina el código de .container y observa que estamos cambiando el tamaño del elemento e indicando un overflow-y: scroll para forzar a que haya barra de desplazamiento en el eje Y (vertical).

Una vez hecho esto, podemos utilizar nuestra pseudoclase con el elemento que queramos, o con body si queremos aplicarlo a la barra de desplazamiento global del navegador:

.container {
  width: 300px;
  max-height: 50px;
  border: 1px solid #222;
  font-size: 1.5rem;
  color: #fff;
  background: #000;
  padding: 2rem;
  overflow-y: scroll;
}

.container::-webkit-scrollbar {
  width: var(--width, 15px);
  background: indigo;
}
<div class="container">
  <p>Esto es un ejemplo donde va a aparecer una barra de desplazamiento, para que podamos ver como se le puede dar estilo personalizado.</p>
</div>

<input name="width" type="range" value="10" min="1" max="35" /><output>10px</output>
const container = document.querySelector(".container");
const inputWidth = document.querySelector("input[name=width]");

const update = (variable, input) => {
  container.style.setProperty(variable, `${input.value}px`);
  input.nextElementSibling.textContent = input.value + "px";
}

inputWidth.addEventListener("input", () => update("--width", inputWidth));

Observa que aquí lo único que hacemos es cambiar el color de fondo de la barra de desplazamiento y el tamaño de ancho de la misma. Sin embargo, no contiene nada porque aún no falta estilar las demás partes, que veremos a continuación.

El fondo con ::-webkit-scrollbar-track

Con el pseudoelemento ::-webkit-scrollbar-track podemos cambiar el fondo por donde se desplaza la barra de desplazamiento. Ten en cuenta que existe tanto un track como un track-piece, donde este último es una región más interna por donde se puede mover la barra de desplazamiento:

.container::-webkit-scrollbar-track {
  background: #444;
}

.container::-webkit-scrollbar-track-piece {
  background: #555;
}

Normalmente, con utilizar track nos basta, pero si quieres ver bien la diferencia añade un margin: 10px a cada elemento y verás rápidamente la porción que ocupa cada uno.

La barra con ::-webkit-scrollbar-thumb

Además, también tenemos el pseudoelemento ::-webkit-scrollbar-thumb que aplica estilos a la barra de desplazamiento propiamente dicha. Probablemente, es el elemento más importante de los que hemos visto:

.container::-webkit-scrollbar-thumb {
  background: yellowgreen;
}
.container::-webkit-scrollbar-thumb:hover { background: green; }
.container::-webkit-scrollbar-thumb:active { background: deeppink; }

Observa que podemos usar :hover para cambiar estilo cuando mueves el ratón por encima (o :active para cuando pulsas). Vamos a añadir el código que hemos visto hasta ahora al ejemplo inicial anterior:

.container {
  width: 300px;
  max-height: 50px;
  border: 1px solid #222;
  font-size: 1.5rem;
  color: #fff;
  background: #000;
  padding: 2rem;
  overflow-y: scroll;
}

.container::-webkit-scrollbar {
  width: var(--width, 15px);
  background: #333;
}

.container::-webkit-scrollbar-track {
  background: #444;
}

.container::-webkit-scrollbar-thumb {
  background: yellowgreen;
}

.container::-webkit-scrollbar-thumb:hover { background: lawngreen; }
.container::-webkit-scrollbar-thumb:active { background: deeppink; }
<div class="container">
  <p>Esto es un ejemplo donde va a aparecer una barra de desplazamiento, para que podamos ver como se le puede dar estilo personalizado.</p>
</div>

Si lo quisieras podrías añadir otras propiedades interesantes. Por ejemplo, un border-radius: 10px al thumb para hacer que la barra de desplazamiento esté redondeada. Recuerda que no todas las propiedades CSS funcionan en este pseudoelemento.

Los botones con ::-webkit-scrollbar-button

Observa que hasta ahora puedes mover la barra de desplazamiento tanto arrastrando el thumb como pulsando en las zonas vacías del track. Sin embargo, es posible que quieras añadir los clásico botones de desplazamiento, si te parece más intuitivo.

Esto se hace con el pseudoelemento ::-webkit-scrollbar-button, que se puede configurar bastante:

.container::-webkit-scrollbar-button {
  background: #222;
}

Si añades este fragmento de código, verás que aparecen a los extremos unos cuadraditos que son los botones de las barras de desplazamiento. Sin embargo, por defecto aparecen sin icono, ni nada en su interior. Vamos a ponerle solución.

Modificadores para los botones

Existen varios modificadores para nuestros botones, que podemos utilizar en ::-webkit-scrollbar-button:

Modificador Descripción
:single-button Aplica estilos si es una barra con botones individuales a los extremos (lo más habitual).
:double-button Aplica estilos si es una barra con botones dobles.
:no-button Aplica estilos sólo si es una barra sin botones, por lo que afecta al track-piece.
:horizontal Aplica estilos sólo si es una barra de desplazamiento horizontal.
:vertical Aplica estilos sólo si es una barra de desplazamiento vertical.
:increment Aplica estilos sólo si es un botón de incremento.
:decrement Aplica estilos sólo si es un botón de decremento.

Ten en cuenta que estos modificadores se añaden al final y son acumulables, por lo que puedes usar varios. Veamos un ejemplo donde además, utilizamos background para añadir un icono SVG para las flechas. En este caso lo hacemos con svg inline, pero se puede perfectamente hacer con un fichero externo .svg:

.container::-webkit-scrollbar-button:single-button:vertical:decrement {
  background-image: url("data:image/svg+xml;utf8,<svg viewBox='0 0 150 150' xmlns='http://www.w3.org/2000/svg' fill='white'><polygon points='50,0 0,50 100,50'/></svg>");
  background-repeat: no-repeat;
  background-position: 2px 5px;
}

.container::-webkit-scrollbar-button:single-button:vertical:decrement:hover {
  background-color: red;
}

.container::-webkit-scrollbar-button:single-button:vertical:increment {
  background-image: url("data:image/svg+xml;utf8,<svg viewBox='0 0 150 150' xmlns='http://www.w3.org/2000/svg' fill='white'><polygon points='0,0 100,0 50,50'/></svg>");
  background-repeat: no-repeat;
  background-position: 2px 6px;
}

.container::-webkit-scrollbar-button:single-button:vertical:increment:hover {
  background-color: red;
}

En lugar de :increment o :decrement también podemos utilizar :start o :end, que puede ser más intuitivo en el caso de necesitarlo.

El redimensionador con ::-webkit-resizer

En algún caso podríamos necesitar tener un redimensionador. Para ello, en el CSS del elemento se suele indicar la propiedad resize``con los valores both, horizontalovertical`. Si lo hacemos, veremos que en una esquina nos aparece un redimensionador.

.container::-webkit-resizer {
  background: green;
}

Este redimensionador se puede estilar utilizando el pseudoelemento ::-webkit-resizer. Veámoslo en funcionamiento con todo lo anterior que hemos aprendido en este artículo:

.container {
  width: 300px;
  max-height: 50px;
  border: 1px solid #222;
  font-size: 1.5rem;
  color: #fff;
  background: #000;
  padding: 2rem;
  overflow-y: scroll;
  resize: both;
}

.container::-webkit-scrollbar {
  width: var(--width, 15px);
  background: #333;
}

.container::-webkit-scrollbar-track {
  background: #444;
}

.container::-webkit-scrollbar-thumb {
  background: yellowgreen;
}

.container::-webkit-scrollbar-thumb:hover { background: lawngreen; }
.container::-webkit-scrollbar-thumb:active { background: deeppink; }

.container::-webkit-resizer {
  background: linear-gradient(-45deg, gold 50%, black 50%);
}

.container::-webkit-scrollbar-button:single-button:vertical:decrement {
  background-image: url("down.svg");
  background-repeat: no-repeat;
  background-position: 2px 5px;
}

.container::-webkit-scrollbar-button:single-button:vertical:decrement:hover {
  background-color: red;
}

.container::-webkit-scrollbar-button:single-button:vertical:increment {
  background-image: url("up.svg");
  background-repeat: no-repeat;
  background-position: 2px 6px;
}

.container::-webkit-scrollbar-button:single-button:vertical:increment:hover {
  background-color: red;
}
<div class="container">
  <p>Esto es un ejemplo donde va a aparecer una barra de desplazamiento, para que podamos ver como se le puede dar estilo personalizado.</p>
</div>

Mejora progresiva

Recuerda que las propiedades iniciales que vimos son las propiedades estándar y las que deberíamos utilizar en primer lugar. Luego, si queremos mayor personalización para los navegadores que lo soporten, podríamos añadir este mecanismo orientado a webkit o blink.

La mejor forma de realizar esto, es utilizar la regla @supports, donde podemos definir como queremos utilizarlo:

.container {
  /* Código CSS normal */
}

@supports (scrollbar-width: thin) {
  .container {
    /* Código CSS estándar de barras de desplazamiento */
  }
}

@supports selector(::-webkit-scrollbar) {
  /* Pseudoelementos de webkit */
}

¿Quién soy yo?

Soy Manz, vivo en Tenerife (España) y soy streamer partner en Twitch y profesor. Me apasiona el universo de la programación web, el diseño y desarrollo web y la tecnología en general. Aunque soy full-stack, mi pasión es el front-end, la terminal y crear cosas divertidas y locas.

Puedes encontrar más sobre mi en Manz.dev