Cómo hacer un botón de desplazamiento hacia arriba discreto »Wiki Ùtil Programar Plus

Un botón para volver a la parte superior de la página permite al usuario volver rápidamente a la parte superior de la página sin hacer demasiado esfuerzo. Esto puede ser muy útil cuando la página tiene mucho contenido o lo que sucede, por ejemplo, en sitios web de una página, cuando se usa el desplazamiento infinito o en dispositivos móviles donde diferentes tamaños de pantalla pueden hacer que el contenido se extienda.

Por lo general, esos botones flotan en la esquina inferior de los sitios y luego lo llevan de regreso a la parte superior de la página cuando se hace clic en ellos. Son bastante fáciles de crear con JavaScript. Pero visualmente, buscamos que no sea molesto y al mismo tiempo sea un objetivo lo suficientemente grande como para tocar o hacer clic. Veamos algunas formas en que podemos hacer esto, comenzando de manera simple y luego mejorando las cosas a medida que avanzamos.

Opción 1: hazlo simple

Primero, seleccionamos el botón en JavaScript.

var scrollToTopBtn = document.getElementById("scrollToTopBtn")

Ahora document.documentElement devuelve el elemento raíz del documento. Lo necesitamos para obtener los valores de compensación. Entonces, a continuación, guardémoslo en una variable llamada rootElement – de esa manera es más fácil llamar al código.

var rootElement = document.documentElement

Agregaremos un detector de eventos de clic al botón:

function scrollToTop {
  // scroll to top logic
}

scrollToTopBtn.addEventListener("click", scrollToTop)

Entonces, dentro del scrollToTop función, haremos que se desplace a la parte superior de la pantalla con el scrollTo método.

function scrollToTop() {
  // Scroll to top logic
  rootElement.scrollTo({
    top: 0,
    behavior: "smooth"
  })
}

También podemos modificar un poco el estilo del botón:

#scrollToTopBtn {
  background-color: black;
  border: none;
  border-radius: 50%;
  color: white;
  cursor: pointer;
  font-size: 16px;
  line-height: 48px;
  width: 48px;
}

Ahora podemos soltar el botón en algún lugar de la página, digamos, el pie de página:

<footer>
  <!-- Scroll to top button -->
  <button id="scrollToTopBtn">☝️</button>
</footer>

Y obtenemos esto:

Opción 2: detección de la posición de desplazamiento

Podemos detectar el desplazamiento con un detector de eventos de desplazamiento.

function handleScroll() {
  // Do something on scroll
}
document.addEventListener("scroll", handleScroll)

El handleScroll se llamará a la función cada vez que el usuario se desplace. Ahora necesitamos el número total de píxeles que podemos desplazar.

  • scrollHeight da la altura de un elemento, incluida la parte no visible debido al desbordamiento.
  • clientHeight da la altura interior de un elemento en píxeles, que es la altura de la parte visible.

Si restamos scrollHeight por clientHeight, obtenemos la cantidad total de píxeles que podemos desplazar:

var scrollTotal = rootElement.scrollHeight - rootElement.clientHeight

Ahora tenemos una variable llamada scrollTotal que representa el número máximo de píxeles que se pueden desplazar verticalmente. Al dividir la cantidad desplazada por la cantidad total de píxeles que podemos desplazar, obtenemos una proporción entre 0 y 1. Jugando con esta proporción, podemos activar y desactivar fácilmente el botón.

Por ejemplo, agregaremos una condición que muestra el botón de desplazamiento hacia la parte superior cuando el usuario se ha desplazado un 80% (o una proporción de 0,80) hacia abajo en la altura total de la página. 80% es un número arbitrario. Básicamente, cuanto más nos acercamos a 1, más tiene que desplazarse el usuario antes de ver el botón.

Aquí está el JavaScript:

var rootElement = document.documentElement


function handleScroll() {
  // Do something on scroll
  var scrollTotal = rootElement.scrollHeight - rootElement.clientHeight
  if ((rootElement.scrollTop / scrollTotal ) > 0.80 ) {
    // Show button
    scrollToTopBtn.classList.add("showBtn")
  } else {
    // Hide button
    scrollToTopBtn.classList.remove("showBtn")
  }
}


