【问题标题】:How to scroll an HTML page to a given anchor如何将 HTML 页面滚动到给定的锚点
【发布时间】:2011-03-10 23:14:04
【问题描述】:

我想让浏览器将页面滚动到给定的锚点,只需使用 JavaScript。

我在我的 HTML 代码中指定了 nameid 属性:

 <a name="anchorName">..</a>

 <h1 id="anchorName2">..</h1>

我希望通过导航到 http://server.com/path#anchorName 获得与您相同的效果。应滚动页面,使锚点靠近页面可见部分的顶部。

【问题讨论】:

    标签: javascript jquery html scroll anchor


    【解决方案1】:

    您可以使用 jQuery 的 .animate().offset()scrollTop。喜欢

    $(document.body).animate({
        'scrollTop':   $('#anchorName2').offset().top
    }, 2000);
    

    示例链接:http://jsbin.com/unasi3/edit

    如果您不想制作动画,请使用.scrollTop(),例如:

    $(document.body).scrollTop($('#anchorName2').offset().top);
    

    或者 JavaScript 原生的location.hash 喜欢:

    location.hash = '#' + anchorid;
    

    【讨论】:

    • 至于创建选择器来查找&lt;h1 id="anchorName"&gt;&lt;a name="anchorName"&gt;,使用$('#'+hash+',a[name='+hash+']') 或稍微优化的$(document.getElementById(hash) || 'a[name='+hash+']') 将首先通过id 搜索元素,然后诉诸搜索仅当未找到时才为 a。
    • @gnarf - 没有任何需要优化 jQuery 中的 '#' 选择器 - 它们已经为您优化了。很容易看出你是否阅读过 jQuery 源代码。
    • @CodeJoust - 我是 jQuery 团队的一员,我已经读过很多遍了,是的,$("#selector") 已经过优化,但 $("#selector,a[name='selector']") 不会很快进行同样的优化。我想我 2.5 岁的评论听起来有点奇怪。 “优化”是在找到 id 时避免 a[name='selector'] 搜索,而不是优化对 id 的搜索。
    • 我对这种方法有点运气:About
    • 有时这是不准确的......当页面具有延迟加载的动态部分时
    【解决方案2】:
    function scrollTo(hash) {
        location.hash = "#" + hash;
    }
    

    根本不需要 jQuery!

    【讨论】:

    • 这实际上并没有滚动,它只是跳跃。到时候你还不如直接链接到锚点&lt;a href="#anchorName"&gt;link&lt;/a&gt;
    • 请注意,这只会工作一次。设置散列后,页面将不会滚动到相同的散列,除非您将其更改为虚拟散列然后重新设置。
    • 你不应该使用scrollTo,因为它已经被全局窗口对象使用了。此外,参数不应命名为 hash,因为 location.hash 也已定义。您可以使用此代码:function scrollToHash(hashName) { location.hash = "#" + hashName; }
    • @MarkusZeller,为什么不应该将参数称为哈希?它不会与位置冲突,是吗?
    • 如果你设置“scroll-behavior:smooth;”,它会滚动在 html 元素上
    【解决方案3】:

    更简单:

    var element_to_scroll_to = document.getElementById('anchorName2');
    // Or:
    var element_to_scroll_to = document.querySelectorAll('.my-element-class')[0];
    // Or:
    var element_to_scroll_to = $('.my-element-class')[0];
    // Basically `element_to_scroll_to` just have to be a reference
    // to any DOM element present on the page
    // Then:
    element_to_scroll_to.scrollIntoView();
    

    【讨论】:

    • 我起初以为 Mandx 是在拖钓,然后我尝试了这个,它奏效了。除了我之外,我以前从未遇到过这种方法。 Mozilla Docs for this method。此外,这似乎将在浏览器中得到很好的支持。
    • 我遇到了很多 jquery 解决方案无法滚动的问题。这让我省去了很多挫败感。
    • 警告! 如果上面的 div 包含浮动元素并且无法轻松确定其大小,则此方法可能会出现问题。
    • 这是一个干净的解决方案,但是到目前为止它不允许任何调整,它会进行硬滚动。有一个实验性参数scrollIntoViewOptions 有一个behavior: "smooth" 选项,但它目前仅与Firefox 兼容。
    • 如果你认为你想要平滑滚动,你应该使用document.getElementById("xyz").scrollIntoView({block:"nearest", behavior:"smooth"});,这样如果用户在浏览器设置中禁用了平滑滚动,他们就不会被强制平滑滚动。 Safari 不支持这一点,因此它只会在没有动画的情况下捕捉到正确的位置。您应该使用它而不是滚动到给定的像素偏移,因为这可以尊重例如scroll-margin 属性自动。重新实现对scroll-margin 的支持将非常复杂。
    【解决方案4】:
    $(document).ready ->
      $("a[href^='#']").click ->
        $(document.body).animate
          scrollTop: $($(this).attr("href")).offset().top, 1000
    

    【讨论】:

    • 解释一下。例如,想法/要点是什么?请通过editing (changing) your answer 回复,而不是在 cmets 中(without "Edit:"、"Update:" 或类似的 - 答案应该看起来像是今天写的)。
    【解决方案5】:

    很好 solution by jAndy,但平滑滚动似乎在 Firefox 中出现问题。

    以这种方式编写也适用于 Firefox。

    (function($) {
        $(document).ready(function() {
             $('html, body').animate({
               'scrollTop':   $('#anchorName2').offset().top
             }, 2000);
        });
    })(jQuery);
    

    【讨论】:

    • 在最新的 Chrome 版本中,这是我发现的唯一有效的方法。感谢您的提示!
    【解决方案6】:

    我找到了一个简单易用的jQuery solution on CSS-Tricks。就是我现在用的那个。

    $(function() {
      $('a[href*=#]:not([href=#])').click(function() {
        if (location.pathname.replace(/^\//,'') == this.pathname.replace(/^\//,'') && location.hostname == this.hostname) {
          var target = $(this.hash);
          target = target.length ? target : $('[name=' + this.hash.slice(1) +']');
          if (target.length) {
            $('html,body').animate({
              scrollTop: target.offset().top
            }, 1000);
            return false;
          }
        }
      });
    });
    

    【讨论】:

    • 选择器在 jquery 2.2.0 中抛出异常。 0x800a139e - JavaScript 运行时错误:语法错误,无法识别的表达式:a[href*=#]:not([href=#])
    【解决方案7】:

    大多数答案都不必要地复杂。

    如果你只想跳转到目标元素,你不需要JavaScript:

    # the link:
    <a href="#target">Click here to jump.</a>
    
    # target element:
    <div id="target">Any kind of element.</div>
    

    如果您想以动画方式滚动到目标,请参考5hahiL's answer

    【讨论】:

    • 有时,您需要动态地进行;即,不通过用户的直接操作。我相信这就是 OP 想要的。
    • 是的,显然 OP 已经知道锚链接功能。
    【解决方案8】:

    来自 CSS-Tricks 的解决方案不再适用于 jQuery 2.2.0。它会抛出一个选择器错误:

    JavaScript 运行时错误:语法错误,无法识别的表达式:a[href*=#]:not([href=#])

    我通过更改选择器来修复它。完整的 sn-p 是这样的:

    $(function() {
      $("a[href*='#']:not([href='#'])").click(function() {
        if (location.pathname.replace(/^\//,'') == this.pathname.replace(/^\//,'') && location.hostname == this.hostname) {
        var target = $(this.hash);
        target = target.length ? target : $('[name=' + this.hash.slice(1) +']');
        if (target.length) {
          $('html,body').animate({
            scrollTop: target.offset().top
          }, 1000);
          return false;
        }
      }
     });
    });
    

    【讨论】:

      【解决方案9】:

      这是一个没有 jQuery 的纯 JavaScript 解决方案。它已在 Chrome 和 Internet Explorer 上进行了测试,但未在 iOS 上进行测试。

      function ScrollTo(name) {
        ScrollToResolver(document.getElementById(name));
      }
      
      function ScrollToResolver(elem) {
        var jump = parseInt(elem.getBoundingClientRect().top * .2);
        document.body.scrollTop += jump;
        document.documentElement.scrollTop += jump;
        if (!elem.lastjump || elem.lastjump > Math.abs(jump)) {
          elem.lastjump = Math.abs(jump);
          setTimeout(function() { ScrollToResolver(elem);}, "100");
        } else {
          elem.lastjump = null;
        }
      }
      

      演示:https://jsfiddle.net/jd7q25hg/12/

      【讨论】:

      • 抱歉评论一个老话题,但这对我来说最有效,因为我的项目没有使用 JQuery。我注意到的唯一问题是,如果您滚动到最顶部,它会丢失 5 个像素左右。
      • 看到纯js版本很爽。我教学生始终深入了解并理解 JQuery 为他们做了什么,所以这是一个很好的例子。
      • 这应该是公认的答案:它是一个纯 js 示例并且它实现了所需的滚动动画效果。我将超时值调整为 20,它可以完美运行。
      • 谢谢我喜欢纯javascript解决方案
      • Works in IOS刚刚测试过。
      【解决方案10】:

      这是一个将页面滚动到锚点的工作脚本。 要设置它,只需为锚链接提供一个与您要滚动到的锚的名称属性相匹配的 id。

      <script>
          jQuery(document).ready(function ($){
              $('a').click(function (){
                  var id = $(this).attr('id');
                  console.log(id);
                  if ( id == 'cet' || id == 'protein' ) {
                      $('html, body').animate({ scrollTop: $('[name="' + id + '"]').offset().top}, 'slow');
                  }
              });
          });
      </script>
      

      【讨论】:

        【解决方案11】:

        在 2018 年,你不需要 jQuery 来做这样简单的事情。内置的scrollIntoView() 方法支持“behavior”属性以平滑滚动到页面上的任何元素。您甚至可以使用哈希更新浏览器 URL 以使其可收藏。

        来自this tutorial on scrolling HTML Bookmarks,这是一种自动为页面上的所有锚链接添加平滑滚动的原生方式:

        let anchorlinks = document.querySelectorAll('a[href^="#"]')
         
        for (let item of anchorlinks) { // relitere 
            item.addEventListener('click', (e)=> {
                let hashval = item.getAttribute('href')
                let target = document.querySelector(hashval)
                target.scrollIntoView({
                    behavior: 'smooth',
                    block: 'start'
                })
                history.pushState(null, null, hashval)
                e.preventDefault()
            })
        }
        

        【讨论】:

        • 消除对 jQuery 依赖的优秀答案
        • 哇!效果很棒!
        • 什么是"relitere"?有错别字吗?
        【解决方案12】:

        这行得通:

        $('.scroll').on("click", function(e) {
        
          e.preventDefault();
        
          var dest = $(this).attr("href");
        
          $("html, body").animate({
        
            'scrollTop':   $(dest).offset().top
        
          }, 2000);
        
        });
        

        https://jsfiddle.net/68pnkfgd/

        只需将“滚动”类添加到您想要动画的任何链接

        【讨论】:

        • 不错,简单易用的解决方案。谢谢!
        【解决方案13】:

        jQuery("a[href^='#']").click(function(){
            jQuery('html, body').animate({
                scrollTop: jQuery( jQuery(this).attr('href') ).offset().top
            }, 1000);
            return false;
        });

        【讨论】:

          【解决方案14】:

          2018-2020 纯 JavaScript:

          有一种非常方便的滚动到元素的方法:

          el.scrollIntoView({
            behavior: 'smooth', // smooth scroll
            block: 'start' // the upper border of the element will be aligned at the top of the visible part of the window of the scrollable area.
          })
          

          但据我了解,它没有以下选项那么好的支持。

          Learn more about the method.


          如果元素必须在顶部:

          const element = document.querySelector('#element')
          const topPos = element.getBoundingClientRect().top + window.pageYOffset
          
          window.scrollTo({
            top: topPos, // scroll so that the element is at the top of the view
            behavior: 'smooth' // smooth scroll
          })
          

          Demonstration example on CodePen


          如果您希望元素位于中心:

          const element = document.querySelector('#element')
          const rect = element.getBoundingClientRect() // get rects(width, height, top, etc)
          const viewHeight = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);
          
          window.scroll({
            top: rect.top + rect.height / 2 - viewHeight / 2,
            behavior: 'smooth' // smooth scroll
          });
          

          Demonstration example on CodePen


          支持:

          他们写道scrollscrollTo 的方法相同,但scrollTo 的支持效果更好。

          More about the method.

          【讨论】:

          • 这个解决方案非常好用!感谢分享!
          • 请注意scrollIntoView 会遇到与scrollto(some px location) 相同的问题 - 如果元素的位置在您滚动时发生变化,您将滚动到错误的位置。例如,如果您在滚动时加载了未知维度的图像,这很容易发生这种情况,这会将滚动目标元素向下推,并且您漂亮的精美滚动将在过度戏剧化的史诗失败中停止。
          • 请注意,如果您使用带有font-display: swap 的网络字体,如果您在换入字体之前测量滚动位置,最终可能会出现稍微不正确的滚动偏移。当您使用font-display: swap 时,换入是异步的,取决于客户端网络速度、DNS 服务器、Web 字体托管 CDN 和客户端 CPU 能力,因此它实际上是随机的。您可以做的最好的事情是尝试检测字体加载事件:stackoverflow.com/a/66739727/334451
          【解决方案15】:

          一个 Vue.js 2 解决方案...添加一个简单的数据属性来简单地强制更新:

            const app = new Vue({
            ...
          
            , updated: function() {
                     this.$nextTick(function() {
                     var uri = window.location.href
                     var anchor = ( uri.indexOf('#') === -1 ) ? '' : uri.split('#')[1]
                     if ( String(anchor).length > 0 && this.updater === 'page_load' ) {
                        this.updater = "" // only on page-load !
                        location.href = "#"+String(anchor)
                     }
                   })
                  }
               });
               app.updater = "page_load"
          
           /* Smooth scrolling in CSS - it works in HTML5 only */
           html, body {
               scroll-behavior: smooth;
           }
          

          【讨论】:

            【解决方案16】:

            平滑滚动到合适的位置

            获取正确y坐标并使用window.scrollTo({top: y, behavior: 'smooth'})

            const id = 'anchorName2';
            const yourElement = document.getElementById(id);
            const y = yourElement.getBoundingClientRect().top + window.pageYOffset;
            
            window.scrollTo({top: y, behavior: 'smooth'});
            

            【讨论】:

            • 我认为您应该在 CSS 样式文件中添加以下内容:css html { scroll-behavior: smooth; }
            【解决方案17】:

            让浏览器将页面滚动到给定锚点的最简单方法是在 style.css 文件中添加*{scroll-behavior: smooth;},并在 HTML 导航中使用 #NameOfTheSection

            *{scroll-behavior: smooth;}
            <a href="#scroll-to">Click to Scroll<a/>
            
            <p>other sections</p>
            <p>other sections</p>
            <p>other sections</p>
            <p>other sections</p>
            <p>other sections</p>
            <p>other sections</p>
            <p>other sections</p>
            <p>other sections</p>
            <p>other sections</p>
            <p>other sections</p>
            <p>other sections</p>
            <p>other sections</p>
            <p>other sections</p>
            
            <section id="scroll-to">
            <p>it will scroll down to this section</p>
            </section>

            【讨论】:

            • 这个 CSS 方法非常适合我,而且超级优雅!
            猜你喜欢
            • 2017-02-12
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-03-23
            • 1970-01-01
            相关资源
            最近更新 更多