Click here to Skip to main content
15,887,485 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hi. I have a navigation pane with an image inside it. Both shrink in size (minimizes) when the user scrolls down the page. It seems smooth, but if you scroll slowly or use the scroll wheel to move down, it starts to stutter and flicker (as the nav section starts to shrink). What could be causing this?

Here is a Codepen for reference.

JavaScript
window.onscroll = function() {
  scrollFunction()
};

function scrollFunction() {
  if (document.body.scrollTop > 20 || document.documentElement.scrollTop > 20)
  {
    document.getElementById("navContainer").style.padding = "20px 10px";
    document.getElementById("logo").style.width = "200px";
  }
  else {
    document.getElementById("navContainer").style.padding = "20px 10px";
    document.getElementById("logo").style.width = "400px";
  }
}


CSS
body {
  margin:0;
  height:300vh;
}

#navContainer {
    overflow: hidden;
    padding: 40px 10px;
    background-color: #000000;
    position: sticky;
    max-width: 100%;
    top: 0;
    border-bottom: 1px solid #999;
    margin-bottom:3%;
}


.headerImageDiv {
    text-align: center;
}

.headerImage {
    transition: 0.4s;
    max-width:400px;
}

#text {
  line-height:1.2rem;
  font-family: 'Trebuchet MS', 'Lucida Sans Unicode', 'Lucida Grande', 'Lucida Sans', Arial, sans-serif;
  padding: 0% 2%;
  margin-bottom:4%;
}


HTML
<div id="navContainer">
<div class="headerImageDiv">
  <img id="logo" class="headerImage" src="images/myimage.png" alt="">
</div>
</div>

<div id="text">
  Lorem ipsum dolor sit amet consectetur adipisicing elit. Quibusdam deserunt dolor quod blanditiis quae harum reprehenderit, consequatur placeat possimus adipisci aperiam laboriosam id in? Exercitationem non commodi sapiente atque tempora?<br>
  Tempore maiores id ipsam vero, libero architecto aliquam officiis nulla laborum culpa cum voluptatum fugit temporibus aperiam reiciendis quaerat officia sed aliquid? Sequi soluta asperiores atque, accusamus perspiciatis modi iste!<br>
  Ab eos vitae, error a quam suscipit accusamus cupiditate nam sequi asperiores tempora pariatur, quia consectetur! In ut ad fugit corporis, laboriosam deserunt enim ipsa, nobis rem iusto eligendi neque!<br>
  Quis aliquam tempora, asperiores, commodi non et minus quo nam vitae nulla cupiditate saepe nostrum eum quam officiis. Fuga molestias atque nisi magni ad alias cupiditate facilis, dolorum in natus!<br>
  Nemo libero distinctio pariatur iste facere quibusdam quo eum illo perspiciatis reiciendis illum laborum sapiente ullam aut magnam voluptatum et eius velit temporibus in, placeat amet dicta. Facilis, ab! Quis.<br>
</div>


What I have tried:

Tried to implement the onscroll event smoothly, but the code as-is doesn't seem to be smooth when scrolling slowly.
Posted
Updated 4-Aug-23 1:05am
v2

Using the scroll event to change the document when you scroll beyond a certain threshold rarely works well. It's usually better to use the Intersection Observer API[^] instead.

For example:
CSS
.scrolled #navContainer {
	padding: 20px 10px;
}

.headerImage {
    transition: 0.4s;
    width: 400px;
}
.scrolled .headerImage {
	width: 200px;
}
JavaScript
document.addEventListener("DOMContentLoaded", () => {
	const toggle = document.createElement("div");
	toggle.style.position = "absolute";
	toggle.style.top = "20px";
	toggle.style.left = "0px";
	document.body.appendChild(toggle);
	
	const observer = new IntersectionObserver(
		([e]) => document.body.classList.toggle("scrolled", e.intersectionRatio < 1),
		{ threshold: [1] }
	);
	
	observer.observe(toggle);
});
Demo[^]
 
Share this answer
 
Comments
Andre Oosthuizen 4-Aug-23 7:00am    
Hi Richard, in your demo, there is still a bad flicker when you scroll.
We had a similar issue a while back and added a debounce mechanism/function (anti-flicker) to the scroll event listener. Debouncing will delay the execution of your scroll function until after a certain period of inactivity, so the function won't be called too frequently while scrolling.

a Slight change to your Javascript -
JavaScript
//Debounce function to delay the execution of the scrollFunction...
function debounce(func, wait) {
  let timeout;
  return function () {
    const context = this;
    const args = arguments;
    const later = function () {
      timeout = null;
      func.apply(context, args);
    };
    clearTimeout(timeout);
    timeout = setTimeout(later, wait);
  };
}

//Call the scrollFunction with a debounce of 100ms. You can change this to fit your needs...
window.onscroll = debounce(function () {
  scrollFunction();
}, 100);

function scrollFunction() {
  if (document.body.scrollTop > 20 || document.documentElement.scrollTop > 20) {
    document.getElementById("navContainer").style.padding = "20px 10px";
    document.getElementById("logo").style.width = "200px";
  } else {
    document.getElementById("navContainer").style.padding = "40px 10px";
    document.getElementById("logo").style.width = "400px";
  }
}


You can see a working fiddle here - Remove bouncing/flickering in scroll function[^]

I have also tested it in your codepen, also works as expected.
 
Share this answer
 
v2
Comments
Jayne_B 4-Aug-23 10:10am    
I'm seeing a similar problem with this as well. It sticks to the top of the page too long while scrolling, making it difficult to read some of the scrolling content below.

I actually found a working example on another site, but it uses text instead of an image:
https://ide.geeksforgeeks.org/online-html-editor/dafa3583-4c60-4b4d-abbe-b37e0ad8e3a0

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900