如何将 HTML 页面滚动到给定的锚点

Posted

技术标签:

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

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

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

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

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

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

【问题讨论】:

【参考方案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 能力,因此它实际上是随机的。您可以做的最好的事情是尝试检测字体加载事件:***.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 方法非常适合我,而且超级优雅!

以上是关于如何将 HTML 页面滚动到给定的锚点的主要内容,如果未能解决你的问题,请参考以下文章

滚动到 iframe 中的锚点

js如何实现进入页面后自动跳转到锚点

怎么样在HTML页面上添加锚点啊?

使用带反应路由器的锚点

强制 iframe 滚动到 Firefox 中查询字符串传递的锚点

当锚点遇到fixed定位