1. Web Design
  2. Parallax Scrolling

Create a Unique Scrolling Website With Locomotive Scroll & Tailwind CSS

Scroll to top
Read Time: 14 min

Have you ever wanted to build a unique single-page scrolling website but weren’t sure where to start? If so, don’t worry! Today we’re going to build just such a website using Locomotive Scroll, a small and easy-to-use JavaScript library for cool scrolling effects.

Plus, to speed up the development process (and to create a responsive layout with minimal effort) we’ll put Tailwind CSS into play.

This tutorial has been updated to include some extra functionality—check out the added Case Study sections and watch them change color as they smooth scroll into view!

What We’re Building

As usual, before moving on, let’s examine the final result (scroll—or perhaps even better, view the demo on a large screen—and check the effects):

What is Locomotive Scroll?

Locomotive Scroll is one of the many JavaScript scrolling libraries that exist today. You might have already used some other ones in your projects, like ScrollTrigger.js and ScrollMagic.js. In actual fact, I covered a ScrollMagic example in a previous tutorial.

locomotive scroll v4locomotive scroll v4locomotive scroll v4

Here’s its definition as used on the Locomotive Scroll site:

“A simple scroll library used by developers at Locomotive. Built as a layer on top of ayamflow’s virtual-scroll, it provides smooth scrolling with support for parallax effects, toggling classes, and triggering event listeners when elements are in the viewport.”

Are you curious enough to explore the capabilities of this library? Let’s begin!

Getting Started With Locomotive Scroll

To get started with Locomotive Scroll, you have to include the following files in your project:

  • The locomotive-scroll.css file or its minified version
  • The locomotive-scroll.js file or its minified version

You can download them by visiting its GitHub repo, using a package manager (e.g. npm), or loading the necessary assets through a CDN (e.g. jsDelivr). For this tutorial, we’ll choose the last option.

As discussed in the introduction, for this demonstration, beyond the Locomotive files, we’ll also incorporate Tailwind CSS to create the page layout.

With that in mind, if you look under the Settings tab of our demo pen, you’ll see that there are two external CSS files and one external JavaScript file.

The required CSS filesThe required CSS filesThe required CSS files
The required JavaScript fileThe required JavaScript fileThe required JavaScript file

1. Structuring the Page

Locomotive Scroll comes with several different data attributes for manipulating the elements. We’ll use a lot of them, so at the end of this tutorial you’ll have a good grasp of what they do and how you can use them.

Let’s start by specifying a wrapper element with the data-scroll-container attribute. Inside it we’ll place the page sections and a back-to-top link. Later on, we’ll initialize the plugin by targeting this wrapper.

All page sections will have the data-scroll-section attribute. Plus, almost all of them will have an id attribute. This attribute will help us smoothly navigate to target sections through the menu and back-to-top links.

Here’s the initial page structure:

At this point, we’re ready to have a closer look at the important page sections.

Section #1

The first section will include a heading and a paragraph.

The layout of the first sectionThe layout of the first sectionThe layout of the first section

Another important thing here: by default, the back-to-top link won’t appear. As we scroll:

  • If the heading is in view, the link will be/remain invisible.
  • It will appear only when the heading isn’t in view.
The back-to-top link

To implement this functionality, we’ll pass the data-scroll, data-scroll-repeat, and data-scroll-call="toggleBackToTop" attributes to the heading. Let’s now discuss a little further the role of these attributes:

  • The job of the data-scroll attribute is to check if the element is in view. As soon as it appears for the first time, the plugin will add the is-inview class to it. This class won’t be removed any more. Notice also how the plugin modifies the element’s CSS transform property to apply the different effects.
The is-inview class added by Locomotive ScrollThe is-inview class added by Locomotive ScrollThe is-inview class added by Locomotive Scroll
  • The job of the data-scroll-repeat attribute is to check repeatedly if the element is in view. The plugin will toggle the is-inview class depending on the element’s position. In our case, we’ll use this attribute only in pair with the data-scroll-call attribute that needs it to work properly.
  • The job of the data-scroll-call attribute is to trigger Locomotive’s call event. The attribute value that can be anything we want is passed as a parameter to the event callback and allows us to do stuff when the target element enters or leaves the viewport. It’s a bit hard to explain it with words, so it’s better that you see the JavaScript code. We’ll work with it again in the upcoming sections. As said, remember that we’ll use it together with the data-scroll-repeat attribute.

