0

On my site I have a sticky header so when I use anchor links they get covered by the header.

I found a bit of script that solves my problem... the only problem I have found with it is it only works once... if I scroll back to the top and hit the link again the header covers it... If I hit another anchor link on the same page it works and then go back to the previous link it works... it's only when I hit the same link twice.

(function($, window) {
    var adjustAnchor = function() {

        var $anchor = $(':target'),
                fixedElementHeight = 51;

        if ($anchor.length > 0) {

           window.scrollTo(0, $anchor.offset().top - fixedElementHeight);

        }

    };

    $(window).on('hashchange load', function() {
        adjustAnchor();
    });

})(jQuery, window);

I found this code on another question and it is the only thing that comes close to what I need. Some other scripts I have tried affect Bootstrap dropdown's which use id's. I would like to use a CSS solution such as...

 :target::before { 
   display: block; 
   content: " "; 
   margin-top: -51px; 
   height: 51px; 
   visibility: hidden; 
 }

The only problem with that is it doesn't work if the target has any top padding.

So my question is, is there a way to make the script above kind of reset after it fires so it will work on the same link multiple times (again I found it here offsetting an html anchor to adjust for fixed header? Can you see any potential problems using that scrip? Does anyone have a pure CSS solution that actually works (I've tried everything on this page http://nicolasgallagher.com/jump-links-and-viewport-positioning/demo/)? I manage a large site with content managers so I cannot control if a anchor has margin or padding on the top.. so the solution has to be flexible. Like I said the scrip above is the best solution I have found so far. Thanks!

dbaker6
  • 39
  • 2
  • 8
  • please post a fiddle or a snippet of your problem – Alexandre Elshobokshy Jan 30 '19 at 15:13
  • I have a solution here: https://codepen.io/HerrSerker/pen/Mwdpzq – yunzen Jan 30 '19 at 15:15
  • So when you define your firstElementHeight at the top you will face the problem with the margin-top:-51 , one of the solutions here is to check if the anchor has this style property then you add 51 to the firstElementHeight which result in 102 or if not just delete firstElementHeight from anchor.offset() – Osama Jan 30 '19 at 15:20
  • Osama how so? My jquery skills are not the best. Thank you! – dbaker6 Jan 30 '19 at 15:29

1 Answers1

0

// smoothscroll for anchor links and hashed URLs (works with id and name attributes)
;
(function($, window) {

  var defaultOptions = {
    // The selector of the fixed element
    headerSelector: '.header',
    // the offset to the fixed element at the end of the scroll
    offsetTop: 10,
    // the scroll duration
    duration: 1000
  }
  fixedOptions = {
  }
  
  function smoothScroll(options) {
    options = $.extend({}, defaultOptions, options, fixedOptions)
    headerSelector = options.headerSelector
    offsetTop = options.offsetTop
    duration = options.duration
    $(function($) {
      readyFunc();
    });

    if ("onhashchange" in window) {
      $(window).on('hashchange', hashChangeFunc);
    }

    // Every Link that has a hash in it, but isn't just a hash
    $('a[href*="#"]:not([href="#"])').on('click', clickFunc);
  }
  
  window.smoothScroll = smoothScroll;
  var hash = document.location.hash;
  // if we have a fixed position header element
  var headerSelector;
  // always add this offset
  var offsetTop;
  // scrollTime
  var duration;
  var target;

  // set scroll to all top on doc load
  var readyFunc = function() {
    if (document.location.hash) {
      setTimeout(function() {
        window.scrollTo(0, 0);
      }, 1);
      scrollFunc($(document.location.hash), headerSelector);
    }
  }

  // don't follow hash links
  var hashChangeFunc = function(e) {
    e.preventDefault();
    return false;
  }

  var clickFunc = function(e) {
    // check if link is on the same page
    if (location.pathname.replace(/^\//, '') == this.pathname.replace(/^\//, '') && location.hostname == this.hostname) {
      e.preventDefault();
      target = $(this.hash);
      target = target.length ? target : $('[name="' + this.hash.slice(1) + '"]');

      if (target.length) {
        scrollFunc(target, headerSelector);
      }
      if (window.history && window.history.pushState) {
        history.pushState(null, null, this.hash);
      } else {
        document.location.hash = this.hash;
      }
    }
  }

  var scrollFunc = function(elem, fixed) {
    if ($(elem).css('position') == 'fixed') {
      var top = $(elem).position().top;
    } else {
      var top = $(elem).offset().top;
    }

    if ($(fixed).css('position') == 'fixed') {
      var offset = $(fixed).outerHeight();
    } else {
      var offset = 0;
    }
    top = Math.max(0, top - offset - offsetTop);
    $('html, body')
      .stop()
      .animate({
        scrollTop: top
      }, duration)
      .end();
  }

}(jQuery, window));

smoothScroll()
.header {
  position: fixed;
  background: silver;
  border-bottom: 1px solid gold;
  width: 100%;
  padding: 10px;
  top: 0;
}

body {
  margin: 0;
  margin-top: 70px;
}

#myid,
.src {
  padding: 10px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="header">Header<br>Header<br>Header</div>
<div id="top"></div>

<div class="src">
  <a href="#myid">link scroll 1</a><br>
  <a href="#myname">link scroll 2</a>

  <br />
  <br />
  <br />
  <br /> Some content
  <br />
  <br />
  <br />
  <br />
  <br /> Some content
  <br />
  <br />
  <br />
  <br />
  <br /> Some content
  <br />
  <br />
  <br />
  <br />
  <br /> Some content
  <br />
  <br />
  <br />
  <br />
  <br /> Some content
  <br />
  <br />
  <br />
  <br /> Some content
  <br />
  <br />
  <br /> Some content
  <br />
  <br />
  <br />
  <br />
  <br />
  <br /> Some content
  <br />
  <br />
  <br />
  <br />
  <br />
  <br />
  <br />
  <br /> Some content
  <br />
  <br />
  <br />
  <br />
  <br />
  <br />
  <br />
  <br />
  <br />
  <br />
  <br /> Some more content
  <br />
  <br />
  <br />
  <br />
  <br />
  <br />
  <br />
  <br />
  <br />
  <br />
</div>
<div id="myid"></div>
Scroll 1
<a href="#top">Top</a>
<br />
<br /> Some more content
<br />
<br /> Some more content
<br />
<br /> Some more content
<br />
<br /> Some more content
<br />
<br /> Some more content
<br />
<br /> Some more content
<br />
<br /> Some more content
<br />
<br /> Some more content
<br />
<br /> Some more content
<br />
<br /> Some more content
<br />
<br /> Some more content
<br />
<br /> Some more content
<br />
<br /> Some more content
<br />
<br />
<br /> Some more content
<br />
<br />
<br /> Some more content
<br />
<div name="myname"></div>
Scroll 2
<a href="#top">Top</a>
<br />
<br /> Some more content
<br />
<br />
<br /> Some more content
<br />
<br />
<br /> Some more content
<br />
<br />
<br /> Some more content
<br />
<br />
<br /> Some more content
<br />
<br />
<br /> Some more content
<br />
<br />
<br /> Some more content
<br />
<br />
<br /> Some more content
<br />
<br />
<br /> Some more content
<br />
<br />
<br /> Some more content
<br />
<br />
<br /> Some more content
<br />
<br />
<br /> Some more content
<br />
<br />
<br /> Some more content
<br />
<br />
<br /> Some more content
<br />
<br />
<br /> Some more content
<br />
<br />
<br /> Some more content
<br />
<br />
<br /> Some more content
<br />
<br />
<br /> Some more content
<br />
<br />
<br /> Some more content
<br />
<br />
<br /> Some more content
<br />
<br />
<br /> Some more content
<br />
<br />
<br /> Some more content
<br />
<br />
<br />
<b>This is the end</b><br>
<a href="#top">Top</a>
<br />
<br />
yunzen
  • 32,854
  • 11
  • 73
  • 106
  • Thank you Yunzen. I tried but this script affects bootstrap dropdown's. – dbaker6 Jan 30 '19 at 15:27
  • Can you provide a [fiddle](https://jsfiddle.net) or a [codepen](https://codepen.io) or a [snippet](https://stackoverflow.blog/2014/09/16/introducing-runnable-javascript-css-and-html-code-snippets/) with an example? – yunzen Jan 30 '19 at 22:07