Crea un sitio web con desplazamiento único con Locomotive Scroll y Tailwind CSS
Spanish (Español) translation by Carlos (you can also view the original English article)
¿Alguna vez has querido crear un sitio web de una sola página con un desplazamiento único pero no sabías por dónde empezar? Si es así, ¡no te preocupes! Hoy vamos a crearlo juntos. Para lograr esto, aprovecharemos Locomotive Scroll, una biblioteca de JavaScript para crear efectos de desplazamiento geniales, es pequeña y fácil de usar.
Además, para acelerar el proceso de desarrollo (y crear un diseño responsivo con un esfuerzo mínimo) haremos uso de Tailwind CSS.
Lo que vamos a crear
Como siempre, antes de continuar, examinemos el resultado final (desplázate o, mejor aún, mira la demostración en una pantalla grande y revisa los efectos):
¿Qué es Locomotive Scroll?
Locomotive Scroll es una de las muchas bibliotecas de desplazamiento de JavaScript que existen actualmente. Quizá ya hayas utilizado algunas otras en tus proyectos, como ScrollTrigger.js y ScrollMagic.js. De hecho, traté un ejemplo con ScrollMagic en un tutorial anterior.
Esta es la definición que aparece en el sitio de Locomotive Scroll:
«Una biblioteca de desplazamiento simple que usan los desarrolladores en Locomotive. Creada como una capa sobre virtual-scroll de ayamflow, brinda un desplazamiento suave con soporte para efectos de paralaje, alternancia de clases y activación de event listeners cuando los elementos están en la ventana gráfica».
¿Tienes curiosidad por explorar las capacidades de esta biblioteca? ¡Comencemos!
Empezar con Locomotive Scroll
Para empezar con Locomotive Scroll, tienes que incluir los siguientes archivos en tu proyecto:
- El archivo
locomotive-scroll.css
o su versión minimizada - El archivo
locomotive-scroll.js
o su versión minimizada
Puedes descargarlos visitando su repositorio en GitHub, usando un administrador de paquetes (por ejemplo, npm) o cargando los recursos necesarios mediante un CDN (por ejemplo, jsDelivr). Para este tutorial, elegiremos la última opción.
Como se mencionó en la introducción, para esta demostración, además de los archivos de Locomotive, también incorporaremos Tailwind CSS para crear el diseño de la página.
Teniendo eso presente, si miras en la pestaña Settings (Configuraciones) de nuestro pen de demostración, verás que hay dos archivos CSS externos y un archivo JavaScript externo.






1. Estructurar la página
Locomotive Scroll viene con varios atributos data
distintos para manipular los elementos. Utilizaremos muchos de ellos, por lo que al final de este tutorial tendrás un buen conocimiento de lo que hacen y cómo puedes usarlos.
Empecemos especificando un elemento contenedor con el atributo data-scroll-container
. Dentro de él, colocaremos las secciones de la página y un enlace para regresar a la parte superior. Más tarde, inicializaremos el plugin dirigiéndonos a este contenedor.
Todas las secciones de la página tendrán el atributo data-scroll-section
. Además, casi todos tendrán un atributo id
. Este atributo nos ayudará a navegar con suavidad a las diferentes secciones mediante el menú y el enlace de regreso a la parte superior.
Esta es la estructura de la página inicial:
<div data-scroll-container> <section id="intro" class="h-screen flex items-center justify-center text-center bg-green-200" data-scroll-section>...</section> <section class="py-40" data-scroll-section>...</section> <section id="about-section" class="py-40 bg-green-50" data-scroll-section>...</section> <section id="office" class="py-20" data-scroll-section>...</section> <section id="services" class="relative py-60 bg-green-50" data-scroll-section>...</section> <section id="clients-section" class="py-40" data-scroll-section>...</section> <section id="contact" class="py-80 border-t-2 border-solid border-gray-50" data-scroll-section>...</section> <section class="h-screen flex items-center justify-center text-center bg-green-200" data-scroll-section>...</section> <a class="back-to-top fixed bottom-24 right-4 text-red-500 hover:text-red-600 focus:text-red-600 transition opacity-0 invisible" href="#intro" role="button" aria-label="Back to top" data-scroll-to> <svg aria-hidden="true" xmlns="https://www.w3.org/2000/svg" width="40" height="40" viewBox="0 0 24 24"> <path d="M12 0c-6.627 0-12 5.373-12 12s5.373 12 12 12 12-5.373 12-12-5.373-12-12-12zm0 7.58l5.995 5.988-1.416 1.414-4.579-4.574-4.59 4.574-1.416-1.414 6.006-5.988z" /> </svg> </a> </div>
En este punto, estamos listos para examinar más detalladamente las secciones importantes de la página.
Sección #1
La primera sección incluirá un encabezado y un párrafo.



