Can JavaScript trigger scrolling events to smoothly fade elements into view?

I am endeavoring to fix some divs in place and create a fading effect as they appear and disappear while a user scrolls down. This is what my code looks like so far:

$(window).on("load",function() {
    var fadeDuration = 500;
    function fade() {
    // calculate current window boundaries
    var windowTop = $(window).scrollTop(),
        windowBottom = windowTop + $(window).innerHeight(),
        focusElt = null;

    // locate the focus element, which is the first visible .copy element,
    // using a short-circuiting loop
    $('.imgdiv').toArray().some(function(e, i) {
        var objectTop = $(e).offset().top;
        if ((objectTop >= windowTop) && (objectTop <= windowBottom)) {
            focusElt = e;
            return true;
        }
            console.log(focusElt);

    });

    // hide all other elements
    $('.focus').not(focusElt)
        .removeClass('focus')
        .fadeTo(fadeDuration, 0);

    // focus on our focus element; if it was the previous focus, leave it;
    // but if it wasn't previously focused / shown, make
    // it visible and assign the class 'focus'
    $(focusElt).not('.focus')
        .addClass('focus')
        .fadeTo(fadeDuration, 1);

}
fade(); // Ensure completely visible elements are faded during page load
$(window).scroll(function() {fade();}); // Fade in elements during scroll

});

Here's a link to the corresponding fiddle that almost achieves what I'm aiming for. However, instead of the green "Fade In" blocks moving upwards and fading, I want them to stay fixed near the top of the window. As the "IMG DIVs" move past them, they should fade in and out with each new "IMG DIV". Currently, I'm focusing on the specific green block and fading it when it becomes the focus element. Instead, I need to focus on the IMG DIV blocks, add a "pinned" class to the green blocks when they reach the top of the page, and control the fading in and out of the green blocks.

Does anyone have any insights or suggestions?

As a follow-up question, I am also curious about how to achieve this using native JavaScript without relying on jQuery's dependencies.

Answer №1

Alright, let's break down your initial problem into two separate issues :)

Firstly, the main objective is to trigger certain actions when an element becomes visible within the viewport and also when it goes out of view. So, essentially, what you need is a function like this:

watchElementVisibility(
    $('.imgdiv'),
   executeActionWhenElementEntersViewport,
    executeActionWhenElementLeavesViewport
);

Once the element is in view, you may want to display another related element; similarly, when it goes out of sight, you might want to hide that corresponding element. Hence, define these two functions accordingly:

function executeActionWhenElementEntersViewport(element) {
    // retrieve text associated with the element
    var $copy = $(element).next('.copy');

    // fade it in
    $copy.fadeTo(500, 1);
}

function executeActionWhenElementLeavesViewport(element) {
    // retrieve text connected to the element
    var $copy = $(element).next('.copy');

    // fade it out
    $copy.fadeTo(500, 0);
}

Now, what about watchElementVisibility? It's not complicated; it simply encapsulates the logic you've already laid out but separated from element manipulation.

function watchElementVisibility($elements, elementEnteredViewport, elementLeftViewport) {
    var currentlyVisible = [ ];    
    // fetch positions once, assuming they won't change during script execution
    var positions = getVerticalBoundaries($elements);

    function _scrollHandler() {
        var viewportTop = window.scrollY;
        var viewportBottom = viewportTop + window.innerHeight;

        $elements.each(function(index, element) {
            var elementPosition = positions[index];
           
            var elementInViewport = (elementPosition.top < viewportBottom) && (elementPosition.bottom > viewportTop);
            var elementIndexInCurrentlyVisible = currentlyVisible.indexOf(element);

            // if element is now visible but wasn't before
            if(elementInViewport && (elementIndexInCurrentlyVisible === -1)) {
                elementEnteredViewport(element);

                currentlyVisible.push(element);
              
            // if element is no longer visible but was before
            } else if(!elementInViewport && (elementIndexInCurrentlyVisible !== -1)) {
                elementLeftViewport(element);

                currentlyVisible.splice(elementIndexInCurrentlyVisible, 1);
            }
        });
    }

    // check initially and update
    _scrollHandler();

    // perform check and update on every scroll event
    $(window).on('scroll', _scrollHandler);
}

And there you have it. Check out the live demonstration.

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

The action of JQuery is modifying the value of the checkbox, but it is not visually showing as checked

I am working on a list that contains checkboxes and text, similar to an email inbox. My goal is to be able to check or uncheck the checkbox anytime I click anywhere on the list item (row). To achieve this functionality, I have used the following code withi ...

Using JavaScript to pass a newly created variable as an argument in a default

Currently, I am developing a node application that heavily utilizes promises. To enhance the readability of my code, I have been removing anonymous functions and storing them in a JavaScript object called "myCallbacks". Here's an example: let myCallb ...

