Ways to "halt" an element once reaching a different element while scrolling

I'm attempting to recreate the interactive widget titled "Engage. Involve. Connect" found on this webpage: . The concept involves the widget remaining fixed at the bottom of the page until the user scrolls, at which point it dynamically positions itself just above the text that reads "Experiences shape us."

Currently, I am developing a similar widget for my site located at . However, I am encountering challenges in ensuring the #widget / #unanchored element stops scrolling once it reaches the ".xp" class, contained within the "Experiences shape us." section.

This is the JavaScript code I am working with:

window.addEventListener('scroll', function() {
  var widget = document.getElementById('widget');
  var xpElement = document.querySelector('.xp');
  var widgetHeight = widget.offsetHeight;
  var xpPosition = xpElement.getBoundingClientRect().top;
  var windowHeight = window.innerHeight;

  var distance = xpPosition - windowHeight + widgetHeight;

  if (distance <= 0) {
    // Un-anchor and scroll with content
    widget.classList.add('unanchored');
  } else {
    // Keep anchored
    widget.classList.remove('unanchored');
  }
  
  // Dynamically set height of .xp element
  xpElement.style.setProperty('--xp-height', widgetHeight + 'px');
});

Here is the corresponding HTML:

<h3 id="widget" class="wp-block-heading has-text-align-center frontpage ticss-f97cde6b has-white-color has-text-color has-background" style="background-color:#00000087;font-size:39px">Engage. &nbsp; Involve. &nbsp; Connect.<br><span class="text frontpage2" style="font-weight: 200 !important;">We fuse Art + Engineering to create world-class experiences.</span><br><a href="https://williamh117.sg-host.com/#spacestop"><i class="arrow down"></i></a></h3>

And here is the CSS:

.unanchored {
  position: fixed !important;
  bottom: 300px !important;
  top: calc(100% - var(--widget-height) - 30px);
  left: 0 !important;
    margin-bottom:0px !important;
}

.xp {
  --widget-height: 30px;
  position: relative;
}

#widget {
  position: fixed;
  bottom: 0;
  left: 0;
  background-color: #f0f0f0;
  width: 100%;
  text-align: center;
  transition: bottom 0.3s ease-in-out;
    z-index:1000 !important;
    scroll-behavior: smooth !important;
}

Your advice and assistance are greatly appreciated. Thank you!

Answer №1

If you're looking for a similar function, you can find it here: CodePen example

<!DOCTYPE html>
<html lang="en">
    <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
    .banner {
        width: 100%;
        height: 100vh; /* Note */
        background-color: #098;
    }
    .widget {
        position: relative; /* Note */
        z-index: 9;
        top: -200px; /* Widget Height */
        width: 100%;
        height: 200px;
        background-color: #0005;

        display: grid;
        place-content: center;
        color: #fff;
    }
    .content {
        position: relative; /* Note */
        margin-top: -200px; /* Widget Height */
        width: 100%;
        height: 1000px;
        background-color: #000;
        padding-top: 200px;
        color: #fff;
    }
    </style>
</head>
<body>
    <section class="banner"></section>
    <section class="widget">
        <h2>Widget Content</h2>
    </section>
    <section class="content">
        <div class="children">
            <h1>This is Title</h1>
        </div>
    </section>

    <script>
        function map_range(value, input1Start, input1End, input2Start, input2End) {
            const normalizedValue = (value - input1Start) / (input1End - input1Start);
            return input2Start + normalizedValue * (input2End - input2Start);
        }
        window.addEventListener('scroll', function() {
            const wantedHeightToEnd = window.innerHeight * 0.5; // want to end animation at middle of the screen
            if (window.scrollY < wantedHeightToEnd) {
                const value = map_range(window.scrollY, 0, wantedHeightToEnd, -200 /* Widget Height */, 0);
                document.querySelector(".widget").style.top = value + px;
            }
        });
    </script>
</body>
</html>

Keep in mind that the banner, widget, and following section are on the same level.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What are the steps to achieve a smooth transition from a background-image to transparency?

Take a look at this related image: The goal is to replicate the design shown on the right side of the image. However, there's also a parent container with its own background image, as opposed to a solid color. Any guidance on how to achieve this? U ...

How to Call a Nested Object in JavaScript Dynamically?

