Achieving success by correctly reaching the window's edge during an event (onscroll)

This happens to be my 1st inquiry.

Specifically, I have a navigation menu with a transparent background and I am attempting to alter the background once it reaches the top edge of the window.

window.addEventListener("scroll", navSticky);
function navSticky(){
 let nav = document.getElementById('navbar');
 let bounding = nav.getBoundingClientRect();

 if(bounding.top <= 0 ){
     nav.classList.add("sticky");
 }else{
     nav.classList.remove("sticky");
 }
}
*{
 margin: 0;
 text-align: center;
}

body{
 background: lightgrey;
}

header h1{
 padding: 40px;
}

nav{
 position: sticky;
 top: 0;
 padding: 12px;
 background: linear-gradient(to right, 
 rgba(0,0,0,0),
 rgba(0,255,0, 0.5), 
 rgba(255,0,0, 0.5),
 rgba(0,0,0,0));
 color: black;
}

nav:before{
 content: "now bg transparent";
}

.container{
 min-height: 1000px;
 padding: 20px;
}

nav.sticky{
 background: linear-gradient(to right, 
 rgb(0,255,0), 
 rgb(255,0,0));
 color: white;
}

nav.sticky:before{
 content: "now bg isn't transparent";
}
<body>
 <header>
   <h1>Header, that request you scroll page</h1> 
 </header>
 <nav id="navbar">
 </nav>
 <div class ="container">
     While scrolling the page and when the nav hits the top of the screen, .sticky is added to classList<br>
 </div>
</body>

It's functioning as intended, but I do have some inquiries:

  1. Can this be achieved without JavaScript?
  2. Is there a way to optimize this script since the scroll event is triggered frequently?

Appreciate your help!

Answer №1

  1. Regrettably not.
  2. Absolutely, utilizing the IntersectionObserver API proves to be a highly effective and efficient solution for tackling this particular issue.

This API enables you to monitor elements as they enter or exit the viewport without causing any render-blocking code since it operates separately from the main thread.

In your specific scenario, monitor the <header> element. As soon as the element exits the view, that signifies when the navbar should become sticky. Within the callback function, verify whether the isIntersecting property is set to true or false. This property indicates whether the observed element is partially in view or not at all.

const header = document.querySelector('#header');
const nav = document.querySelector('#navbar');

const callback = ([entry]) => {
  const { isIntersecting } = entry;
  nav.classList.toggle('sticky', !isIntersecting);
};

const options = {
  root: null,
  rootMargin: '0px',
  threshold: 0
};

const observer = new IntersectionObserver(callback, options);
observer.observe(header);
* {
  margin: 0;
  text-align: center;
}

body {
  background: lightgrey;
}

header h1 {
  padding: 40px;
}

nav {
  position: sticky;
  top: 0;
  padding: 12px;
  background: linear-gradient(to right, rgba(0, 0, 0, 0), rgba(0, 255, 0, 0.5), rgba(255, 0, 0, 0.5), rgba(0, 0, 0, 0));
  color: black;
}

nav:before {
  content: "now bg transparent";
}

.container {
  min-height: 1000px;
  padding: 20px;
}

nav.sticky {
  background: linear-gradient(to right, rgb(0, 255, 0), rgb(255, 0, 0));
  color: white;
}

nav.sticky:before {
  content: "now bg isn't transparent";
}
<body>
  <header id="header">
    <h1>Header, that prompt you to scroll through the page</h1>
  </header>
  
  <nav id="navbar"></nav>
  
  <div class="container">
    When we scroll the page and the navigation bar reaches the top of the screen, the .sticky class gets added to the classList.<br>
  </div>
</body>

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

Tips for Adding For Loop Value to an Array in JavaScript

Trying to Add For Loop Value to an Array My Current View <script src="https://cdn.jsdelivr.net/npm/apexcharts"></script> <style> body { font-family: Roboto, sans-serif; } #chart { max-width: 650px; margin: 35px auto; ...

What is the best way to retrieve information from an http website and display it in an html table using javascript

