如何将 HTML 页面滚动到给定的锚点
Posted
技术标签:
【中文标题】如何将 HTML 页面滚动到给定的锚点【英文标题】:How to scroll an HTML page to a given anchor 【发布时间】:2011-03-10 23:14:04 【问题描述】:我想让浏览器将页面滚动到给定的锚点,只需使用 javascript。
我在我的 html 代码中指定了 name
或 id
属性:
<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;
【讨论】:
至于创建选择器来查找<h1 id="anchorName">
或<a name="anchorName">
,使用$('#'+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!
【讨论】:
这实际上并没有滚动,它只是跳跃。到时候你还不如直接链接到锚点<a href="#anchorName">link</a>
请注意,这只会工作一次。设置散列后,页面将不会滚动到相同的散列,除非您将其更改为虚拟散列然后重新设置。
你不应该使用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
支持:
他们写道scroll
与scrollTo
的方法相同,但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 页面滚动到给定的锚点的主要内容,如果未能解决你的问题,请参考以下文章