CSS: Desplazamiento

En la navegación web, el desplazamiento (scroll) es aquella interacción que realiza el usuario para visualizar el contenido que no cabe en la ventana gráfica (viewport) del navegador. También puede ser necesario desplazarse para ver el contenido que excede los límites de su elemento contenedor pero está oculto.

Cuando el contenido no cabe en su elemento contenedor o en la ventana gráfica (viewport) del navegador web pueden aparecer las barras de desplazamiento, dependiendo de la configuración del desbordamiento.

El desplazamiento más habitual es el que se realiza de forma vertical, ya que los elementos de una página web siguen el flujo normal, pero también puede realizarse un desplazamiento en horizontal o en ambos ejes. En ordenadores se realiza con el teclado, el ratón o el panel táctil, y en los móviles con el dedo.

En CSS existe varias propiedades que permiten cambiar el desplazamiento nativo. Por ejemplo, que al saltar a un enlace ancla lo haga de forma suave (smooth scroll) en vez de saltar de forma brusca; o que el salto se produzca entre secciones o elementos (snap scroll), ideal para crear un carrusel de imágenes.

Propiedad Valor
scroll-behavior Crea un desplazamiento suave.

Propiedades para crear puntos de ajuste del desplazamiento:

Propiedad Valor
scroll-snap-type Indica la tipología de los puntos de ajuste.
scroll-snap-align Indica la posición de los puntos de ajuste.
scroll-snap-stop Indica si debe desplazarse o detenerse.

También existe una serie de propiedades CSS que se pueden usar en combinación con las anteriores. Con la propiedad scroll-margin y derivadas se puede aplicar márgenes a los elementos hijos, y con la propiedad scroll-padding y derivadas se aplica un espacio de relleno al elemento contenedor.

Desplazamiento suave (smooth scroll)

La propiedad scroll-behavior permite crear un desplazamiento suave (smooth), que se aplica al navegar en otras secciones de un mismo documento HTML, es decir, cuando se pulsa un enlace ancla. Por defecto, se produce un salto brusco, pero este comportamiento se puede cambiar para suavizar el salto.

Esta propiedad puede tener dos valores que son dos palabras clave. Con el valor auto (por defecto) se produce un salto brusco, de forma instantánea. Con el valor smooth se produce un salto suave: de forma gradual se pasa desde la posición actual hasta la posición a la que apunta el enlace ancla.

Hay que tener en cuenta que esta propiedad no afecta a otros desplazamientos que pueda realizar el usuario, ya sea usando el teclado o el ratón en el ordenador, mediante el panel táctil (touchpad) en un ordenador portátil, o desplazándose con el dedo en un dispositivo móvil.

Cuando se aplica un desplazamiento suave en el elemento raíz, como sería el elemento <html> o a la pseudoclase :root, el efecto se aplicará a toda la ventana gráfica (viewport) del navegador. Por tanto, si se aplica al elemento <body>, este efecto no se propagará a nivel general.

Vamos a ver un ejemplo en el que creamos dos secciones con un enlace en cada una. Se aplica un desplazamiento suave al elemento raíz del documento HTML y un pequeño margen superior. En este sitio ya lo utilizamos por defecto.

Código CSS:

html {
  scroll-behavior: smooth;
}

Resultado:

Sección 1

Salta a la sección 2

Al presionar el enlace se realiza un desplazamiento suave hacia la sección 2, que se encuentra justo debajo de esta sección.

Sección 2

Salta a la sección 1

Al presionar el enlace se realiza un desplazamiento suave hacia la sección 1, que se encuentra justo encima de esta sección.

Ajuste del desplazamiento (snap scroll)

Cuando el usuario se desplaza a través del contenido de una página web, ya sea utilizando el ratón, el teclado o el dedo en un dispositivo móvil, lo hace de una forma poco precisa. Esta imprecisión depende de la velocidad del desplazamiento. Si se hace de forma rápida, la posición final será menos previsible.

Imagina que el usuario se desplaza a través de una serie de imágenes, vídeos o elementos de algún tipo. Es habitual que, tras la acción del desplazamiento, solo se vea una parte del contenido y, por tanto, el usuario tendrá que volver a desplazarse de forma intuitiva un poco más despacio para ajustarlo manualmente a la ventana gráfica (viewport). De esta manera podrá verlo de forma completa.

En estos casos, lo preferible es que tras un desplazamiento, el elemento se visualice de forma completa con una simple acción del usuario, sin importar la velocidad que se use. Con CSS se puede forzar la posición final y lograr que el desplazamiento se ajuste a determinados puntos de control.

En el siguiente ejemplo se realiza un ajuste de desplazamiento a través del eje vertical. Vamos a producir un salto entre los cinco elementos hijos del contenedor.

Código CSS:

