アンカーリンクをクリックしたときのスムーズなスクロール


487

ページにハイパーリンクがいくつかあります。ユーザーが私のヘルプセクションにアクセスしたときに読むFAQ。

アンカーリンクを使用して、ページをアンカーに向かってスクロールさせ、ユーザーをそこに誘導できます。

そのスクロールをスムーズにする方法はありますか?

しかし、彼がカスタムJavaScriptライブラリを使用していることに注意してください。たぶんjQueryはこのようなものを提供していますか?


多分ベストアンサーをレビューしていただけますか?ピュアCSSの1行のソリューションは、すべてのかさばるjqueryの提案の中で見つけるのは難しいです:stackoverflow.com/a/51588820/1422553
АлександрКиричек

回答:


1160

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

そしてここにフィドルがあります: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;
});

10
これはURLから#extensionを削除し、back関数を壊すようです。これを回避する方法はありますか?
Fletch

2
@JosephSilberはscrollTop: $(this.hash).offset().top代わりにすべきではありませんscrollTop: $(this.href).offset().topか?
Gregory Pakosz 2013年

4
@CreateSean -scrollTop: $(href).offset().top - 72
ジョセフSILBER

5
html, bodyここでオブジェクトをキャッシュする必要はないと思います。クリックごとに1回セレクターを実行することは、それほど多くはありません。

2
最初のソリューションは、あなたがこの古いブラウザでこの動作をサポートするために、このポリフィルを使用することができ、最良かつ最も近代的であるポリフィル
EFE

166

正しい構文は次のとおりです。

//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*=\\#

  • *#charを含むものと一致することを意味します。したがって、アンカーのみに一致します。これの意味については、こちらをご覧ください
  • \\これは#、CSSセレクターの特殊文字であるため、エスケープする必要があるためです。

8
アンカーURLのみを提供$('a')する$('a[href*=#]')ように変更する必要がありました
okliv 2013

2
@oklivこれは、たとえばのようなJavaScriptリンクのように機能しすぎます<a href="javascript:$('#test').css('background-color', '#000')">Test</a>$('a[href^=#]')ハッシュ文字で始まるすべてのURLを照合するために使用する必要があります。
Martin Braun

3
また、「#」は、特殊な文字であり、それは次のようにエスケープする必要があります:a[href^=\\#]
QuinnFreedman

3
これにより、他のページのアンカーへのリンクが機能しなくなりました。条件付きif($($(this.hash).selector).length){...スムーズスクロールを追加することで解決します。}
Liren

1
新しいページに初めて移動するときに、これをアニメーション化するにはどうすればよいですか?たとえば、website.com / newpage /#section2をクリックします。ページを読み込んでから下にスクロールしたいと思います。それは可能ですか?
Samyer 2017

72

CSS3の新しいホットネス。これは、このページにリストされているすべてのメソッドよりもはるかに簡単で、JavaScriptを必要としません。以下のコードをcssに入力するだけで、自分のページ内の場所を指す突然のリンクがすべてスムーズなスクロールアニメーションになります。

html{scroll-behavior:smooth}

その後、divに向けられたリンクはそれらのセクションにスムーズに移動します。

<a href="#section">Section1</a>

編集:上記のタグについて混乱している人のために。基本的にそれはクリック可能なリンクです。その後、次のようなWebページのどこかに別のdivタグを付けることができます

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

この点で、リンクはクリック可能になり、#sectionが何であっても移動します。この場合は、セクションと呼ばれるdivです。

ところで、私はこれを機能させるために何時間も費やしました。あいまいなコメントのセクションで解決策を見つけました。バグがあり、一部のタグでは機能しませんでした。体内で機能しませんでした。CSSファイルのhtml {}に配置すると、ようやく機能しました。


4
私はとても便利かもしれませんが、それは欠点です
Buzut

3
いいですが、現時点ではSafariと明らかにExplorerによってサポートされていないため、注意が必要です(03/2019)
Marco Romano

2
素晴らしいソリューション、カバレッジのみが74,8%制限されています。多分将来
iepur1lla

1
すごい。どうもありがとう。
Mikkel Fennefoss

1
これは、今後数年間で最も関連性の高い答えになるでしょう。
Nurul Huda

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

これは私にとって完璧に働きました


