Bir bağlantı bağlantısını tıklarken yumuşak kaydırma


487

Sayfamda birkaç köprü var. Kullanıcıların yardım bölümümü ziyaret ettiklerinde okuyabilecekleri bir SSS.

Bağlantı bağlantılarını kullanarak, sayfayı bağlantıya doğru kaydırabilir ve kullanıcıları oraya yönlendirebilirim.

Bu kaydırmayı düzgünleştirmenin bir yolu var mı?

Ancak özel bir JavaScript kitaplığı kullandığına dikkat edin. Belki jQuery pişmiş böyle bir şey sunuyor?


Belki en iyi cevabı inceleyebilir misiniz? Saf css tek satırlı çözüm tüm hantal jquery önerileri arasında bulmak zordur: stackoverflow.com/a/51588820/1422553
Александр Киричек

Yanıtlar:


1159

Nisan 2018'i güncelleyin: Şimdi bunu yapmanın yerel bir yolu var :

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

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

Bu, şu anda yalnızca en kanayan kenar tarayıcılarında desteklenmektedir.


Daha eski tarayıcı desteği için bu jQuery tekniğini kullanabilirsiniz:

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

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

Ve işte keman: http://jsfiddle.net/9SDLw/


Hedef öğenizin bir kimliği yoksa ve bu öğeye onunla bağlantı oluşturuyorsanız name, şunu kullanın:

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

    return false;
});

Artan performans için, bunu önbelleğe gerektiğini $('html, body')yayınlanmamasını böylece, seçici her seferinde bir çapa tıklandığında:

var $root = $('html, body');

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

    return false;
});

URL'nin güncellenmesini istiyorsanız, animategeri arama dahilinde yapın :

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
Bu, # fonksiyonunu URL'den kaldırır ve geri işlevini kırar. Bunun etrafında bir yol var mı?
Fletch

2
@JosephSilber scrollTop: $(this.hash).offset().topbunun yerine olmamalı scrollTop: $(this.href).offset().topmı?
Gregory Pakosz

4
@CreateSean -scrollTop: $(href).offset().top - 72
Joseph Silber

5
html, bodyBurada nesneyi önbelleğe almanın gereksiz olduğunu, tıklama başına bir kez seçici çalıştırmanın o kadar da fazla olmadığını iddia ediyorum .

2
İlk çözüm en iyi ve en modern, bununla eski tarayıcılarda bu davranışı desteklemek için bu polyfill kullanabileceği başka Polyfill
Efe

166

Doğru sözdizimi:

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

Basitleştirilmiş : KURU

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

Açıklama href*=\\#:

  • *#char içeren şeylerle eşleştiği anlamına gelir . Böylece sadece çapalarla eşleşir . Bunun anlamı hakkında daha fazla bilgi için buraya bakın
  • \\çünkü #css selector özel bir karakter, bu yüzden kaçmak zorundayız.

8
Ben sadece çapa urls hizmet değiştirmek $('a')zorunda $('a[href*=#]')kaldı
okliv

2
@okliv Bu, örneğin javascript bağlantısı gibi çok fazla hizmet verecek <a href="javascript:$('#test').css('background-color', '#000')">Test</a>. $('a[href^=#]')Karma karakterle başlayan tüm URL'lerle eşleşmeyi tercih etmelisiniz .
Martin Braun