Otra cosa importante aquí: de manera predeterminada, el enlace de regreso a la parte superior no aparecerá. A medida que nos desplacemos:
- Si el encabezado está a la vista, el enlace será/permanecerá invisible.
- Aparecerá únicamente cuando el encabezado no esté a la vista.

Para implementar esta funcionalidad, pasaremos los atributos data-scroll
, data-scroll-repe
at y data-scroll-call="toggleBackToTop"
al encabezado. Ahora examinemos un poco más la función de estos atributos:
El trabajo del atributo data-scroll
es comprobar si el elemento está a la vista. Tan pronto como aparezca por primera vez, el plugin le añadirá la clase is-inview
. Esta clase ya no se eliminará. Observa también cómo el plugin modifica la propiedad transform
de CSS del elemento para aplicar los diferentes efectos.



El trabajo del atributo data-scroll-repeat
es comprobar repetidamente si el elemento está a la vista. El plugin alternará la clase is-inview
dependiendo de la posición del elemento. En nuestro caso, utilizaremos este atributo únicamente en combinación con el atributo data-scroll-call
que lo necesita para funcionar correctamente.
El trabajo del atributo data-scroll-call
es activar el evento call
de Locomotive. El valor del atributo, que puede ser cualquier cosa que queramos, se pasa como un parámetro al callback del evento y nos permite hacer cosas cuando el elemento objetivo entra o sale de la ventana gráfica. Es un poco difícil explicarlo con palabras, por lo que es mejor que veas el código JavaScript. Trabajaremos con él de nuevo en las próximas secciones. Como se dijo, recuerda que lo utiizaremos junto con el atributo data-scroll-repeat
.
Así es como estructuramos esta sección:
<section id="intro" class="h-screen flex items-center justify-center text-center bg-green-200" data-scroll-section> <div class="container px-5 mx-auto"> <h1 class="text-5xl font-bold" data-scroll data-scroll-repeat data-scroll-call="toggleBackToTop">A Simple Demo With <a class="underline" href="https://locomotivemtl.github.io/locomotive-scroll/" target="_blank">Locomotive Scroll</a></h1> <p class="text-2xl mt-2">Scroll down 👇</p> </div> </section>
Sección #22
La segunda sección incluirá los enlaces del menú..



Para navegar con suavidad a las secciones de la página al hacer clic en un enlace, tenemos que proporcionar el atributo data-scroll-to
a los enlaces..
Nota: Pasaremos el mismo atributo al enlace de regreso a la parte superior..
Ten presente que este atributo no forma parte de los documentos al momento de redactar este artículo. Si te preguntas cómo sé sobre su existencia, la respuesta es que lo encontré al revisar el código fuente de la página de GitHub del plugin..



Como alternativa, si no quieres usar este atributo, puedes lograr esta funcionalidad utilizando algunos métodos de desplazamiento de JavaScript..
Así es como estructuramos esta sección::
<section class="py-40" data-scroll-section> <div class="container px-5 mx-auto"> <nav> <ul class="grid md:grid-flow-col gap-8 lg:gap-16 justify-center text-center"> <li> <a class="inline-block text-2xl font-medium px-4 py-2 border-4 border-double border-transparent hover:border-green-400 focus:border-green-400 rounded-md transition" href="#about-section" data-scroll-to> About </a> </li> <li> <a class="inline-block text-2xl font-medium px-4 py-2 border-4 border-double border-transparent hover:border-green-400 focus:border-green-400 rounded-md transition" href="#office" data-scroll-to> Office </a> </li> ... </ul> </nav> </div> </section>
Sección #33
La tercera sección incluirá un encabezado y algo de texto..



A medida que nos desplacemos, fijaremos el título en la parte superior. ¿Pero por cuánto tiempo? Bueno, hasta desplazarnos más allá de su parent. En ese punto, el elemento desaparecerá, ya que será parte del flujo normal del documento..
Para implementar esta funcionalidad, asignaremos los atributos data-scroll
, data-scroll-sticky
y data-scroll-target="#about"
al encabezado. Algunas notas::
- Como ya sabemos, el atributo
data-scroll
detectará si nuestro elemento está a la vista.. - El atributo
data-scroll-sticky
lo hará «pegajoso» junto con el atributodata-scroll-target
.. - El valor del atributo
data-scroll-target
determinará las posiciones pegajosas inicial y final del elemento..



