Using Locomotive Scroll together with the Angular framework can be tricky. This is especially true when working with multiple routes inside an Angular application. The goal of this tutorial is to outline a possible solution for using Locomotive Scroll in combination with the Angular framework. Therefore a multi route Angular application capable of smooth scrolling will be implemented.
Note: for this tutorial Angular version 11 and Locomotive Scroll version 4.1.0 are used.
First a new instance of an Angular Application is needed. To get this done initialize a new Angular application with routing by running following command in your console.
ng new locomotive-angular
Follow the instructions of the CLI to add routing and SCSS as a style preprocessor to the project. This will initialize an empty angular project, building the foundation for further steps. Next, jump into the project directory by running „cd locomotive-angular“ in your console and run „npm install“ to get the required dependencies. These steps will complete the initial setup for this tutorial.
Add Routing and Content
To enable navigation, multiple components and routing is needed. To do so, create two components („page-a“ and „page-b“) by using the Angular CLI. The following command initializes the boilerplate for the two components:
ng g c page-ang g c page-b
Running the command „ng serve -o“ will compile the application and open it in your default browser on port 4200. For now a fresh instance of Angular, including its boilerplate shall be shown.
Once checked that the application is compiled successfully, up and running jump into app.compoennt.html and remove all the default markup in this file. Replace the boilerplate with a simple navigation element and a router outlet. The following code outlines the markup for app.component.html.
Next add some dummy content to the components „page-a“ and „page-b“. Make sure there is plenty of content, so it overflows the window height and is scrollable. For this tutorial Samuel L. Jackson quotes provided by https://slipsum.com and kitten image provided by https://placekitten.com are used as dummy content.
To finalize the setup routing in between the components has to be added. To do so the following code has to be added to the app-routing.module.ts file.
These steps shall add routing to the application. For now the two components implements native scrolling behavior due to their content height. In the next step Locomotive Scroll is added, so smooth scrolling in the Angular application is enabled.
Adding Locomotive Scroll
As outlined on Locomotive Scrolls GitHub Page (https://github.com/locomotivemtl/locomotive-scroll) running the following command will add Locomotive Scroll to the project and save the dependency in the projects package.json file.
npm install locomotive-scroll -s
To make use of Locomotive Scroll throughout the application the scroll controller will be initialized in the app.component.ts file. To do so the following steps are required:
- Import Locomotive Scroll by adding this import statement:
import LocomotiveScroll from ‘locomotive-scroll’;
- Add a class variable called „scroll“ above the constructor
- Initialize Locomotive Scroll in the ngOnInit live-cycle hook
- Set the element selector to document.querySelector(‚[data-scroll-container]’)
- Enable smooth scrolling by setting Locomotive Scrolls setting smooth to true
After these steps the app.component.ts file should looks like this:
When initializing Locomotive Scroll it will looks for its scroll container. This is defined by document.querySelector(‚[data-scroll-container]’) on line 17 and implies, that Locomotive Scroll will use the element with the data-scroll-container attribute as its main element. Therefore wrap the markup outlined in the app.component.html file into a div and assign the data-scroll-container attribute to it. After this step the app.component.html file should look like this:
Next adding Locomotive Scroll’s styles to the application is required. To do so add the following import statement the style.scss file.
When reloading the page you can notice, that the scrolling behavior of the application changed. However, the scrolling behavior is somehow wicked. Depending on the added contents length, the page might be cut off, an offset on top of the page is added or the window height does not match the content height. Further more, no scrolling capability might be a result of this step. This behavior can get even worse when lazy loading content or changing elements on the fly. In the next section the solution to this problem is outlined.
Updating Locomotive Scroll on content change
When resizing the browser window, Locomotive Scrolls update function is triggered. In this function Locomotive Scroll checks the height of the scroll-container and sets its internal parameters acordingly. You can check this by resizing the browser window manually. After doing so, the application shall behave as expected and smooth scrolling shall work like a charm.
Following this approach Locomotive Scrolls needs to be updated whenever the height of its scroll container changes. To do this automatically the “resize-observer” library is used. The repository to this library can be found here: https://github.com/juggle/resize-observer. As outlined in the repository’s readme, the resize observer is added to the project by running the following code in your console:
npm i @juggle/resize-observer -s
After installing the dependency the resize event has to be hooked up to Locomotive Scrolls update function. To do so open the projects app.component.ts file and proceed with the following steps:
- Import ResizeObserver in the top section of the file.
- Add a view child called scrollContent and link it to the router outlets wrapper.
- Initialize a new RezieObserver inside the ngAfterViewInit livecycle hook and use it to observe the scrollContent element reference.
After these changes the projects app.component.ts file should look like this:
Do not forget to add a local variable to the router outlets wrapper in the app.component.html file. The following snippet shows the local variable on the outlets wrapper.
After this these steps your application shall be capable of smooth scrolling. You can now fine-tune the application with various parameters. A good starting-point is Locomotive Scrolls documentation, especially the instance options part: https://github.com/locomotivemtl/locomotive-scroll#instance-options.
In some cases it might be useful to set the scroll-container to position: fixed and place it manually to top: 0 and left: 0. This method can be used to overcome cut off parts at the bottom of the page.
You can find the complete codebase for this tutorial on GitHub by following this link: https://github.com/FloLech/locomotive-angular-tutorial
Besides smooth scrolling, Locomotive Scroll offers other useful scrolling operations like element in viewport detection, parallax animation and sticky elements. In case you liked this tutorial and are interested in future readings about Locomotive Scroll and Angular please leave a comment and hit the clap button.