Creating a Scroll-Locked Page

In this tutorial, we'll be creating a Wix page where you can set specific "anchors" where your user's screen will jump to as they navigate, just like this page.

First time using Corvid? Click here for a quick intro guide.

Our first step is to create a strip page. For our code example, we'll be using four strips 700 pixels tall although you can add as many as you'd like!

In this demo, each strip has a text element with tutorial content. You can replace this text element with a box, image, button, or whatever you'd like but go ahead and add one of these per strip, as we'll be implementing them in the code. Center them for now, so you can get a clear idea of what's going on. You can, of course, change their position after the tutorial.

Once you've added one per strip,  name them according to their index. I.E.:

#textOne, #textTwo, #textThree, #textFour

Now that our page is set up, let's start coding.

 

First, we'll create our event listeners. For #textOne through #textFour, activate onViewportEnter in their respective properties panel. If you don't know what this means, refer to the quick intro guide.

Next up, delete everything in the code panel (yes, everything), as we'll be replacing it with the following:

 

Here, we import the wix-window API, set up our page's onReady, and write our event listeners:

import wixWindow from 'wix-window';

$w.onReady(function() {

    $w('#textOne').onViewportEnter();

    $w('#textTwo).onViewportEnter();

    $w('#textThree').onViewportEnter();

    $w('#textFour').onViewportEnter();

});

For now, these listeners are just listening without doing anything. We'll fix that later.

To tell the page to stick to our "anchors", we'll be using the following function:

let prevLoc = 1;

const locker =  function(loc) {

    wixWindow.getBoundingRect().then((vpInfo) => {

    });

}

Our function is called locker, it grabs viewport information (vpInfo) from the wix-window module, and it contains two variables. The prevLoc variable will store the user's previous location on the page, and the loc variable represents their current location.

We need three specific details about the user's viewport: their current x and y scroll positions, and the height of their viewport. So let's go ahead and define those as well:

let prevLoc = 1;

const locker =  function(loc) {

    wixWindow.getBoundingRect().then((vpInfo) => {

        const currY = vpInfo.scroll.y,

            currX = vpInfo.scroll.x,

            high = vpInfo.window.height; 

    });

}

When our user is scrolling up, we want the page to automatically take them to the previous strip, and when they scroll down, we want them to be taken to the next. The code will decide to scroll down if loc is greater than prevLoc, or else scroll up if loc is less than or equal to prevLoc:

if (loc > prevLoc) { } else { }

 

For maximum consistency, simplicity, and control in our code, we'll use the y scroll position to determine the coordinates the page will scroll to:

if (currY < 700) { } else if (currY < 1400) { } else if (currY < 2100) { }

Keep in mind the strips in this demo are each 700px tall, which is why our currY values are set at 1*700, 2*700, 3*700.

One last condition. If the user's viewport is tall enough, there's a chance that they will always have at least two of our designated elements on screen. If that happens, the code will take them to either the bottom or top of the page, which we don't want. Some solutions to this are larger layout, altering scroll values, using event listeners on smaller items, etc. Whatever your choice, insert it in the following else condition:

if (high < 1300) { } else { }

Lastly, let's make sure to set our loc and prevLoc values strategically. We pass the loc variable each time we trigger the locker function, and we set prevLoc after the window has scrolled. Our final code:

import wixWindow from 'wix-window';

$w.onReady(function() {

    if (wixWindow.formFactor === 'Desktop') {

    $w('#textOne').onViewportEnter(() => { locker(1); });

    $w('#textThree').onViewportEnter(() => { locker(3); });

    $w('#textFour').onViewportEnter(() => { locker(4); });

    }

    let prevLoc = 1;

    const locker =  function(loc) {

        wixWindow.getBoundingRect().then((vpInfo) => {

            const currY = vpInfo.scroll.y,

                currX = vpInfo.scroll.x,

                high = vpInfo.window.height;

                if (high < 1300) {

                    if (loc > prevLoc) {

                        if (currY < 700) {

                            wixWindow.scrollTo(currX, 760);

                        } else if (currY < 1400) {

                            wixWindow.scrollTo(currX, 1460);

                        } else if (currY < 2100) {

                            wixWindow.scrollTo(currX, 2160);

                        }

                    } else {

                        if (currY < 700) {

                            wixWindow.scrollTo(currX, 0);

                        } else if (currY < 1400) {

                            wixWindow.scrollTo(currX, 760);

                        } else if (currY < 2100) {

                            wixWindow.scrollTo(currX, 1460);

                        }

                    }

                } else {

                    //anything here happens on taller monitors

                }

                prevLoc = loc;

        });

    }

});

This code is highly dependent on the size of our strip and header height, but it makes it easier to conceptualize what is going on so that you can play around with it yourself. For a more abstract, plug-and-play code, use the one on the following strip. It's also limited here to desktop users, as using this on a touch device would likely just be annoying.

import wixWindow from 'wix-window';

const headerHeight = 000,    //replace 000 with your exact header height

    stripHeight = 000;    //replace 000 with your exact strip height

$w.onReady(function() {

    $w('#textOne').onViewportEnter(() => { locker(1); });

    $w('#textTwo).onViewportEnter(() => { locker(2); });

    $w('#textThree').onViewportEnter(() => { locker(3); });

    $w('#textFour').onViewportEnter(() => { locker(4); });

    let prevLoc = 1;

    const locker =  function(loc) {

        wixWindow.getBoundingRect().then((vpInfo) => {

            const currY = vpInfo.scroll.y,

                currX = vpInfo.scroll.x,

                high = vpInfo.window.height;

                if (high < stripHeight * 2 - 100) {

                    if (loc > prevLoc) {

                        if (currY < stripHeight) {

                            wixWindow.scrollTo(currX, stripHeight + headerHeight);

                        } else if (currY < stripHeight * 2) {

                            wixWindow.scrollTo(currX, stripHeight * 2+ headerHeight);

                        } else if (currY < stripHeight * 3) {

                            wixWindow.scrollTo(currX, stripHeight * 3 + headerHeight);

                        }

                    } else {

                        if (currY < stripHeight) {

                            wixWindow.scrollTo(currX, 0);

                        } else if (currY < stripHeight * 2) {

                            wixWindow.scrollTo(currX, stripHeight + headerHeight);

                        } else if (currY < stripHeight * 3) {

                            wixWindow.scrollTo(currX, stripHeight * 2 + headerHeight);

                        }

                    }

                } else {

                    //anything here happens on taller monitors

                }

                prevLoc = loc;

        });

    }

});