document.addEventListener("scroll", handleScroll)

Vamos a querer algo de CSS para colocar el botón correctamente cuando esté a la vista:

.scrollToTopBtn {
  /* same general styles as before */
  
  /* place it at the bottom-right corner */
  position: fixed;
  bottom: 30px;
  right: 30px;


  /* keep it at the top of everything else */
  z-index: 100;


  /* hide with opacity */
  opacity: 0;


  /* also add a translate effect */
  transform: translateY(100px);


  /* and a transition */
  transition: all .5s ease
}


.showBtn {
  opacity: 1;
  transform: translateY(0)
}

Con eso, el botón aparece cuando el usuario baja un 80% en la página y luego se oculta cuando es más alto que eso.

Esto parece una gran opción, y configurar un detector de eventos para que lo haga es bastante fácil. Pero la sobrecarga de rendimiento puede ser costosa, ya que siempre estamos comprobando la posición actual del desplazamiento.

Hay otra opción que se encarga de esto …

Opción 3: Observador de intersecciones

La API de Intersection Observer es una excelente solución al problema anterior. Es una API de navegador bastante reciente que permite a los desarrolladores entregar la mayoría de estas tareas al navegador, de una manera más optimizada. Travis Almand escribió una explicación detallada de cómo funciona. Así es como MDN lo define:

La API de Intersection Observer proporciona una forma de observar de forma asincrónica los cambios para la intersección de un elemento de destino con un elemento ancestro o con la ventana gráfica de un documento de nivel superior.

¡Con buena pinta! Eso significa que el botón puede ser nuestro elemento de destino:

// We select the element we want to target
var target = document.querySelector("footer");

Luego escribimos una función de devolución de llamada que hace algo cuando nuestro elemento se “cruza” con la ventana gráfica, que es una forma elegante de decir cuando aparece a la vista.

Y una vez que el pie de página entra o sale de la ventana gráfica, todo lo que realmente queremos hacer es agregar o eliminar una clase. La devolución de llamada recibe una matriz de entradas como parámetro.

function callback(entries, observer) {
  // The callback will return an array of entries, even if you are only observing a single item
  entries.forEach(entry => {
    if (entry.isIntersecting) {
      // Show button
      scrollToTopBtn.classList.add('showBtn')
    } else {
      // Hide button
      scrollToTopBtn.classList.remove('showBtn')
    }
  });
}

Necesitamos crear un nuevo IntersectionObserver instancia y pasarle la función de devolución de llamada que acabamos de escribir.

let observer = new IntersectionObserver(callback);

Finalmente, le decimos al observador que comience a mirar (errar, observar) el elemento de destino que se seleccionó anteriormente para cuando se cruza con la ventana gráfica:

observer.observe(target);

¿Y qué pasa con el desplazamiento suave?

¡Por supuesto que es posible! De hecho, Chris nos mostró cómo se puede hacer con CSS en 2019:

<html id="top">
  <body>
     <!-- the entire document -->
     <a href="https://css-tricks.com/how-to-make-an-unobtrusive-scroll-to-top-button/#top">Jump to top of page</a>
  </body>
</html>
html {
  scroll-behavior: smooth;
}

Hay un poco más de matices, como mejoras de accesibilidad que Chris también cubre en la publicación. El punto es que CSS está adquiriendo nuevos poderes que pueden lograr cosas para las que solíamos usar JavaScript.

¡Ahí tienes! Empezamos con una idea bastante sencilla. Lo mejoramos mostrando y ocultando el botón según la posición de desplazamiento del usuario. Luego, mejoramos el rendimiento implementando la API de Intersection Observer en lugar de observar la posición de desplazamiento actual. Y, finalmente, vimos cómo se puede usar CSS para un desplazamiento suave. En conjunto, obtenemos un botón de desplazamiento hacia la parte superior que es fácil de ver y usar, sin bloquear otros elementos de la página.