1
「event.preventDefault();」「return false」を置き換えることができます。
Andres Separ 2014年

申し訳ありませんが、アンカーという名前のページでは機能せず、スムーズに表示されずにすばやく表示されます。
Kamlesh

18

一致するようにブラウザーの場所のハッシュを更新するネイティブソリューションを誰も投稿していないことに驚いています。ここにあります:

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-topCSSを使用してオフセットを提供できます。


1
私はこの答えが一番好きです。ただし、オフセットを提供する方法はありません。固定ヘッダーの場合に必要になります。
bskool 2018年

Unfotunately、CSSスクロール・行動特性と同じ貧しいサポート:developer.mozilla.org/en-US/docs/Web/CSS/...
ドミトリーNevzorov

15

CSSのみ

html {
    scroll-behavior: smooth !important;
}

これだけを追加する必要があります。これで、内部リンクのスクロール動作がストリームフローのようにスムーズになります。

:すべての最新のブラウザ(OperaChromeFirefoxなど)は、この機能をサポートしています。

詳細を理解するには、この記事を読んでください


1
いいね!なぜこれは受け入れられない答えですか?このJavaScriptはすべて必要ありません。
Trevor de Koekkoek

1
それは素晴らしい働きをします、これは受け入れられた答えであるべきです。


1
その魅力のように動作します。jsの必要なし
Navbro

これはこれまでにスムーズなスクロールのための最良のソリューションです!ありがとう!
yehanny

10

この一般的なコードを作成することをお勧めします:

$('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


9
これは一般的なものではなく、jQueryです。
AnrDaemon 2016

6
$(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;
      }
    }
  });
});

公式:http : //css-tricks.com/snippets/jquery/smooth-scrolling/


1
これは内部ページのアンカーリンクに対してのみ機能するようですが、他のページからのアンカーリンクは機能しません。たとえば、website.com
about

5

ここには良い答えがたくさんありますが、空のアンカーを除外しなければならないという事実はありませ。それ以外の場合、空のアンカーがクリックされるとすぐに、これらのスクリプトはJavaScriptエラーを生成します。

私の意見では、正しい答えは次のとおりです:

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

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

4

JQueryの使用:

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


3

与えられた答えは機能しますが、発信リンクを無効にします。ボーナスが追加されたバージョンの下では、緩和(スイング)し、発信リンクを尊重します。

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

        var target = this.hash;
        var $target = $(target);

        $('html, body').stop().animate({
            'scrollTop': $target.offset().top
        }, 900, 'swing', function () {
            window.location.hash = target;
        });
    });
});

stop()ただし、URLクラムが+1 すると期待どおりに機能しません。[戻る]ボタンは元に戻りません。これは、アニメーションの完了後にクラムがURLに設定されているためです。たとえば、URLにクラムがなければ、airbnbのようになります。
エリック

3

HTML

<a href="#target" class="smooth-scroll">
    Link
</a>
<div id="target"></div>

または絶対完全URLを使用

<a href="https://somewebsite.com/#target" class="smooth-scroll">
    Link
</a>
<div id="target"></div>

jQuery

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

3

最近のブラウザーは、最近は少し高速になっています。setIntervalが機能する場合があります。この機能は最近のChromeとFirefoxでうまく機能します。

function smoothScroll(event) {
    if (event.target.hash !== '') { //Check if tag is an anchor
        event.preventDefault()
        const hash = event.target.hash.replace("#", "")
        const link = document.getElementsByName(hash) 
        //Find the where you want to scroll
        const position = link[0].getBoundingClientRect().y 
        let top = 0

        let smooth = setInterval(() => {
            let leftover = position - top
            if (top === position) {
                clearInterval(smooth)
            }

            else if(position > top && leftover < 10) {
                top += leftover
                window.scrollTo(0, top)
            }

            else if(position > (top - 10)) {
                top += 10
                window.scrollTo(0, top)
            }

        }, 6)//6 milliseconds is the faster chrome runs setInterval
    }
}

3

スクロール動作を使用してこれを行うcssの方法があります。次のプロパティを追加します。

    scroll-behavior: smooth;

そして、それはそれです。JSは必要ありません。

