点击锚点链接时平滑滚动

643

我网页上有几个超链接,是用户访问我的帮助部分时需要阅读的常见问题解答。

通过使用锚点链接,我可以使页面滚动到锚点处并引导用户查看相关信息。

有没有一种方法可以使滚动更加平滑?

但请注意,他正在使用自定义JavaScript库。也许jQuery内置了类似于此的功能吗?


3
请问您能否帮忙查看一下最佳答案?在所有臃肿的jQuery建议中,很难找到一个纯CSS的单行解决方案:https://dev59.com/mmsz5IYBdhLWcg3wsaHN#51588820 - Александр Киричек
你可以使用这个轻量级脚本。初始化只需要一行代码。 - Asef Hossini
5
对于所有正在寻找快速答案的人:html { scroll-behavior: smooth; } - Felix Geenen
30个回答

1384

2018年4月更新:现在有一种原生方法可以实现此功能

document.querySelectorAll('a[href^="#"]').forEach(anchor => {
    anchor.addEventListener('click', function (e) {
        e.preventDefault();

        document.querySelector(this.getAttribute('href')).scrollIntoView({
            behavior: 'smooth'
        });
    });
});

目前只有最新版本的浏览器支持此功能。


如果需要支持旧版浏览器,您可以使用这种 jQuery 技术:

$(document).on('click', 'a[href^="#"]', function (event) {
    event.preventDefault();

    $('html, body').animate({
        scrollTop: $($.attr(this, 'href')).offset().top
    }, 500);
});

这里有一个 jsfiddle 示例:http://jsfiddle.net/9SDLw/


如果您要链接的目标元素没有 ID,而是使用其 name 属性进行链接,请使用以下代码:

$('a[href^="#"]').click(function () {
    $('html, body').animate({
        scrollTop: $('[name="' + $.attr(this, 'href').substr(1) + '"]').offset().top
    }, 500);

    return false;
});
为了增加性能,你应该缓存 $('html, body') 选择器,这样它不会在每次单击锚点时都运行:
var $root = $('html, body');

$('a[href^="#"]').click(function () {
    $root.animate({
        scrollTop: $( $.attr(this, 'href') ).offset().top
    }, 500);

    return false;
});
如果你想更新URL,请在animate的回调函数中执行:
var $root = $('html, body');

$('a[href^="#"]').click(function() {
    var href = $.attr(this, 'href');

    $root.animate({
        scrollTop: $(href).offset().top
    }, 500, function () {
        window.location.hash = href;
    });

    return false;
});

9
我认为在这里缓存 html, body 对象是不必要的,每次点击运行一次选择器并没有那么耗费性能。 - user3638471
最好将其包装在 window.addEventListener('load', function (){ } 中,以确保在标签出现后执行。 - GDavoli

289

CSS3中的新亮点。这比本页面上列出的所有方法都要简单得多,而且不需要Javascript。只需将以下代码输入您的CSS中,突然间链接到您自己页面内部位置的链接就会具有平滑滚动动画。

html{scroll-behavior:smooth}

此后,任何指向div的链接都会平滑地滑动到这些部分。

<a href="#section">Section1</a>
编辑:对于那些对上面的a标签感到困惑的人,基本上它是一个可点击的链接。您可以在网页的某个地方再添加另一个div标签。

编辑:对于那些对上面的a标签感到困惑的人,基本上它是一个可点击的链接。您可以在网页的某个地方再添加另一个div标签。

<div id="section">content</div>

在这方面,一个链接将是可点击的,并且将转到#section,本例中为我们称之为section的div。

顺便说一句,我花了几个小时才使它工作。在某些晦涩的评论部分找到了解决方案。在某些标签中存在缺陷,无法正常工作。在主体中也无法工作。当我将其放入CSS文件中的html {}中时,它最终起作用了。


13
我可以非常有用,但它们有缺点 - Buzut
7
不错,但要小心,因为目前它不受Safari和显然的Explorer(03/2019)支持。 - Marco Romano
几年后回到这里。谢谢@Cristian :) - Dawid Gałecki
1
我在使用Chrome浏览器时遇到了一些问题。不过,我通过在CSS代码中设置!important标志来解决了这个问题,所以我的CSS现在看起来是这样的 - html{scroll-behavior: smooth !important;} - Martin Rohwedder

