Explain Codes LogoExplain Codes Logo

Have a div cling to top of screen if scrolled down past it

javascript
sticky-elements
scroll-position
dom-access
Anton ShumikhinbyAnton Shumikhin·Feb 9, 2025
TLDR

To make a div stick to the top during scroll, utilize this position: sticky; top: 0; style

.sticky-top { position: sticky; top: 0; }

Apply this style like so:

<div class="sticky-top">Content will stick at the top when scrolling</div>

The sticky-top div will remain in the viewport once you've scrolled past it, because position: sticky; kicks in when the element's position hits top: 0.

Stickiness with JavaScript or jQuery

To handle older browsers that don't support position: sticky;, let's toggle a sticky class with JavaScript or jQuery based on the scroll position.

Determining barometer for stickiness

const stickyDiv = document.querySelector('.my-div'); // Selector for your div const stickyPoint = stickyDiv.offsetTop; // The magic point of stickiness window.addEventListener('scroll', () => { window.pageYOffset >= stickyPoint ? stickyDiv.classList.add('sticky-top') // Become sticky if scrolled past : stickyDiv.classList.remove('sticky-top'); // Go back to normal otherwise });

Cached selectors swagger

Cache the selectors to reduce DOM access. Adding this will make your performance go from "meh" to "whoa".

const stickyDiv = document.querySelector('.my-div'); const stickyPoint = stickyDiv.offsetTop; const onScroll = () => { window.pageYOffset >= stickyPoint ? stickyDiv.classList.add('sticky-top') : stickyDiv.classList.remove('sticky-top'); }; window.addEventListener('scroll', onScroll); // The 'onScroll' function calls the class toggle

Prevent layout shift with CSS and HTML

Add an empty div to prevent a flickering layout when the div becomes fixed.

<div class="anchor-div" style="height: 100px;"></div> <!-- This is where the magic happens --> <div class="my-div">...</div> <!-- The actual content div -->

Establish stickiness class and toggle on scroll

Define the sticky class in CSS and toggle it with JavaScript or jQuery:

.sticky-top { position: fixed; top: 0; left: 0; right: 0; height: 100px; }

Using jQuery, class toggling becomes a one-liner. jQuery surely has the ring for our class toggling needs.

const $stickyDiv = $('.my-div'); const stickyPoint = $stickyDiv.offset().top; // Our aspiring magician $(window).on('scroll', () => { $(window).scrollTop() >= stickyPoint ? $stickyDiv.addClass('sticky-top') // Stage entry - the div is now sticky! : $stickyDiv.removeClass('sticky-top'); // Exit stage - back to being static! });

"If you gaze long into the scroll, the scroll also gazes into you." - Friedrich Scrollszsche

When you use sticky headers with anchor links, the page might scroll too far, hiding the beginning of the anchored section. Add some shift to the scroll position:

$(document).on('click', 'a[href^="#"]', function(event) { event.preventDefault(); const target = $($(this).attr('href')); const offsetTop = target.offset().top - $('.sticky-top').outerHeight(); $('html, body').animate({ scrollTop: offsetTop }, 0); });