The React Js error message shows an 'Uncaught (in promise)' TypeError that prevents reading an undefined property

Struggling with passing the response from an Ajax request to another function in React. Although I am able to receive the response, I cannot pass it to { this.showBattersData(data); } where I need to render the DOM. It's clear that something is missin ...

Are your divs getting truncated?

Currently faced with a perplexing issue where inserting elements into a div causes scaling problems, resulting in most of the divs being cut off. This glitch occurs when two new elements are added. Despite changing page sizes and thoroughly debugging by o ...

The WordPress GD Star rating plugin is failing to load on the webpage

I am having trouble getting the GD star rating plugin to load on my website. I followed the correct installation and configuration steps, but the plugin still won't show up on the page. I have attempted various solutions without success. Can anyone s ...

How can I horizontally center an element in CSS/HTML if auto-margin does not produce the desired result?

This is a snippet of the CSS code I'm using for my menu: ul { text-align: left; display: inline; margin: auto; width: 50%; position: fixed; top: 0; list-style: none; } I've attempted to use auto-margin left and right ...

Having trouble with clearing floats in Twitter Bootstrap CSS - any help appreciated!

Today, in an effort to learn CSS and apply it practically by creating simple themes, I decided to delve into the proper ways of clearing floats in CSS. My research led me to explore how Twitter handles this issue, so I dug into Bootstrap's CSS file an ...

Reactivity in Vue.js powered by ES6 classes

I am attempting to create a computed property in Vue.js that is associated with an ES6 class. Here is an example of my Vue instance setup: ... props: ['customClass'], computed: { localClass: { get() { return this.custom ...

"By implementing an event listener, we ensure that the same action cannot be

function addEventListenerToElement(element, event, handlerFunction) { if(element.addEventListener) { element.addEventListener(event, function(){ handlerFunction(this.getAttribute("src")); }, false); } } //initialize the function addEve ...

The Glyphicons in Bootstrap are showing up with incorrect images

After downloading bootstrap 3.3.7, I extracted all the files including css, fonts, and js folders. These were then copied to the respective directories under www/css, www/js, and www/css/fonts in index.html as shown below: <link href="css/bootstrap.min ...

Acquire HTML content from XML with the help of jQuery

Can anyone guide me on how to extract content from this XML file? <?xml version="1.0" encoding="UTF-8"?> <feed xmlns="http://www.w3.org/2005/Atom" xmlns:app="http://www.w3.org/2007/app" xmlns:opensearch="http://a9.com/-/spec/opensearch/1.1/" ...

Difficulty with MultiHandleSliderExtender and postback in JavaScript

Attempting to implement the multihandlesliderextender (from the Ajax Toolkit) for creating a price filter option on a webshop. Upon selecting a new price, it should trigger a reload of everything including extensive behind-the-scenes code. Referenced an a ...

When attempting to utilize putImageData on the HTML5 canvas context, an error occurs stating that the overload resolution has failed

While following the MDN canvas tutorial, I encountered an issue with a code snippet I wrote. The code is supposed to color the top left corner (50x50 pixels) of the canvas in red. However, I'm receiving an error message that says Overload resolution ...

What is the process for implementing a context menu in datatables version 1.10?

I need to enhance my table using DataTables from datatables.net by adding a context menu feature. Upon researching, I came across the jQuery contextMenu plugin and found some information in the DataTables forum about implementing a context menu. However, ...

Manage and update events in the Angular Bootstrap Calendar

For the past few days, I have been working on integrating a calendar into my project. I decided to repurpose an example provided by the developer. One issue that I've come across is related to the functionality of deleting events when using the dropdo ...

Learn the process of displaying and concealing elements when hovering over the parent element with Javascript

I am facing a challenge with my containing div that has a 'h1' title and a 'p' description inside it. My goal is to have the 'description paragraph' hidden while the 'title' is visible when the page loads, and to hav ...

Footer not being pushed down by content in mobile view on page

Hello everyone, Can you assist me with a query, please? My form works perfectly fine in desktop view, but it gets cut off on mobile view and I'm unsure of the reason why. Here is my code: .upload-pic { position: absolute; max-width: au ...

D3 Chart: What is the best way to insert images into a node?

Within the jsFiddle demo provided in this query, there is code displayed. I am curious about how I can assign images to each node. var graph = { "nodes":[ {"name":"1","rating":90,"id":2951}, ] } You can access my jsFiddle Demo through this ...

Circle a component around another on the vertical axis (z-index)

A plugin caught my eye some time back, but I'm having trouble locating it. This nifty tool operates by positioning an element behind another one, then smoothly sliding it to the right. After that, it changes the z-index so the element appears larger i ...

Why is the image auto-swapping script failing to display images frequently?

I have a script that is currently running to rotate between two different logos on my webpage. What I am attempting to achieve is for the page to load and then seamlessly transition from one image to the other without any blank space. Below is the code I ...