Programming Vue.js Fullpage Scroll

Programming Vue.js Fullpage Scroll

With Fullpage Scroll, normal scrolling is deactivated and you are always scrolled exactly into the next section. Here you can learn step by step how to program this feature yourself with Vue.js.

Table of contents


To make it clear right from the start what the result will look like, I’ve already prepared a demo here. This version is supported by all common browsers and also works on mobile devices.

However, there is a small problem in the Microsoft Edge Browser (successor of IE): The pure Smooth Scroll is not supported here. The scrolling is a bit jerky, but all functions are still usable. Thus we have created a nice workaround.

If you’re still looking for design inspirations, I have two more pages here that have, in my opinion, set the full page scroll extremely well in scene:

Fullpage Scroll Frameworks

I know there are already some really good Vue.js fullpage scroll frameworks out there, like this one. However, it’s much cooler to program it yourself. And you don’t have so many “unnecessary” functions on your site that you don’t need.

If you’re not a friend of Vue.js, you can do the same with ReactAngularJS or jQuery. The procedure is mostly similar. Individual functions can of course be adapted to the frameworks.

HTML Structure

First we need a container in which our Vue.js App runs. Therefore we create a container #app. There the rest of the HTML comes in.

<div id="app">
    <!-- CONTENT HERE -->

Next, we create our individual sections. There you can then pack in and design any content you like.

<section class="fullpage">
    <h1>Section 1</h1>
<section class="fullpage">
    <h1>Section 2</h1>
<section class="fullpage">
    <h1>Section 3</h1>
<section class="fullpage">
    <h1>Section 4</h1>

In the next step we want to create the side menu. This allows you to navigate to another section by clicking on it and the active section is always displayed.

<div class="sections-menu">
     v-bind:class="{active: activeSection == index}"
     v-for="(offset, index) in offsets"

To this block it now needs some explanation: To make the menu we make a wrapper .sections-menu. In it is a span tag which contains some attributes for Vue.js. So here is the exact explanation:


In order for the effect of the full page scroll to come into its own, the individual sections should be at least 100vh (i.e. exactly screen height). So you have to see that the content of a section is adjusted to exactly this height.