a {
  display: inline-block;
  width: 50px;
  text-decoration: none;
}
nav, scroll-container {
  display: block;
  margin: 0 auto;
  text-align: center;
}
nav {
  width: 339px;
  padding: 5px;
  border: 1px solid black;
}
scroll-container {
  display: block;
  width: 350px;
  height: 200px;
  overflow-y: scroll;
  scroll-behavior: smooth;
}
scroll-page {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  font-size: 5em;
}
<nav>
  <a href="#page-1">1</a>
  <a href="#page-2">2</a>
  <a href="#page-3">3</a>
</nav>
<scroll-container>
  <scroll-page id="page-1">1</scroll-page>
  <scroll-page id="page-2">2</scroll-page>
  <scroll-page id="page-3">3</scroll-page>
</scroll-container>

PS:ブラウザの互換性を確認してください。


どのコンテナにスクロール動作を使用する必要がありますか:スムーズ;
CraZyDroiD 2018年

疑問がある場合は、本文のタグ@CraZyDroiDに追加してください
Santosh

2

これを追加する:

function () {
    window.location.hash = href;
}

どういうわけか垂直オフセットを無効にしています

top - 72

FirefoxおよびIEでは、Chromeではありません。基本的に、ページはオフセットに基づいて停止するポイントまでスムーズにスクロールしますが、オフセットなしでページが移動する場所にジャンプします。

ハッシュはURLの末尾に追加されますが、戻るキーを押しても先頭に戻ることはありません。URLからハッシュが削除され、表示ウィンドウがそのまま残ります。

ここに私が使用している完全なjsがあります:

var $root = $('html, body');
$('a').click(function() {
    var href = $.attr(this, 'href');
    $root.animate({
        scrollTop: $(href).offset().top - 120
    }, 500, function () {
        window.location.hash = href;
    });
    return false;
});

2

このソリューションは、別のページへのアンカーリンクを壊すことなく、次のURLでも機能します。

http://www.example.com/dir/index.html
http://www.example.com/dir/index.html#anchor

./index.html
./index.html#anchor

var $root = $('html, body');
$('a').on('click', function(event){
    var hash = this.hash;
    // Is the anchor on the same page?
    if (hash && this.href.slice(0, -hash.length-1) == location.href.slice(0, -location.hash.length-1)) {
        $root.animate({
            scrollTop: $(hash).offset().top
        }, 'normal', function() {
            location.hash = hash;
        });
        return false;
    }
});

私はまだこれをすべてのブラウザでテストしていません。


2

これにより、jQueryがターゲットハッシュを識別し、いつ、どこで停止するかを簡単に知ることができます。

$('a[href*="#"]').click(function(e) {
    e.preventDefault();
    var target = this.hash;
    $target = $(target);

    $('html, body').stop().animate({
        'scrollTop': $target.offset().top
    }, 900, 'swing', function () {
        window.location.hash = target;
    });
});

2
$("a").on("click", function(event){
    //check the value of this.hash
    if(this.hash !== ""){
        event.preventDefault();

        $("html, body").animate({scrollTop:$(this.hash).offset().top}, 500);

        //add hash to the current scroll position
        window.location.hash = this.hash;

    }



});

2

テストおよび検証されたコード

<script>
jQuery(document).ready(function(){
// Add smooth scrolling to all links
jQuery("a").on('click', function(event) {

// Make sure this.hash has a value before overriding default behavior
if (this.hash !== "") {
  // Prevent default anchor click behavior
  event.preventDefault();

  // Store hash
  var hash = this.hash;

  // Using jQuery's animate() method to add smooth page scroll
  // The optional number (800) specifies the number of milliseconds it takes to scroll to the specified area
  jQuery('html, body').animate({
    scrollTop: jQuery(hash).offset().top
  }, 800, function(){

    // Add hash (#) to URL when done scrolling (default click behavior)
    window.location.hash = hash;
  });
} // End if
});
});
</script>

1

"/ xxxxx#asdf"と "#asdf" hrefアンカーの両方でこれを行いました