.contenedor {
  height: 102px;
  overflow-y: scroll;
  scroll-snap-type: y mandatory;
  width: 100%;
}
.item {
  background: #ff7f2a55;
  border: 1px solid #ff7f2a;
  font-size: 1.4em;
  height: 90px;
  line-height: 90px;
  margin-right: 15px;
  scroll-snap-align: center;
  text-align: center;
}

Código HTML:

<div class="contenedor">
  <div class="item">1</div>
  <div class="item">2</div>
  <div class="item">3</div>
  <div class="item">4</div>
  <div class="item">5</div>
</div>

Resultado:

1
2
3
4
5

Realiza varios movimientos de desplazamiento. Observarás que tras cada acción, los elementos hijos numerados se ajustan desde su centro al centro del contenedor, exceptuando el primero y el último que se ajustan a los bordes superior e inferior. La ventaja es que ninguno de los elementos hijos queda situado en posiciones intermedias; todos se ven completos.

Para indicar el tipo de desplazamiento, se utiliza la propiedad scroll-snap-type sobre el elemento contenedor. Luego, para definir la alineación del ajuste entre el contenedor padre y el contenido se utiliza la propiedad scroll-snap-align sobre los elementos hijos. De forma opcional puede utilizarse la propiedad scroll-snap-stop, para indicar si el ajuste debe ser obligatorio.

Vamos a ver estas tres propiedades con más detalle.

La propiedad ‘scroll-snap-type’

La propiedad scroll-snap-type permite especificar el sistema de ajuste que se debe aplicar al desplazamiento en un elemento contenedor concreto. Por ejemplo, puede aplicarse en un carrusel de imágenes e indicar que se aplique a través del eje horizontal de un modo muy estricto (obligatorio).

Esta propiedad debe utilizarse en el elemento contenedor (padre) para que se aplique sobre su contenido, como podría ser un carrusel de imágenes. Se usa en combinación con la propiedad scroll-snap-align. Su valor por defecto es none, mediante el cual no se aplicará ningún tipo de ajuste.

Lista de valores de la propiedad scroll-snap-type:

Valor Descripción
none No aplica ningún ajuste. Valor por defecto.
x Aplica ajuste solo en el eje horizontal.
y Aplica ajuste solo en el eje vertical.
block Aplica ajuste a lo largo del eje de bloque.
inline Aplica ajuste a lo largo del eje de línea.
both Aplica ajuste en los dos ejes.

Los valores de la tabla anterior pueden ir seguidos de otros dos valores opcionales que definen si la aplicación es más o menos estricta: mandatory y proximity. Cuando se usa el valor mandatory, el ajuste será obligatorio y encajará de forma exacta hasta el punto establecido. Cuando se usa el valor proximity, se ajustará al punto más cercano siempre y cuando esté lo suficientemente cerca.

Varios ejemplos de uso:

.ejemplo { scroll-snap-type: x mandatory }
.ejemplo { scroll-snap-type: y proximity}
.ejemplo { scroll-snap-type: both }
.ejemplo { scroll-snap-type: inline }

La propiedad ‘scroll-snap-align’

La propiedad scroll-snap-align permite indicar la posición del ajuste sobre los elementos hijos. Esta propiedad se utiliza en combinación con scroll-snap-type, que se usa en el elemento contenedor; deben utilizarse en conjunto.

Como resultado, cuando se termina la acción del desplazamiento, el elemento hijo en cuestión queda alineado en una parte del elemento contenedor. Por ejemplo, se puede alinear el borde lateral del elemento hijo con el borde lateral del elemento contenedor. También se puede alinear en el centro.

Esta propiedad admite uno o dos valores. Si se indica un solo valor, se aplicará tanto al eje de bloque como al eje de línea. Pero si se indica dos valores, el primero controla el eje de bloque y el segundo controla el eje de línea.

Lista de valores de la propiedad scroll-snap-align:

Valor Descripción
none Sin posición de ajuste. Valor por defecto.
start Ajusta su inicio en el inicio del contenedor.
end Ajusta su final en el final del contenedor.
center Ajusta su centro en el centro del contenedor.

A continuación se muestra varios ejemplos de uso:

.ejemplo { scroll-snap-align: none }
.ejemplo { scroll-snap-align: center }
.ejemplo { scroll-snap-align: start end }
.ejemplo { scroll-snap-align: end center }
.ejemplo { scroll-snap-align: center start }

La propiedad ‘scroll-snap-stop’

Mediante la propiedad scroll-snap-stop se indica si durante el desplazamiento se puede pasar por alto posibles posiciones de ajuste. Al igual que la propiedad anterior, también se utiliza sobre los elementos hijos.

Lista de valores de la propiedad scroll-snap-stop:

Valor Descripción
normal Puede pasar por alto posibles posiciones de ajuste.
always Debe ajustarse al punto de control establecido.

