I have used this feature a lot on web site development, but never really investigated how it works : fixed header that shrinks when user scrolls down is a nice way of putting a bigger logo without comprising further reading.
requirements : tailwind, only ! we'll use pure javascript and a bit of css
first the html code , note that some elements are in brackets because I currently work with statamic antlers layout language. but most importantly here is the h-auto and w-24 initial sizing of the navigation bar logo
<div class="sticky top-0 z-50 bg-white shadow-md">
<img src="{{ settings:logo }}" alt="{{ alt ?? 'Logo' }}" class="h-auto w-24" id="wavelogo">
</div>
the css here is important to get a smooth transition
#wavelogo {
transition: width 0.2s,
height 0.5s,
transform 0.2s;
}
and the javascript works with a limit value for the beginning of shrink effect, note that there a buffer value that will prevent flickering on most browsers
const elem = document.getElementById("wavelogo");
var originalWidth=elem.style.width
var originalHeight=elem.style.height
var originalRatio =elem.style.width / elem.style.height
window.onscroll = function() {
console.log(window.scrollY)
const buffer = 15;
if(window.scrollY>=90+buffer){
//user scrolled to the top of the page
var w= 50
elem.style.width = w + "px";
elem.style.height = w/originalRatio+ "px";
}
else if (window.scrollY < (90 - buffer))
{
//user scrolled to the top of the page
elem.style.width = originalWidth;
elem.style.height = originalHeight;
}
};
another technique to prevent flickering would be to use a timeout
let timeoutId;
window.onscroll = function() {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => {
if(window.scrollY >= 90){
var w = 50;
elem.style.width = w + "px";
elem.style.height = w/originalRatio + "px";
} else {
elem.style.width = originalWidth;
elem.style.height = originalHeight;
}
}, 10); // 10ms delay
};