Así es como estructuramos esta sección::
<section id="about-section" class="py-40 bg-green-50" data-scroll-section> <div class="container px-5 mx-auto"> <div id="about" class="lg:grid grid-cols-2 gap-4 items-start"> <h2 class="text-5xl font-extrabold" data-scroll data-scroll-sticky data-scroll-target="#about">About</h2> <div class="text-xl pt-4 lg:pt-0">...</div> </div> </div> </section>
Sección #44
La cuarta sección incluirá dos imágenes de Unsplash..



A medida que nos desplacemos, se producirá un efecto de paralaje. Para ser más específicos, la primera imagen se moverá cuatro veces más rápido que la segunda..
Para implementar esta funcionalidad, pasaremos los atributos data-scroll
y data-scroll-speed
a las imágenes. El valor del segundo atributo determinará su velocidad de desplazamiento. Aquí le asignaremos data-scroll-speed="4.8"
a la primera imagen y data-scroll-speed="1.2"
a la segunda..
Así es como estructuramos esta sección::
<section id="office" class="py-20" data-scroll-section> <div class="sm:grid grid-cols-2 gap-40"> <figure class="flex items-end"> <img class="shadow-lg h-auto" width="1000" height="667" src="office1.jpg" alt="" data-scroll data-scroll-speed="4.8"> </figure> <figure> <img class="shadow-lg h-auto" width="1000" height="1498" src="office2.jpg" alt="" data-scroll data-scroll-speed="1.2"> </figure> </div> </section>
Sección #55
La quinta sección contendrá un encabezado y dos banners de texto explicando nuestros servicios..



A medida que nos desplazamos, se producirán varios efectos de paralaje::
- Primero, las letras del encabezado se moverán a diferentes velocidades. Además, cada vez que aparezcan, recibirán un color aleatorio de una lista de colores predefinidos..
- En segundo lugar, los banners se moverán de forma horizontal en diferentes direcciones..
Para implementar esta funcionalidad, haremos lo siguiente::
Asignaremos los atributos data-scoll
, data-scroll-repeat
, data-scroll-speed
y data-scroll-call="randomizeTextColor"
a las letras del encabezado. Como queremos un efecto de paralaje, el valor del atributo data-scroll-speed
variará para cada letra. Recuerda la función del atributo data-scroll-call
. Aquí estamos diciendo: cuando las letras ingresen a la ventana gráfica y se active el evento call
de Locomotive, haz algo. Si revisas la sección de JavaScript, notarás que en este punto se activa la función getRandomColor()
. De manera opcional, aquí también podemos poner en acción el atributo data-scroll-delay
..
También asignaremos los atributos data-scroll
, data-scroll-direction="horizontal"
, data-scroll-speed
y data-scroll-target="#services"
a los banners. El atributo data-scroll-direction="horizontal"
moverá los elementos de forma horizontal durante el desplazamiento. Luego, al dar valores opuestos a los atributos data-scroll-speed
, nos aseguramos de que se moverán en diferentes direcciones (de izquierda a derecha o de derecha a izquierda). Por último, el atributo data-scroll-target="#services"
determinará cuándo deben empezar las animaciones horizontales. Para entenderlo, trata de poner la id
de otra sección, por ejemplo data-scroll-target="#office"
y recarga la página. Observa que las animaciones empiezan mucho antes de lo que deberían..
Así es como estructuramos esta sección::
<section id="services" class="relative py-60 bg-green-50" data-scroll-section> <h2 class="absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 -skew-x-12 whitespace-nowrap text-6xl sm:text-9xl font-extrabold py-4"> <span class="inline-block" data-scroll data-scroll-repeat data-scroll-speed="3" data-scroll-call="randomizeTextColor">S</span> <span class="inline-block" data-scroll data-scroll-repeat data-scroll-speed="2" data-scroll-call="randomizeTextColor">e</span> <span class="inline-block" data-scroll data-scroll-repeat data-scroll-speed="3" data-scroll-call="randomizeTextColor">r</span> <span class="inline-block" data-scroll data-scroll-repeat data-scroll-speed="2" data-scroll-call="randomizeTextColor">v</span> <span class="inline-block" data-scroll data-scroll-repeat data-scroll-speed="3" data-scroll-call="randomizeTextColor">i</span> <span class="inline-block" data-scroll data-scroll-repeat data-scroll-speed="2" data-scroll-call="randomizeTextColor">c</span> <span class="inline-block" data-scroll data-scroll-repeat data-scroll-speed="3" data-scroll-call="randomizeTextColor">e</span> <span class="inline-block" data-scroll data-scroll-repeat data-scroll-speed="2" data-scroll-call="randomizeTextColor">s</span> </h2> <div class="transform rotate-6 skew-x-12"> <div data-scroll data-scroll-direction="horizontal" data-scroll-speed="20" data-scroll-target="#services"> <span class="text-3xl sm:text-4xl md:text-6xl 2xl:text-7xl bg-green-400 p-5 whitespace-nowrap">Social Media — Email Marketing — Digital Advertising</span> </div> </div> <div class="transform -rotate-6 -skew-x-12 mt-40"> <div data-scroll data-scroll-direction="horizontal" data-scroll-speed="-20" data-scroll-target="#services"> <span class="text-3xl sm:text-4xl md:text-6xl 2xl:text-7xl bg-green-400 p-5 whitespace-nowrap">Web Development - Motion Design - Graphic Design</span> </div> </div> </section>
Sección #77
La séptima sección incluirá un encabezado de llamada a la acción..



