JS DOM: Floating Box Following Scroll

By Xah Lee. Date: . Last updated: .
πŸ’›

Scroll the page down and you'll see a item that follows your window scrolling, so that it is always visible.

How It Works

The moving box is just a HTML element, like this:

<div id="float215">πŸ’›</div>

Setup CSS to make the box on its own layer. γ€”see CSS: Position Absolute〕

#float215 {
 position: absolute;
 top: 200px;
 right: 20px;
 z-index: 2;
 width: 100px;
 font-size: 3rem;
}

To move the box, we need to:

  1. Set up a scroll event, so that when user scroll, a function f is called.
  2. f computes the distance of the box to window's vertical center, and move the box closer if it is not already there. (moving is done by changing its position in the top value in CSS.)
  3. The function f then calls itself again, until the box is in the center.

Here is the JavaScript code:

"use strict";
/*
box following scroll
change position of id float215

created 2010-03-10
version 2025-04-23
Copyright 2025 by Xah Lee
http://xahlee.info/js/moving_block.html
license: permission is granted for using the code, but this license section must remain intact.

 */
{
    // number of pixels of the widget should be from top of the window
    const OffsetFromTop = Math.floor(window.innerHeight / 2);
    // milisecond. The smaller the value, smooth the animation.
    const UpdateFrequency = 50;
    // the closing-in factor. Smaller makes it smoother.
    const ChaseFactor = .05;
    const xfloatbox = document.getElementById("float215");
    xfloatbox.style.position = "absolute";
    xfloatbox.style.zIndex = "296";
    xfloatbox.style.top = OffsetFromTop.toString() + "px";
    let ymovto = 0;
    let ydiff = 0;
    const fMoveIt = () => {
        // distance user has scrolled
        ydiff = ymovto - window.pageYOffset;
        if (Math.abs(ydiff) > 9) {
            // turn off now, prevent event repeat firing when user kept scrolling
            window.removeEventListener("scroll", fMoveIt);
            ymovto -= ydiff * ChaseFactor;
            xfloatbox.style.top = (ymovto + OffsetFromTop).toString() + "px";
            setTimeout(fMoveIt, UpdateFrequency); // calls itself again
        }
        else {
            window.addEventListener("scroll", fMoveIt, false); // turn back on
        }
    };
    window.addEventListener("scroll", fMoveIt, false);
}
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.