var myObj = { bar_foo : "test", bar : { foo : "hi there"; }, foo : { bar : { foo: "and here we go!" } } } How can we achieve the following: var arr = [["bar", "foo"], ...

Dealing with Inline Styling Woes

Trying to style a row of buttons on the left, a center-aligned navigation list, and another row of buttons on the right. The navigation buttons are grouped to account for layout changes. How can I horizontally center the navigation within the parent elemen ...

Updating the Backbone.js model within a MySQL database

I am facing an issue with my model setup: var Car = Backbone.Model.extend({ url: "/save.php", defaults: { color: "red" } }); Upon document ready, I initialize a new instance of the model and save it: new volvo = new Car({color:"gree ...

An issue was encountered while trying to access ./node_modules/@esri/calcite-components/dist/custom-elements/index.mjs from 1:0-147

After including dist/custom-elements/index.mjs": "dist/custom-elements/index.js in my package.json file, I encountered the following error message. Is there something I missed? { "name": "@map/react-app", "private&quo ...

The table's content extends beyond the confines of the page

I have an HTML page where I am embedding an SSRS report. The report extends beyond the page as shown in the image below: This is the table that is generated: <table cellpadding="0" cellspacing="0" id="ctl00_MainContent_FiveYearReportViewer_fixedTable" ...

Converting text to icons and adding tooltips using only CSS

I am faced with the challenge of transforming a hyperlink into an icon while converting the text content into a tooltip using only CSS and without the ability to modify the HTML or add JavaScript. Data is being extracted from an external source in the form ...

In need of styling text using CSS?

Despite setting the CSS to .text { word-wrap : break-word; max-width: 100px}, the text is not wrapping as expected. It is still displaying in a single line. I am anticipating that the large text should wrap onto the next lines. ...

Issue with modal box not displaying properly when hidden div is within a for loop

In my project, I have a MySQL select statement that retrieves all the results to be displayed in an unordered list (<ul>) using a for loop. This functionality works perfectly. However, I wanted to add a "click more" link at the bottom of each result ...

Guide on installing React packages during runtime

My React project has a number of packages that need to be installed, but they take up a lot of disk space. I would like to install them only when necessary, after the user interacts with a specific component that requires these packages. Is there a way t ...

Preview your uploaded image before finalizing

I am currently working on implementing a new upload feature for users of our forum. This feature will allow them to upload a personal picture. Here is what I have developed so far: HTML <label>Profile image</label> <div class="phot ...

toggle between utilizing the page object API and the primary Nightwatch API

Currently, I am incorporating the page object model alongside nightwatch for my testing procedures. Encountering challenges while trying to interact with an element led me to execute some jquery. However, the 'execute' command is not featured in ...

JavaScript: Collection of Pictures

I've recently begun my journey into HTML and JavaScript by working on a basic website that showcases four images using a for loop. However, upon viewing the website in a browser, I noticed that only the names of the images are displayed, not the actua ...

Encountering an 'Undefined' error when trying to access data object values within the map function in a

// I keep encountering undefined values when trying to access object values from my data map // ../data/section1 const products = [{ id: 1, image: './images/homepage/xbox-games.png', text: 'Buy Xbox games and consoles', }, ...

Whenever I try to import a directory that contains modules, Webpack encounters an error

I am currently in the process of developing a small npm library to streamline API interaction. Here is an overview of my folder structure... dist/ index.js src/ index.js endpoints/ endpoint1.js package.json webpack.config.js Inside my src/index ...

Is there a way to update the Angular component tag after it has been rendered?

Imagine we have a component in Angular with the selector "grid". @Component({ selector: 'grid', template: '<div>This is a grid.</div>', styleUrls: ['./grid.component.scss'] }) Now, when we include this gri ...

Can you explain the significance of `window.jqueryFoo = false;`?

I came across this code snippet within a React component: export default class pageWithModal extends React.Component { constructor(props) { super(props); window.jqueryFoo = false; this.state = { modal: false, value: '&apo ...

I am experiencing an issue with my jQuery loop code not functioning properly when using the .each method within the loop

I am struggling with the following code. <input type="text" name="1" class = "inp<?=$p?>"> <input type="text" name="2" class = "inp<?=$p?>"> <input type="text" name="3" class = "inp<?=$p?>"> <input type="text" na ...

Tips for updating the styleurls link dynamically by clicking a button and maintaining the changes

In the midst of developing an angular 2 project, I am currently working on integrating theme settings. Within my project, I have crafted three distinct component.scss files: red.component.scss, yellow.component.scss, and blue.component.scss. My goal is t ...

JavaScript Fullcalendar script - converting the names of months and days

I recently integrated the Fullcalendar script into my website (https://fullcalendar.io/). Most of the features are functioning correctly, however, I am seeking to translate the English names of months and days of the week. Within the downloaded package, ...