$("a[href*=#]").on('click', function(event){
    var href = $(this).attr("href");
    if ( /(#.*)/.test(href) ){
      var hash = href.match(/(#.*)/)[0];
      var path = href.match(/([^#]*)/)[0];

      if (window.location.pathname == path || path.length == 0){
        event.preventDefault();
        $('html,body').animate({scrollTop:$(this.hash).offset().top}, 1000);
        window.location.hash = hash;
      }
    }
});

1

スムーズなスクロールのために、複数のリンクとアンカーに実装したソリューションは次のとおりです。

http://www.adriantomic.se/development/jquery-localscroll-tutorial/ ナビゲーションdivでナビゲーションリンクを設定し、次の構造で宣言している場合:

<a href = "#destinationA">

そして対応するアンカータグの宛先は次のとおりです:

<a id = "destinationA">

次に、これをドキュメントの先頭にロードします。

    <!-- Load jQuery -->
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js"></script>

<!-- Load ScrollTo -->
<script src="http://flesler-plugins.googlecode.com/files/jquery.scrollTo-1.4.2-min.js"></script>

<!-- Load LocalScroll -->
<script src="http://flesler-plugins.googlecode.com/files/jquery.localscroll-1.2.7-min.js"></script>

<script type = "text/javascript">
 $(document).ready(function()
    {
        // Scroll the whole document
        $('#menuBox').localScroll({
           target:'#content'
        });
    });
</script>

@Adriantomicのおかげで


1

ページに単純なボタンがあり、divまで下にスクロールして、上にジャンプして戻るボタンを機能させるには、次のコードを追加します。

$(window).on('hashchange', function(event) {
    if (event.target.location.hash=="") {
        window.scrollTo(0,0);
    }
});

これを拡張して、ハッシュ値を読み取り、Joseph Silbersが答えるようにスクロールすることで、別のdivにジャンプすることもできます。


1

offset()関数がドキュメントへの要素の位置を与えていることを忘れないでください。したがって、要素を親に対して相対的にスクロールする必要がある場合は、これを使用する必要があります。

    $('.a-parent-div').find('a').click(function(event){
        event.preventDefault();
        $('.scroll-div').animate({
     scrollTop: $( $.attr(this, 'href') ).position().top + $('.scroll-div').scrollTop()
     }, 500);       
  });

重要な点は、scroll-divのscrollTopを取得してscrollTopに追加することです。そうしない場合、position()関数は常に異なる位置値を提供します。


1

あなたは使用することができるwindow.scroll()behavior: smoothし、topアンカータグは、ビューポートの一番上にあることを保証アンカータグのオフセット先頭にセット。

document.querySelectorAll('a[href^="#"]').forEach(a => {
    a.addEventListener('click', function (e) {
        e.preventDefault();
        var href = this.getAttribute("href");
        var elem = document.querySelector(href)||document.querySelector("a[name="+href.substring(1, href.length)+"]");
        //gets Element with an id of the link's href 
        //or an anchor tag with a name attribute of the href of the link without the #
        window.scroll({
            top: elem.offsetTop, 
            left: 0, 
            behavior: 'smooth' 
        });
        //if you want to add the hash to window.location.hash
        //you will need to use setTimeout to prevent losing the smooth scrolling behavior
       //the following code will work for that purpose
       /*setTimeout(function(){
            window.location.hash = this.hash;
        }, 2000); */
    });
});

デモ:

CSSプロパティscroll-behaviorsmooth(ほとんどの最新のブラウザーがサポートする)に設定するだけで、JavaScriptの必要性をなくすことができます。


0

共有してくれてありがとう、ジョセフ・シルバー。ここでは、標準的な動作を維持するためにマイナーな変更を加えたES6としての2018ソリューション(上にスクロール):

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

    const targetElement = document.querySelector(this.getAttribute("href"));
    targetElement.scrollIntoView({
      block: "start",
      alignToTop: true,
      behavior: "smooth"
    });
  });
});

0

jqueryを必要とし、アニメーションをアニメーション化して、ハッシュをブラウザーのURLに追加しながら、IDではなく指定された名前のタグをアンカーします。また、#記号の前にエスケープバックスラッシュが付いていないjqueryのほとんどの回答のエラーを修正します。残念ながら、戻るボタンは以前のハッシュリンクに正しく戻りません...

$('a[href*=\\#]').click(function (event)
{
    let hashValue = $(this).attr('href');
    let name = hashValue.substring(1);
    let target = $('[name="' + name + '"]');
    $('html, body').animate({ scrollTop: target.offset().top }, 500);
    event.preventDefault();
    history.pushState(null, null, hashValue);
});
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.