181

正确的语法是:

//Smooth scrolling with links
$('a[href^=\\#]').on('click', function(event){     
    event.preventDefault();
    $('html,body').animate({scrollTop:$(this.hash).offset().top}, 500);
});

// Smooth scrolling when the document is loaded and ready
$(document).ready(function(){
  $('html,body').animate({scrollTop:$(location.hash).offset().‌​top}, 500);
});

简化:DRY

function smoothScrollingTo(target){
  $('html,body').animate({scrollTop:$(target).offset().​top}, 500);
}
$('a[href^=\\#]').on('click', function(event){     
    event.preventDefault();
    smoothScrollingTo(this.hash);
});
$(document).ready(function(){
  smoothScrollingTo(location.hash);
});

href^=\\#的解释:

  • ^表示它匹配包含#字符的内容。因此只匹配锚点,以确保它是指向同一页的链接(感谢Peter Wong的建议)。
  • \\是因为#是css选择器中的特殊字符,所以我们必须转义它。

2
使用href*=\\#时要小心,而不是href^=\\#,您可能还需要检查路径名以确保它是指向同一页的链接。我们曾经遇到过一个问题,即哈希链接实际上链接到另一页。 - Peter Wong

74

仅使用 CSS

html {
    scroll-behavior: smooth;
}

您只需要添加此代码,现在您的内部链接滚动行为将像流水一样平滑。

编程方式:额外高级功能

// Scroll to specific values
// window.scrollTo or window.scroll
window.scroll({
  top: 1000, 
  left: 0, 
  behavior: 'smooth'
});

// Scroll certain amounts from current position 
window.scrollBy({ 
  top: 250, // could be negative value
  left: 0, 
  behavior: 'smooth' 
});

// Scroll to a certain element
document.getElementById('el').scrollIntoView({
  behavior: 'smooth'
})

注意: 所有最新浏览器 (Opera, Chrome, Firefox 等) 都支持此功能。

如需深入了解,请阅读此文章


27

我很惊讶没有人发布过一个本地解决方案,同时也能更新浏览器的位置哈希值以匹配。以下是解决方案:

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

查看教程:http://www.javascriptkit.com/javatutors/scrolling-html-bookmark-javascript.shtml

对于具有固定页眉的网站,可以使用scroll-padding-top CSS来提供偏移量。


25

不需要任何JavaScript,只需在HTML标签中使用scroll-behavior: smooth。就这样。

html{
scroll-behavior: smooth;
}

1
这是一个很好的答案。似乎大多数桌面浏览器已经支持了几年。iOS上的Safari今年才支持它。这是参考链接:https://caniuse.com/css-scroll-behavior - phip

24
$('a[href*=#]').click(function(event){
    $('html, body').animate({
        scrollTop: $( $.attr(this, 'href') ).offset().top
    }, 500);
    event.preventDefault();
});

这对我来说完美地起作用了


12

我建议您将此代码改为通用代码:

$('a[href^="#"]').click(function(){

var the_id = $(this).attr("href");

    $('html, body').animate({
        scrollTop:$(the_id).offset().top
    }, 'slow');

return false;});

你可以在这里看到一篇非常好的文章:jquery-effet-smooth-scroll-defilement-fluide


11

这里已经有很多好的回答了 - 但它们都忽略了一个事实,即必须排除空锚点。否则,只要单击空锚点,这些脚本就会生成JavaScript错误。

在我看来,正确的答案是这样的:

$('a[href*=\\#]:not([href$=\\#])').click(function() {
    event.preventDefault();

    $('html, body').animate({
        scrollTop: $($.attr(this, 'href')).offset().top
    }, 500);
});

2
此外,当您从不同的URL单击散列链接时,需要考虑到许多window.location....$(this).attr('href').substring(...)处理。 - user151496

10

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接