Here’s how we structure this section:

Section #2

The second section will include the menu links.

The layout of the second sectionThe layout of the second sectionThe layout of the second section

To navigate smoothly to page sections upon clicking a link, we have to give the data-scroll-to attribute to the links.

Note: we’ll pass the same attribute to the back-to-top link.

Keep in mind that this attribute isn’t part of the docs at the time of this writing. If you’re wondering how I know about its existence, the answer is that I found it by checking the source code of the plugin’s GitHub Page.

The required data-scroll-to attribute for smooth scrolling  The required data-scroll-to attribute for smooth scrolling  The required data-scroll-to attribute for smooth scrolling

Alternatively, if you don’t want to use this attribute, you can achieve this functionality using some JavaScript scrolling methods.

Here’s how we structure this section:

Section #3

The third section will include a heading and some text.

The layout of the third sectionThe layout of the third sectionThe layout of the third section

As we scroll, we’ll pin the heading to the top. But, for how long? Well, until we scroll past its parent. At that point, the element will disappear as it will then be part of the normal document flow.

To implement this functionality, we’ll assign the data-scroll, data-scroll-sticky, and data-scroll-target="#about" attributes to the heading. Some notes:

  • As we already know, the data-scroll attribute will detect if our element is in view.
  • The data-scroll-sticky attribute will make it sticky in pair with the data-scroll-target attribute.
  • The value of the data-scroll-target attribute will determine the element’s initial and final sticky positions.
The sticky durationThe sticky durationThe sticky duration
We’ll follow the same technique in the seventh (clients) section, so we’ll skip that one.

Here’s how we structure this section:

Section #4

The fourth section will include two Unsplash images.

The layout of the fourth sectionThe layout of the fourth sectionThe layout of the fourth section

As we scroll, a parallax effect will happen. To be more specific, the first image will move four times faster than the second one.

To implement this functionality, we’ll pass the data-scroll and data-scroll-speed attributes to the images. The value of the second attribute will determine their scrolling speed. Here we’ll give data-scroll-speed="4.8" to the first image and data-scroll-speed="1.2" to the second one.

Here’s how we structure this section:

Section #5

The fifth section will include a heading and two text banners explaining our services.

The layout of the fifth sectionThe layout of the fifth sectionThe layout of the fifth section

As we scroll, multiple parallax effects will take place:

  • First, the heading’s letters will move at different speeds. Plus, each time they come into view, they will receive a random color from a list of predefined colors.
  • Second, the banners will move horizontally in different directions.

To implement this functionality, we’ll do the following:

  • Assign the data-scoll, data-scroll-repeat, data-scroll-speed, and data-scroll-call="randomizeTextColor" attributes to the heading’s letters. As we want a parallax effect, the value of the data-scroll-speed attribute will vary for each letter. Remember the role of the data-scroll-call attribute. Here we’re saying: as the letters enter the viewport and Locomotive’s call event fires, do something. If you check the JavaScript section, you’ll notice that at this point the getRandomColor() function is firing. Optionally, here we can also put into action the data-scroll-delay attribute.
  • Assign the data-scroll, data-scroll-direction="horizontal", data-scroll-speed, and data-scroll-target="#services" attributes to the banners. The data-scroll-direction="horizontal" will move the elements horizontally on scroll. Next, by giving them opposite values for the data-scroll-speed attribute, we ensure that they will move in different directions (from left to right or right to left). Finally, the data-scroll-target="#services" attribute will determine when the horizontal animations should start. To understand it, try to put the id of another section e.g. data-scroll-target="#office" and reload the page. Notice that the animations start much sooner than they should be.

Here’s how we structure this section:

Section #6

The sixth section will include three featured case studies. Each case study will consist of a heading, an image, and a link to the case study’s inner page.

One of the case studiesOne of the case studiesOne of the case studies

As we scroll, each time a case study’s heading (name) comes into view, the background color of the body element will change based on the value of the data-bg attribute of the associated section.