3
Ayrıca, '#' özel bir karakterdir ve şu şekilde kaçması gerekir:a[href^=\\#]
QuinnFreedman

3
Bu, diğer sayfalardaki bağlantılara olan bağlantıların çalışmamasına neden oldu. Koşullu if ($ ($ (this.hash) .selector) .length) {... yumuşak kaydırma ekleyerek çözüldü. }
Liren

1
Yeni bir sayfaya ilk seyahat ederken bunu nasıl canlandırabilirim? Örneğin: website.com/newpage/#section2 öğesini tıklayarak. Sayfayı yüklemesini ve ardından aşağı kaydırmasını istiyorum. Mümkün mü?
Samyer

72

CSS3'teki yeni sıcaklık. Bu, bu sayfada listelenen her yöntemden çok daha kolaydır ve Javascript gerektirmez. Sadece css içine aşağıdaki kodu girin ve aniden bağlantılar kendi sayfanızın içindeki konumlara işaret pürüzsüz bir kaydırma animasyon olacaktır.

html{scroll-behavior:smooth}

Bundan sonra, bir div'a işaret eden bağlantılar, bu bölümlere sorunsuzca kayar.

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

Düzenleme: Yukarıdaki bir etiket hakkında karışık olanlar için. Temel olarak tıklanabilir bir bağlantıdır. Daha sonra web sayfanızın herhangi bir yerinde başka bir div etiketine sahip olabilirsiniz.

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

Bu bağlamda, bir bağlantı tıklanabilir ve #bölümü ne olursa olsun gidecektir, bu durumda bölüm dediğimiz div'ımızdır.

BTW, bunun işe yaraması için saatler harcadım. Bazı belirsiz yorumlar bölümünde çözümü buldum. Buggy ve bazı etiketlerde işe yaramaz. Vücutta çalışmadı. Sonunda CSS dosyasında html {} içine koymak zaman çalıştı.


4
Çok kullanışlı olabilirim ama dezavantajları var
Buzut

3
güzel, ama dikkatli olun çünkü şu anda Safari ve açıkça Explorer tarafından desteklenmiyor (03/2019)
Marco Romano

2
güzel çözüm, sadece kapsama alanı% 74,8 ile sınırlıdır. belki gelecekte
iepur1lla

1
İnanılmaz. Çok teşekkürler.
Mikkel Fennefoss

1
Bu, önümüzdeki yıllarda en geçerli cevap olacaktır.
Nurul Huda

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

bu benim için mükemmel çalıştı


1
"event.preventDefault ();" "return false;"
Andres Separ

Söylediğim için üzgünüm, ancak herhangi bir pürüzsüzlük olmadan çapa adlı sayfada hızlı bir şekilde çalışmıyor ve gösteriliyor.
Kamlesh

18

Hiç kimsenin aynı zamanda tarayıcı konum karmasını güncellemeye özen gösteren yerel bir çözüm yayınlamamasına şaşırdım. İşte burada:

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

Eğiticiye bakın: http://www.javascriptkit.com/javatutors/scrolling-html-bookmark-javascript.shtml

Yapışkan başlıklara sahip siteler scroll-padding-topiçin, bir ofset sağlamak üzere CSS kullanılabilir.


1
Bu cevabı en çok seviyorum. Ancak afais bir mahsup sağlamanın bir yolu yoktur. Sabit bir başlık durumunda ihtiyaç duyulduğu gibi.
bskool

Neyse ki, CSS kaydırma davranışı özelliği ile aynı zayıf destek: developer.mozilla.org/en-US/docs/Web/CSS/…
Dmitry Nevzorov

15

Sadece CSS

html {
    scroll-behavior: smooth !important;
}

Tek yapmanız gereken sadece bunu eklemek. Artık dahili bağlantıların kaydırma davranışı bir akış akışı gibi düzgün olacaktır.

Not : Tüm son tarayıcılar ( Opera, Chrome, Firefoxvs) bu özelliği destekliyor.

ayrıntı anlamak için bu makaleyi okuyun


1
Güzel! Bu neden kabul edilen cevap değil? tüm bu javascriptlere ihtiyacımız yok!
Trevor de Koekkoek

1
Harika çalışıyor, kabul edilen cevap bu olmalı.
mezar

Tarayıcı desteğini buradan
Ryan Zhou

1
bir cazibe gibi çalışır. js için gerek yok
Navbro

ŞİMDİYE kadar düzgün kaydırma için en iyi çözümdür! Teşekkürler!
yehanny


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

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


1
bu yalnızca iç sayfa bağlantı bağlantıları için işe
yarar

5

Burada zaten birçok iyi cevap var - ancak hepsi boş çapaların dışlanması gerektiği gerçeğini kaçırıyor . Aksi takdirde, bu komut dosyaları boş bir bağlantı tıklatıldığında JavaScript hataları oluşturur.

Bence doğru cevap şöyle:

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

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

4

JQuery kullanma:

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


3

Verilen cevap çalışıyor ancak giden bağlantıları devre dışı bırakıyor. Ekstra bonus kolaylığı (salınım) olan bir sürümün altında ve giden bağlantılara saygı duyulur.

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

+1 stop()ancak url kırıntısı beklendiği gibi çalışma yapmaz: Geri düğmesi geri getirmiyor, bu kırıntı animasyon tamamlanıncaya sonra url ayarlandığında çünkü. URL'de bir kırıntı olmadan daha iyi, örneğin airbnb böyle yapar.
Eric

3

HTML

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

veya Mutlak Tam URL ile

<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

Modern tarayıcılar bu günlerde biraz daha hızlı. Bir setInterval işe yarayabilir. Bu işlev bu günlerde Chrome ve Firefox'ta iyi çalışıyor. (Safari'de biraz yavaş, IE ile uğraşmadı)

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