Su valor por defecto es normal, con el que el usuario se puede desplazar por un punto de control sin que el movimiento se ajuste. En cambio, si se usa el valor always, se fuerza el ajuste al pasar por un punto de control. Si solo hay una posición de ajuste, esta propiedad no produce ningún efecto.

Veamos algunos ejemplos de uso:

.ejemplo { scroll-snap-stop: normal }
.ejemplo { scroll-snap-stop: always }

Márgenes en el desplazamiento

Cuando se configura el desplazamiento, puede ser necesario añadir un margen de separación con el fin de ajustar el elemento de destino a la ventana gráfica (viewport) del navegador web o al elemento contenedor.

Por ejemplo, cuando se pulsa un enlace ancla y se produce un salto, la posición a la que apunta el enlace queda alineada en la parte superior de la ventana gráfica o del elemento contenedor. Con la propiedad scroll-margin-top podríamos indicar un margen de 20 píxeles, por lo que la posición final tras pulsar el enlace ancla estará exactamente 20 píxeles más abajo.

También puede aplicarse un margen al ajustar el desplazamiento (snap scroll). En este caso, el margen puede verse cuando finaliza el desplazamiento. En un carrusel de imágenes, podríamos indicar que tras cada ajuste de desplazamiento, cada imagen aparezca separada respecto los puntos de control. Las propiedades de márgenes se aplican a los elementos hijos.

Propiedades para añadir margen al terminar un desplazamiento:

Propiedad Valor
scroll-margin-top Indica un margen superior al desplazarse.
scroll-margin-right Indica un margen derecho al desplazarse.
scroll-margin-bottom Indica un margen inferior al desplazarse.
scroll-margin-left Indica un margen izquierdo al desplazarse.
scroll-margin Abreviatura de márgenes al desplazarse.
scroll-margin-block-end Indica un margen vertical al final.
scroll-margin-block-start Indica un margen vertical al inicio.
scroll-margin-block Abreviatura de margen en bloque.
scroll-margin-inline-end Indica un margen horizontal al final.
scroll-margin-inline-start Indica un margen horizontal al inicio.
scroll-margin-inline Abreviatura de margen en línea.

Estas propiedades tienen el 0 como valor por defecto, equivalente a un margen nulo. Admiten valores numéricos que se especifican en unidades de longitud, ya sean relativas o absolutas; por tanto, los porcentajes están permitidos.

Por su parte, la abreviatura (shorthand) scroll-margin admite de uno a cuatro valores, y se introducen de forma idéntica a la propiedad CSS margin, es decir, siguiendo el orden de las agujas del reloj.

Veamos algunos ejemplos:

.ejemplo { scroll-margin: 5px 10px }
.ejemplo { scroll-margin-top: 20px }
.ejemplo { scroll-margin-right: 1.5em }
.ejemplo { scroll-margin-bottom: 3% }

Relleno en el desplazamiento

CSS permite aplicar un espacio de relleno al terminar la transición en un ajuste de desplazamiento (snap scroll). Esta separación se encuentra entre los puntos de ajuste y los límites del elemento contenedor (padre). La utilidad de esta separación es ajustar mejor el resultado final tras el ajuste de desplazamiento.

Las propiedades de relleno se aplican sobre el elemento contenedor (padre). Para poder visualizar el resultado de estas propiedades (scroll-padding y derivadas) es necesario que se esté usando las propiedades siguientes:

  • scroll-snap-type sobre el elemento contenedor
  • scroll-snap-align sobre los elementos hijos

Propiedades para añadir relleno al terminar un desplazamiento:

Propiedad Valor
scroll-padding-top Indica un relleno superior al desplazarse.
scroll-padding-right Indica un relleno derecho al desplazarse.
scroll-padding-bottom Indica un relleno inferior al desplazarse.
scroll-padding-left Indica un relleno izquierdo al desplazarse.
scroll-padding Abreviatura de rellenos al desplazarse.
scroll-padding-block-end Indica un relleno vertical al final.
scroll-padding-block-start Indica un relleno vertical al inicio.
scroll-padding-block Abreviatura de relleno en bloque.
scroll-padding-inline-end Indica un relleno horizontal al final.
scroll-padding-inline-start Indica un relleno horizontal al inicio.
scroll-padding-inline Abreviatura de relleno en línea.

El valor por defecto de estas propiedades es auto, con el que la separación la determina el navegador web, y generalmente equivale a 0 píxeles. Como valor se puede usar números indicando las unidades de longitud.

La abreviatura (shorthand) scroll-padding también admite de uno a cuatro valores, indicados de forma idéntica a la propiedad CSS padding. Se sigue el orden de las agujas del reloj: arriba, derecha, abajo e izquierda.

Veamos algunos ejemplos:

.ejemplo { scroll-padding: 10px }
.ejemplo { scroll-padding-left: 2% }
.ejemplo { scroll-padding-right: 3em }
← Artículo anterior
Artículo siguiente →