A medida que nos desplacemos, ocurrirán dos cosas::
- En primer lugar, cada vez que se vea el encabezado, recibirá un color aleatorio, como en el ejemplo anterior..
- En segundo lugar, animaremos cada letra creando otro efecto de paralaje (lerp)..
Para implementar esta funcionalidad, haremos lo siguiente::
Asignaremos los atributos data-scoll
, data-scroll-repeat
y data-scroll-call="randomizeTextColor"
al encabezado. Recuerda que ya conocemos el atributo data-scroll-call="randomizeTextColor"
. Está bien utilizarlo aquí también..
Y asignaremos los atributos data-scroll
, data-scroll-delay
y data-scroll-speed="5"
a cada letra. Todas las letras se moverán cinco veces más rápido que el desplazamiento normal, pero con distintos retrasos. Por ejemplo, la primera letra tendrá data-scroll-delay="0.15"
mientras que la segunda tendrá data-scroll-delay="0.095"
. Esto creará el efecto lerp/staggering. Nuevamente, puedes ver los efectos lerp en el ejemplo del plugin..
Así es como estructuramos esta sección::
<section id="contact" class="py-80 border-t-2 border-solid border-gray-50" data-scroll-section> <div class="container px-5 mx-auto text-center"> <h2 class="text-2xl sm:text-5xl font-extrabold py-4" data-scroll data-scroll-repeat data-scroll-call="randomizeTextColor"> <span class="inline-block" data-scroll data-scroll-delay="0.15" data-scroll-speed="5">h</span> <span class="inline-block" data-scroll data-scroll-delay="0.095" data-scroll-speed="5">e</span> <span class="inline-block" data-scroll data-scroll-delay="0.085" data-scroll-speed="5">l</span> <span class="inline-block" data-scroll data-scroll-delay="0.075" data-scroll-speed="5">l</span> <span class="inline-block" data-scroll data-scroll-delay="0.065" data-scroll-speed="5">o</span> <span class="inline-block" data-scroll data-scroll-delay="0.055" data-scroll-speed="5">@</span> <span class="inline-block" data-scroll data-scroll-delay="0.045" data-scroll-speed="5">g</span> <span class="inline-block" data-scroll data-scroll-delay="0.035" data-scroll-speed="5">e</span> <span class="inline-block" data-scroll data-scroll-delay="0.035" data-scroll-speed="5">o</span> <span class="inline-block" data-scroll data-scroll-delay="0.045" data-scroll-speed="5">r</span> <span class="inline-block" data-scroll data-scroll-delay="0.055" data-scroll-speed="5">g</span> <span class="inline-block" data-scroll data-scroll-delay="0.065" data-scroll-speed="5">e</span> <span class="inline-block" data-scroll data-scroll-delay="0.075" data-scroll-speed="5">.</span> <span class="inline-block" data-scroll data-scroll-delay="0.085" data-scroll-speed="5">c</span> <span class="inline-block" data-scroll data-scroll-delay="0.095" data-scroll-speed="5">o</span> <span class="inline-block" data-scroll data-scroll-delay="0.15" data-scroll-speed="5">m</span> </h2> </div> </section>
2. Inicialización del pluginn
Hemos hablado de muchas de las funciones del plugin, pero no lo hemos inicializado. Hagámoslo ahora..
Aquí está todo el código JavaScript que se requiere::
const backToTop = document.querySelector(".back-to-top"); const opacityClass = "opacity-0"; const visibilityClass = "invisible"; const scroll = new LocomotiveScroll({ el: document.querySelector("[data-scroll-container]"), smooth: true, tablet: { smooth: true }, smartphone: { smooth: true } }); const arrayOfColors = [ "#0a9396", "#005f73", "#ae2012", "#3d405b", "#003049", "#bc6c25", "#ff006e", "#ef476f", "#1982c4", "#ee964b", "#0ead69", "#390099", "#f6aa1c", "#54101d", "#2b2c28", "#85c7f2", "#e15a97", "#2b70e3", "#b36a5e" ]; function getRandomColor() { const arrayLength = arrayOfColors.length; const randomValue = Math.random() * arrayLength; const roundedNumber = Math.floor(randomValue); const color = arrayOfColors[roundedNumber]; return color; } scroll.on("call", (value, way, obj) => { if (value === "randomizeTextColor") { if (way === "enter") { obj.el.style.color = getRandomColor(); } } else if (value === "toggleBackToTop") { if (way === "enter") { backToTop.classList.add(opacityClass, visibilityClass); } else { backToTop.classList.remove(opacityClass, visibilityClass); } } });
Algunas notas rápidas::
- Mantendremos su comportamiento fluido en todos los dispositivos..
- Observa los parámetros de callback del evento
call
. El primero (es decir,value
) contiene los valores de los atributosdata-scroll-call
. Al usar una condiciónif
, verificamos qué valores están activos en cada ocasión, luego si los elementos asociados entran o salen de la ventana gráfica y, por último, realizamos las acciones deseadas..
Conclusiónn
¡Felicidades, amigos! Logramos crear un sitio web con desplazamiento de paralaje gracias a Locomotive Scroll. Esperemos que este ejercicio haya mostrado el poder de esta pequeña biblioteca y que los haya motivado a crear efectos de desplazamiento avanzados con facilidad..
Este es un recordatorio de lo que hemos creado::
¡No te olvides de darle un poco de amor ❤️!
Antes de concluir, permíteme dejarte algunas reflexiones: :
- Al igual que con todas las tecnologías/herramientas/ bibliotecas, la mejor forma de aprender Locomotive Scroll es a través de sus documentos. Revisa el ejemplo publicado y utiliza las herramientas de tu navegador para inspeccionar su código fuente. Asimismo, consulta su repositorio en GitHub para ver posibles problemas, lo activo que es el proyecto, cómo utilizan la biblioteca otras personas o simplemente para tomar algunas ideas. Si te sientes más aventurero, revisa el código nativo del plugin. Aquí aprenderá cosas como qué parámetros puede aceptar una función (por ejemplo, el callback del evento
call
), etc.. - Los efectos de desplazamiento pueden reducir el rendimiento de un sitio web. Además de este hecho, cuanto más complejos sean los efectos, mayor será el riesgo de que se produzcan problemas en diferentes navegadores/dispositivos. Por ejemplo, en dispositivos móviles yo evitaría utilizar las animaciones horizontales que tratamos..
- Para efectos aún más avanzados, puedes combinar Locomotive Scroll con otras bibliotecas de animación como GSAP y barba.js..
Por último, pero no por ello menos importante, ¡muchas gracias a los desarrolladores de Locomotive por este plugin! Como siempre, muchas gracias por leer y ¡asegúrate de compartir con nosotros tus proyectos con Locomotive!!
Sigue desplazándoteg
Revisa estos otros tutoriales para aprender más sobre JavaScript y desplazamiento::
- Eventos de desplazamientosCómo animar durante el desplazamiento con JavaScript purotJemima Abuu
- JavaScripttCómo crear una barra de progreso de lectura con CSS y JavaScripttAdi Purdilaa
- CSSSCSS Scroll Snap: ¿Qué es? ¿Se necesita??Dennis Gaebell
- HTMLConsejo rápido: cómo crear un efecto de desvanecimiento simple durante el desplazamientolGeorge Martsoukoss