Kaydırma davranışı kullanarak bunu yapmanın bir css yolu vardır. Aşağıdaki özelliği ekleyin.

    scroll-behavior: smooth;

Ve işte bu. JS gerekmez.

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>

Not: lütfen tarayıcı uyumluluğunu kontrol edin.


hangi kapsayıcıya kaydırma davranışı kullanmalıyım: smooth;
CraZyDroiD

Şüphe durumunda, @CraZyDroiD vücut etiketine ekleyin
Santosh

2

Bu ekleniyor:

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

bir şekilde dikey ofseti etkisiz hale getiriyor

top - 72

Firefox ve IE'de, ut Chrome'da değil. Temel olarak, sayfa ofsete bağlı olarak durması gereken noktaya düzgün bir şekilde kayar, ancak daha sonra sayfanın ofset olmadan nereye gideceğine atlar.

Hash'i url'nin sonuna ekler, ancak geri basmak sizi en üste geri götürmez, hash'i url'den kaldırır ve görüntüleme penceresini bulunduğu yere bırakır.

İşte tam js kullanıyorum:

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

Bu çözüm, farklı sayfalara bağlantı bağlantıları kesmeden aşağıdaki URL'ler için de çalışır.

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

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

vb.

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

Bunu henüz tüm tarayıcılarda test etmedim.


2

Bu, jQuery'nin hedef karmasını fark etmesini ve ne zaman ve nerede duracağını bilmesini kolaylaştırır.

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

Test Edilen ve Doğrulanan Kod

<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

Bunu "/ xxxxx # asdf" ve "#asdf" href çapaları için yaptım

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

Düzgün bir kaydırma için birden çok bağlantı ve çapa için uyguladığım çözüm:

http://www.adriantomic.se/development/jquery-localscroll-tutorial/ navigasyon bağlantılarınızı bir navigasyon divinde kurduysanız ve bu yapı ile beyan ettiyseniz:

<a href = "#destinationA">

ve karşılık gelen bağlantı etiketi hedeflerinizi şu şekilde yapın:

<a id = "destinationA">

Sonra bunu belgenin başına yükleyin:

    <!-- 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 sayesinde


1

Sayfada bir div öğesine ilerlemek için basit bir düğmeniz varsa ve üst tarafa atlayarak geri düğmesinin çalışmasını istiyorsanız, şu kodu ekleyin:

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

Bu, karma değerini okuyarak ve Joseph Silbers'in cevabı gibi kaydırarak farklı div'lara atlamak için genişletilebilir.


1

Offset () işlevinin, öğenizin konumunu belgeye verdiğini asla unutmayın. Dolayısıyla öğenizi üst öğeye göre kaydırmanız gerektiğinde bunu kullanmalısınız;

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

Anahtar nokta scroll-div scrollTop'u almak ve scrollTop'a eklemek. Bunu yapmazsanız position () işlevi size her zaman farklı konum değerleri verir.


1

Bağlantı etiketinin görünüm penceresinin üstünde olmasını sağlayan bağlantı etiketinin ofset üstü window.scroll()ile birlikte kullanabilir behavior: smoothve topayarlayabilirsiniz.

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

Demo:

Sadece CSS özelliğini ayarlayabilirsiniz scroll-behavioriçin smoothJavascript ihtiyacını ortadan kaldırır (en modern tarayıcılar destek).


0

paylaştığın için teşekkürler Joseph Silber. İşte 2018 çözümünüzü standart davranışı korumak için küçük bir değişiklikle ES6 olarak (en üste kaydırın):

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 gerektirir ve hash tarayıcı url'sine eklerken, id yerine belirtilen adla etiket yapıştırmak için canlandırır. Ayrıca, # işaretinin kaçan bir ters eğik çizgi ile ön ekinin girmediği jquery ile ilgili çoğu yanıttaki bir hatayı düzeltir. Geri düğmesi maalesef önceki karma bağlantılara düzgün gitmiyor ...

$('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);
});
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.