The background color that is added when the section's heading comes into viewThe background color that is added when the section's heading comes into viewThe background color that is added when the section's heading comes into view

To implement this functionality, we could again use the call event, which is probably a more efficient approach. But, let's, this time, take advantage of another event that the library provides, the scroll one. Check the Javascript code for greater detail on how we handle this event.

Regarding the custom attributes:

  • We'll give the data-bg-color attribute to each section with the desired color value.
  • We’ll add the data-scroll and data-scroll-repeat attributes to the headings so this functionality is repeated as we scroll. Note that we can customize the time that the library toggles the is-inview class via the data-scroll-offset attribute. 

Here’s how we structure this section:

If you need the body color to change based on the section's visibility and not on the heading's visibility, remove the data-scroll and data-scroll-repeat attributes from the headings, and add them to the sections. Also, make the adjustments needed on the JavaScript code.

Also, you don't have to stop only on the body color. Depending on your layout, you can change the text color of each section, add animations, etc.

Section #8

The eighth section will include a call-to-action heading.

The layout of the seventh sectionThe layout of the seventh sectionThe layout of the seventh section

As we scroll, two things will happen:

  • First, each time the heading comes into view, it will receive a random color, like the previous example.
  • Second, we’ll animate each letter by creating another parallax (lerp) effect.

To implement this functionality, we’ll do the following:

  • Assign the data-scoll, data-scroll-repeat, and data-scroll-call="randomizeTextColor" attributes to the heading. Remember that we’ve already met the data-scroll-call="randomizeTextColor" attribute. It’s perfectly fine to use it here as well.
  • Assign the data-scroll, data-scroll-delay, and data-scroll-speed="5" attributes to each letter. All letters will move five times faster than normal scrolling, yet with different delays. For example, the first letter will have data-scroll-delay="0.15" while the second one data-scroll-delay="0.095". This will create the lerp/staggering effect. Again you can see lerp effects in the plugin’s showcase example.

Here’s how we structure this section:

2. Initializing the Plugin

We’ve talked about many of the plugin’s features, yet we haven’t initialized it. Let’s do that now.

Here’s all the required JavaScript code:

Some quick notes:

  • We’ll keep its smooth behavior across all devices.
  • Notice the parameters of the call event callback. The first one (i.e. value) holds the values of the data-scroll-call attributes. Using an if condition, we check to see which values are active each time, then whether the associated elements enter or leave the viewport, and finally, we perform the desired actions.
  • Although not used in our case, the callback of the scroll event accepts one parameter that provides useful info. For example, how much have we scrolled and which elements are currently in view. Use your browser console to see the output of this parameter.

Conclusion

Congrats, folks! We managed to build a parallax scrolling website thanks to Locomotive Scroll. Hopefully, this exercise has revealed the power of this tiny library and motivated you to start creating advanced scrolling effects effortlessly.

Here’s a reminder of what we built:

Don’t forget to give it some love ❤️!

Before closing, let me leave you with a few thoughts:

  • As with every technology/tool/library, the best way to learn Locomotive Scroll is through its docs. Go ahead, check the published example and use your browser tools to inspect its source code. Also, check its GitHub repo for issues, how active the project is, how other people use the library, or just for taking some ideas. If you feel more adventurous, check the plugin’s native code. Here you’ll learn things like what parameters a function (e.g. the callback of the call event) can accept, etc.
  • Scrolling effects can decrease a website’s performance. Besides this fact, the more complex the effects, the more risk there is they will encounter issues across different browsers/devices. For example, on mobile devices I would avoid using the horizontal animations we covered.
  • For even more powerful locomotive scroll effects, you can combine Locomotive Scroll with other animation libraries like GSAP and barba.js.

Have you ever used Locomotive Scroll and Tailwind to build a smooth scrolling website? What other plugins have you tried in that direction?

Last but not least, a big thanks to Locomotive developers for this plugin! As always, thanks a lot for reading, and be sure to share with us your Locomotive projects!

Keep on Scrolling

Check out these other tutorials to learn more about JavaScript and scrolling:

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Web Design tutorials. Never miss out on learning about the next big thing.
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.