Adjusting the visibility of a div as you scroll

I'm trying to achieve a fade-in and fade-out effect on div elements when scrolling over them by adjusting their opacity. However, I'm facing difficulties in getting it to work properly.

The issue lies in the fact that my div elements are positioned in the middle of the page rather than at the top, so using scrollTop doesn't seem to be the right approach, right?

var fade = $('.b_wrapper');
var range = 400;

$(window).on('scroll', function() {
  var st = $(this).scrollTop();
  fade.each(function() {
    var offset = $(this).offset().top;
    var height = $(this).outerHeight();
    offset = offset + height / 1;
    
    $(this).css({
      'opacity': 1 - (st + offset - range) / range
    });
  });
});
.content {
  height: 100px;
}

.b_wrapper {
  background: lightgreen;
  margin-top: 40px;
  padding: 20px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.1/jquery.min.js"></script>
<div class="content"></div>
<div class="b_wrapper">
  <p>this is a div</p>
</div>
<div class="b_wrapper">
  <p>this is a div</p>
</div>
<div class="b_wrapper">
  <p>this is a div</p>
</div>
<div class="b_wrapper">
  <p>this is a div</p>
</div>
<div class="b_wrapper">
  <p>this is a div</p>
</div>
<div class="b_wrapper">
  <p>this is a div</p>
</div>
<div class="b_wrapper">
  <p>this is a div</p>
</div>

(Check out the JsFiddle here)

Answer №1

If you want to monitor changes in the intersection between a target element and its ancestor or the viewport, you should consider using the Intersection Observer API. This API keeps an eye on these intersections and triggers a callback when certain thresholds are met.

To start, initialize a new observer with specific options:

let options = {
  root: null,
  threshold: [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1]
}
let observer = new IntersectionObserver(callback, options);
  • root can refer to either the containing ancestor element (e.g., selected using document.querySelector()) or the viewport by setting it to null.

  • threshold is an array of values that represent different levels of intersection ratios. When an element's intersection ratio matches one of these values, the callback function is invoked, allowing you to adjust the element's opacity directly based on this ratio.

After setting up the options, make sure to add each target element to the observer:

for (const target of document.querySelectorAll('.b_wrapper')) {
    observer.observe(target);
}

The callback function simply sets the opacity of watched elements based on their intersection ratio with the viewport:

let callback = (entries, observer) => {
  entries.forEach((entry) => {
    entry.target.style.opacity = entry.intersectionRatio
  });
};

This should give you a good starting point. For more information and examples, consult the API documentation.

Answer №2

Perhaps not the most optimal approach, but here is my attempt:

  • When scrolling, I determine which element is the most centered on the screen

  • Upon window resize, I update the center of the screen value

let centerOfScreen = window.innerHeight / 2;
let pageScroll;
let closestCenteredDivPosition = 999999;
let currentIndex;

let wrappers = document.getElementsByClassName("wrapper");
let positions = [];
for (let e of wrappers) {
  positions.push(e.offsetTop + e.offsetHeight / 2);
}

highlightMostCenteredDiv = () => {
  pageScroll = document.documentElement.scrollTop || document.body.scrollTop;
  let currentValue;
  for (let i = 0; i < positions.length; i++) {
    currentValue = Math.abs(positions[i] - centerOfScreen - pageScroll);
    if (closestCenteredDivPosition > currentValue) {
      closestCenteredDivPosition = currentValue;
      currentIndex = i;
    }
  }
  if (!document.querySelector(".current")) {
    wrappers[currentIndex].classList.add("current");
  } else {
    if (wrappers[currentIndex] != document.querySelector(".current")) {
      document.querySelector(".current").classList.remove("current");
      wrappers[currentIndex].classList.add("current");
    }
  }
  closestCenteredDivPosition = 999999;
}

highlightMostCenteredDiv();

document.addEventListener("scroll", highlightMostCenteredDiv)

window.addEventListener("resize", () => {
  centerOfScreen = window.innerHeight / 2;
})
body {
  margin: 0;
}

.wrapper {
  background-color: orange;
  height: 100px;
  width: 100%;
  margin: 50px 0;
  opacity: 0.3;
  transition: opacity 1s ease;
}

.current {
  opacity: 1;
}
<div class="wrapper"></div>
<div class="wrapper"></div>
<div class="wrapper"></div>
<div class="wrapper"></div>
<div class="wrapper"></div>
<div class="wrapper"></div>
<div class="wrapper"></div>
<div class="wrapper"></div>

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

Display the React component following a redirect in a Next.js application that utilizes server-side rendering

Just starting out with next.js and encountering a problem that I can't seem to solve. I have some static links that are redirecting to search.tsx under the pages folder. Current behavior: When clicking on any of the links, it waits for the API respo ...

Tips for creating a textarea element that resembles regular text format

I am working on creating an HTML list that allows users to edit items directly on the page and navigate through them using familiar keystrokes and features found in word processing applications. I envision something similar to the functionality of To achi ...

Tips for styling a React JS component class

I am attempting to write inline CSS for a React JS component called Login, but I keep encountering an error. What could be causing this issue? Could you provide guidance on the correct way to implement in-line component CSS? import React, {Component} from ...

The Angular modal feature is specifically designed to function exclusively within the index.html

Success! My angular modal is now functioning properly. https://i.sstatic.net/CUHpL.png One thing to note is that the modal script must be placed within my index.html file for it to work: <script type="text/ng-template" id="myModalContent.html"> ...

JavaScript code not functioning properly when accessing all information retrieved from Django Model

When I retrieve the endDate field from a Django model using a for loop on an HTML page, I want to verify if all the end dates are earlier than today's date. To achieve this, I am utilizing JavaScript code. Although my code successfully checks the fir ...

Verify if the contract address corresponds to a token and retrieve the token details, such as its symbol

Can I use web3 to retrieve token information such as symbol and total supply similar to the etherscan API pro endpoint tokeninformation by providing the contract address? I'm interested in determining whether the addresses I collect are tokens or reg ...

Encountering an issue in React: unable to establish properties for null

There are two elements that should appear based on whether a condition is true or false. However, I am encountering an issue when trying to use the useRef hook for one of them. Despite the fact that the element sometimes renders first, I keep receiving t ...

Experiencing issues with my site's display due to unwanted code plaguing the

I am currently using the latest Divi theme on my WordPress site, and it is in maintenance mode. Recently, I noticed a strange space between the header and the top of the page that only appears on Chrome and IE, but not on Firefox. After inspecting with dev ...

Enable my textbox to interpret the html img tag

Is there a way to display emoji images instead of emoji symbols when inserting them into my textbox? For example, can I show the image representation of ':)' instead of just the symbol itself? ...

The react-transition-group fails to function properly until the page is reloaded

My task scheduler using React Router 5 and React Redux is working fine. Now I am trying to animate transitions between different routes using react-transition-group. When I click the URL changes, but the screen does not re-render until I manually reload ...

Discovering a particular string within a jQuery array object: Tips and tricks

One thing that is confusing me is the jQuery array object. To explain further: I have two arrays, one called brandsLink and the other called floorLink. When a user clicks on a link, I am saving the brand name in a variable called brandName, and then checki ...

AngularJs is not responsive to sending POST requests with hidden <input> values

Within my web application, there are multiple forms on a single page. I am looking to utilize AngularJS to submit a specific form. Each form requires a unique ID with a hidden value for submission. However, using value="UNIQUE_ID" in a hidden input field ...

What is the best way to insert a new item into an array that is nested within an object?

Currently, I am delving into the world of using $resource in angularjs and finding great examples in this answer AngularJS $resource RESTful example. Fetching and creating records is working fine, but now my challenge lies in adding a "section" to an exist ...

Creating a canvas texture on tube geometry with three.js for optimal display on iPad devices

I have a 3D model of a tube geometry with 18000 coordinates on the production side. To simplify, I am selecting every 9th coordinate to plot 9000 coordinates for building the tube geometry using only the CanvasRenderer. When utilizing vertexColors: THREE. ...

Creating a nested tree structure array from a flat array in Node.js

I have an array structure that I need to convert into a tree array using node.js. The current array looks like this: var data= [ { "id1": 1001, "id2": 1002, "id3": 1004, ... } ...

Where should data processing be conducted: in the service or controller layer?

Here's a question regarding the best practices for organizing code. I'm fetching data from an API using $resource and I need to manipulate it before displaying it on the view. My dilemma is at which stage should I process the data? My current b ...

Why are the UI components (`Card Number`, `MM/YY`, `CVC`) not being displayed in the React app when using Card

Having an issue where the CardElement Ui component is not visible in the image provided. It should appear above the Order Total: $0 next to the payment method. I've attempted various debugging methods without success. I'm still working on resolv ...

Issue with Xampp causing server side PHP script to malfunction

I attempted to execute a basic program that collects the user's name and gender from an html form, and then utilizes server-side scripting (php) to display the entered name and gender. Below is my html and php code snippet, with xampp control panel ve ...

The behavior of the jQuery click function seems to be quirky and not functioning as expected. Additionally, the

It seems that instead of triggering a POST request, somehow a GET request is being triggered. Additionally, the ajax call is not being made as expected. I have attempted this many times before, but none of my attempts seem to be working. It could potenti ...

Using TypedArray as a parameter in a Cordova plugin

I've been working on a plugin specifically for Cordova 3.3. Within my JavaScript code, I'm in the process of downloading a PDF file which is being stored as a uInt8Array. download: function ( ) { var xhr = new XMLHttpRequest(); ...