I am attempting to retrieve data from the specified site: . The website appears to feature a list of objects, and my goal is to extract each object enclosed in {} into separate columns within a row (6 columns total - one for gameNumber, one for teams, and ...

Enhance the appearance of your image by adding a stylish frame or border without altering its

Is there a way to add a frame to an image without causing it to shrink due to borders? Below is the code I have tried using: .img-border { height: 100%; width: 100%; position: absolute; z-index: 1; } <div class="border border-black i ...

Jquery Click function malfunctioning on testing environment

I'm facing a bit of challenge and could really use some assistance. I have this code snippet that functions perfectly in my test document, but once it's uploaded to the live server, everything loads correctly except for the fadeOut click function ...

Error: Unable to retrieve the "error" property as the data is not defined

Encountered a title error and struggling to fix it :(. Attempting to retrieve data from a signup page, here is the snippet of my JavaScript code: const SignupComponent = () => { const [values, setValues] = useState({ name: 'ryan', emai ...

RxJS: Transforming an Observable array prior to subscribing

I am retrieving data (students through getStudents()) from an API that returns an Observable. Within this result, I need to obtain data from two different tables and merge the information. Below are my simplified interfaces: export interface student Stude ...

Contrasting ./ and $ in React project module imports

The creator of this particular project has utilized a different path to import a component: import { client } from '$lib/graphql-client' I'm curious: What is the significance of the $ symbol in this case? How does it differ from something ...

html - Removing excess space following the footer

Having trouble getting rid of the excess white space below my footer on this website: I attempted to search for a solution online and even added padding:0; to the footer's CSS, but unfortunately it didn't solve the issue. Appreciate any assista ...

Create a cookie on a subdomain that is accessible by all other subdomains

I have been working on a NextJS project that involves multiple apps on separate subdomains. My objective is to enable single sign-on so that when I log in to one app, I am automatically signed in to all the others. We are utilizing nookies as our cookie ha ...

When XMLHttprequest is used to send a POST request, it sometimes

Here is the code I'm using to send a request: let ajaxHandler = new XMLHttpRequest(); ajaxHandler.onreadystatechange = function() { if(ajaxHandler.readyState == 4) { console.log(ajaxHandler.responseText); } } ajaxHandler.open("POST", ...

Conceal the header and footer during the loading of particular pages

For my Angular 1.x application, I needed a way to hide the header and footer on specific pages. To achieve this, I added a 'navigateOut' data property to my state definitions. Using ng-if in my template, I was able to show/hide elements such as t ...

:root variables not being recognized in SCSS and Vue3 with Vite

I am encountering an issue with setting variables in my root SCSS file, as they are not being recognized correctly. Within my Vite configuration, I have included the following to import my styling: css: { preprocessorOptions: { scss: { additio ...

Guide to making an `Ajax Login` button

I am interested in creating a SIGN IN button using ajax. Specifically, I want it to display something (such as welcome) on the same page without refreshing it. This is the progress I have made so far: update2: <form id="myForm" onsubmit="return signi ...

Examining the process through which an element attains focus

Scenario I am working on a Backbone application that has an event listener set up for focus events on a textarea. Since Backbone relies on jQuery events, my main concern revolves around jQuery focus events. Inquiry Is there a method to determine how an e ...

Tips on maintaining the original text hues that were established using setForeground() when a QTableWidgetItem is picked

Issue at Hand: Currently, when the first row is selected as shown in Figure 2 below, all text colors are changed to black, instead of maintaining their original style displayed in Figure 1. Is there a way to retain the original colors when a row is selec ...

Utilizing Vue.js to initiate a server request with vue-resource

Seeking guidance on performing a server call using vue-resource. I'm unsure about how to set the header and send data via Vue.$http.post Vue.$http.post('http://url/', { email: 'foo', password: 'bar' }, { headers: { ...

Issue with arranging cards in a grid when utilizing v-for alongside bootstrap

Just starting out with vuejs and attempting to create a grid by looping through objects using bootstrap classes. However, I'm running into an issue where the cards are not forming a grid as expected when utilizing the col classes. Below is the code f ...

What's the reason behind this file not opening?

When I try to insert this code into files index.html, style.css, and app.js, the page refuses to open. The browser constantly displays a message saying "The webpage was reloaded because a problem occurred." I am using a MacBook Air with macOS Big Sur and a ...

What is the process for inserting text within a .data() method?

I have set up this AJAX request: $.ajax({ method: "GET", url: $('.item').data('query_selector'), dataType: "html" (The ajax call works perfectly, returning something like "item=Mann+Co.+Supply+Crate&quality=6&trad ...

Attempting to scroll through a webpage and extract data using Python and Selenium in a continuous manner

Recently, I posed a question (you can find it here: Python Web Scraping (Beautiful Soup, Selenium and PhantomJS): Only scraping part of full page) that shed light on an issue I encountered while attempting to scrape all the data from a webpage that updates ...