We use hashes a lot in our URIs to jump people around to a specific place on the page. For example (www.example.com#part1 and www.example.com#part2). However, we have a static fixed header at the top of the page, and so if it tries to jump you down, it ends up plopping what you need to see in a place that's covered by the static header.

Is it possible to use javascript (preferably jQuery) to intercept all hash jumps and add 100px to wherever it's going to take you?

Dani AI

Generated

A few clean options (CSS-first, or JS when you need extra control). ’s hashchange trick is perfectly fine for many cases, and / pointed in the right directions — but there are some edge cases to cover: initial page load with a hash, named anchors, dynamic header height, and keyboard/screen-reader focus. The two recommended patterns below avoid the “target hidden under a fixed header” problem reliably.

CSS-first (modern browsers): add a scroll offset to the targeted elements so the browser’s native jump lands below the header. Example:

/* apply to elements that will be linked-to */
:target,
h2, h3 {           /* or .section-anchor */
  scroll-margin-top: 100px;
  -webkit-scroll-margin-top: 100px;
}

This is the simplest, no-JS fix and works in most modern browsers; provide a JS fallback for older/quirky browsers. (developer.mozilla.org)

JS/jQuery (robust): intercept anchor clicks, handle hashchange and initial load, compute the current header height each time, and move focus for accessibility. Example pattern (not the same snippet posted earlier):

(function($){
  function scrollToHash(hash){
    if(!hash) return;
    var id = hash.slice(1);
    var el = document.getElementById(id) || document.getElementsByName(id)[0];
    if(!el) return;
    var $el = $(el);
    var headerH = $('#static-header.fixed').outerHeight() || 0;
    var top = Math.max($el.offset().top - headerH, 0);
    $('html,body').stop().animate({ scrollTop: top }, 220, function(){
      $el.attr('tabindex','-1').focus(); // keyboard / screen reader friendly
    });
  }

  $(document).on('click', 'a[href^="#"]', function(e){
    var href = $(this).attr('href');
    if(href.length > 1){
      e.preventDefault();
      if(history.pushState) history.pushState(null, null, href);
      else location.hash = href;
      scrollToHash(href);
    }
  });

  $(window).on('hashchange', function(){ scrollToHash(location.hash); });
  $(window).on('load', function(){ if(location.hash) scrollToHash(location.hash); });
})(jQuery);

For programmatic scrolling you can also use Element.scrollIntoView with options; it can be combined with CSS scroll-margin-top for predictable alignment. (developer.mozilla.org)

Troubleshooting notes: recompute header height for responsive/shrinking headers; handle empty/hash-only links; test on browsers known to have scroll-margin quirks and provide the JS fallback when needed; always move focus to the target (tabindex=-1 then focus) to preserve accessibility. (web.dev)

Recommended Answers

All 3 Replies

Something like this? Not sure if the scrollTo can be used relative (never used it).

Thanks guys! What's funny is I'm already using the hashchange trigger elsewhere and for some reason I was still blank!

Here's what I'm doing. Works like a charm:

$(window).on('hashchange', function() {
    var header = $('#static-header.fixed');
    if (window.location.hash != '' && header.length) {
        var position = $(window).scrollTop();
        $(window).scrollTop(position - header.outerHeight());
        return false;
    }
});
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.