.fullpage {
  height: 100vh;
  width: 100%;

In our example, we only have a heading and subheading. For inspiration take a look at the demoslinked above.


I also kept the navigation menu as simple as possible. White points, where the active point is stronger and bigger. In addition, the menu is always on the right side of the screen. The CSS looks like this:

.sections-menu {
  position: fixed;
  right: 1rem;
  top: 50%;
  transform: translateY(-50%);

.sections-menu .menu-point { width: 10px; height: 10px; background-color: #FFF; display: block; margin: 1rem 0; opacity: .6; transition: .4s ease all; }

.sections-menu { opacity: 1; transform: scale(1.5); }

CSS for positioning the font, etc. I did not discuss here, because they are basics and have nothing to do with the actual feature. You can find the complete code on my pen on Codepen.

Vue.js (JavaScript)

The JavaScript has been the most elaborate thing here. We have to cover all modern browsers as well as mobile devices.

Initialize Vue.js App

We start initializing the Vue.js App. We have already created the #app container in the HTML.

var app = new Vue({
  el: '#app',

Declaring and Initializing Variables

Now we declare and initialize the variables. Later it becomes clear which variable we need, if the name doesn’t already tell us.

data: {
    inMove: false,
    activeSection: 0,
    offsets: [],
    touchStartY: 0

Calculate offsets

Now we want to calculate the offsets (upper edge of the sections) of the individual sections. This gives us the advantage that we save computing power, because we don’t have to recalculate it every time we scroll.

We run a loop over all section elements and store the offset in our global offsets array.

calculateSectionOffsets() {
    let sections = document.getElementsByTagName('section');
    let length = sections.length;

for (let i = 0; i &lt; length; i++) {
    let sectionOffset = sections[i].offsetTop;


The function is called once when creating the application in the created() function.

created() {

Event Listener

We need some event listeners to intercept the scroll movement for desktop and swipe on mobile devices. We register these listeners in the created() function.

window.addEventListener('DOMMouseScroll', this.handleMouseWheelDOM); // Mozilla Firefox
window.addEventListener('mousewheel', this.handleMouseWheel, {
    passive: false
}); // Other browsers

window.addEventListener('touchstart', this.touchStart, { passive: false }); // mobile devices window.addEventListener('touchmove', this.touchMove, { passive: false }); // mobile devices

We also remove the event listeners when quitting the application in the destroy() function.

destroyed() {
    window.removeEventListener('mousewheel', this.handleMouseWheel, {
        passive: false
    }); // Other browsers
    window.removeEventListener('DOMMouseScroll', this.handleMouseWheelDOM); // Mozilla Firefox

window.removeEventListener('touchstart', this.touchStart); // mobile devices
window.removeEventListener('touchmove', this.touchMove); // mobile devices


As you can see from the comments, there are different events for different browsers. For some browsers the parameter passive: false is given. This parameter has to be inserted.

I tried a lot of scrolling until it worked smoothly. I could only get the result with this parameter. In addition, error messages were displayed in the browser console.

Scroll Function

This function is already called by our HTML links. Herewith we scroll to the section. The parameter id is the Section ID. The variable inMove makes sure that we have a small cooldown. This means that we can only scroll every 400ms (0.4s). With the parameter force set to true we can skip the cooldown.

scrollToSection(id, force = false) {
    if (this.inMove && !force) return false;

this.activeSection = id;
this.inMove = true;

    behavior: 'smooth'

setTimeout(() =&gt; {
    this.inMove = false;
}, 400);


Recognize Scroll Direction

The handleMouseWheel function is the event listener of the scroll event on desktop devices (mousewheel DOMMouseScroll).

Via the variable wheelDelta of the event we can see if the user scrolls up or down. Accordingly, our moveUp() or moveDown() function is called, which is created in the next step. At the end, e.preventDefault() and return false; abort the event.

handleMouseWheel: function(e) {

if (e.wheelDelta &lt; 30 &amp;&amp; !this.inMove) {
} else if (e.wheelDelta &gt; 30 &amp;&amp; !this.inMove) {

return false;


Scroll section up and down

These two functions are only responsible for scrolling up or down once. If we scroll down and the section is smaller than 0, we scroll to the last section. On the other hand, if the new section is larger than the number of sections, we scroll to the first section. 0 is the first section.

moveDown() {
    this.inMove = true;

if (this.activeSection &lt; 0) this.activeSection = this.offsets.length - 1;

this.scrollToSection(this.activeSection, true);

}, moveUp() { this.inMove = true; this.activeSection++;

if (this.activeSection &gt; this.offsets.length - 1) this.activeSection = 0;

this.scrollToSection(this.activeSection, true);


With this we have created an endless scroll. If you don’t want to do this, you simply can’t do a Swipe, so the user can only scroll in the other direction at the ends.

Detect Mobile Swipe

We have the touchstart and touchmove events on the move, through which we can see where the user is scrolling. When the user starts scrolling, touchStart() is called. There we store the Y position. When the user then moves his finger on the display, touchMove() is called.

We then compare these two values and see whether the user scrolls up or down. Accordingly, our moveUp() or moveDown() function, which we created earlier, is called.

touchStart(e) {

this.touchStartY = e.touches[0].clientY;

}, touchMove(e) { if (this.inMove) return false; e.preventDefault();

const currentY = e.touches[0].clientY;

if (this.touchStartY &lt; currentY) {
} else {

this.touchStartY = 0;
return false;



As you can see, you can add your own features or remove parts if you don’t like them. Fullpage Scroll is a very chic feature and when used properly you can create very nice results. Some inspirations you already got to know during the demos.

You can find the complete code on my pen on Codepen.

If you have suggestions for improvement or feedback, please feel free to add them to your comments! 

Originally published  at on 3. June 2019


Thanks for reading :heart: If you liked this post, share it with all of your programming buddies! Follow me on Facebook | Twitter

Learn More

☞ Nuxt.js - Vue.js on Steroids

☞ Vue JS 2 - The Complete Guide (incl. Vue Router & Vuex)

☞ Master Vuejs from scratch (incl Vuex, Vue Router)

☞ Vue JS 2.0 - Mastering Web Apps

☞ Vue.js Essentials - 3 Course Bundle

☞ MEVP Stack Vue JS 2 Course: MySQL + Express.js + Vue.js +PHP

☞ The Complete JavaScript Course 2019: Build Real Projects!

☞ JavaScript: Understanding the Weird Parts

☞ The Modern JavaScript Bootcamp (2019)

vue-js javascript web-development

Bootstrap 5 Complete Course with Examples

Bootstrap 5 Tutorial - Bootstrap 5 Crash Course for Beginners

Nest.JS Tutorial for Beginners

Hello Vue 3: A First Look at Vue 3 and the Composition API

Building a simple Applications with Vue 3

Deno Crash Course: Explore Deno and Create a full REST API with Deno

How to Build a Real-time Chat App with Deno and WebSockets

Convert HTML to Markdown Online

HTML entity encoder decoder Online

Top Vue.js Developers in USA

Vue.js is an extensively popular JavaScript framework with which you can create powerful as well as interactive interfaces. Vue.js is the best framework when it comes to building a single web and mobile apps.

Hire Web Developer

Looking for an attractive & user-friendly web developer?, a leading web, and mobile app development company, offers web developers for hire through flexible engagement models. You can **[Hire Web...

Hire Node.JS Developers | Skenix Infotech

We are providing robust Node.JS Development Services with expert Node.js Developers. Get affordable Node.JS Web Development services from Skenix Infotech.