首页 > 解决方案 > 使用 Jquery 进行锚点偏移

问题描述

在我的网站上,我有一个粘性标题,所以当我使用锚链接时,它们会被标题覆盖。

我发现了一些脚本可以解决我的问题......我发现它的唯一问题是它只能工作一次......如果我滚动回顶部并再次点击链接,标题会覆盖它......如果我在它工作的同一页面上点击另一个锚链接,然后返回到它工作的上一个链接......只有当我两次点击相同的链接时。

(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);

我在另一个问题上找到了这段代码,它是唯一接近我需要的东西。我尝试过的其他一些脚本会影响使用 id 的 Bootstrap 下拉菜单。我想使用 CSS 解决方案,例如...

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

唯一的问题是,如果目标有任何顶部填充,它就不起作用。

所以我的问题是,有没有办法让上面的脚本在触发后重置,这样它就可以多次在同一个链接上工作(我再次发现它在这里偏移了一个 html 锚以调整固定的标题?你能看到任何使用该脚本的潜在问题?有没有人有一个真正有效的纯 CSS 解决方案(我已经尝试了这个页面http://nicolasgallagher.com/jump-links-and-viewport-positioning/demo/上的所有内容)?我管理一个带有内容管理器的大型站点,因此我无法控制锚点是否在顶部有边距或填充。所以解决方案必须灵活。就像我说的,上面的脚本是我迄今为止找到的最佳解决方案。谢谢!

标签: javascriptjquery

解决方案


// 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 />


推荐阅读