Menggulir dengan lancar saat mengklik tautan jangkar


487

Saya memiliki beberapa hyperlink di halaman saya. FAQ yang akan dibaca pengguna ketika mereka mengunjungi bagian bantuan saya.

Menggunakan tautan Jangkar, saya dapat membuat halaman menggulir ke arah jangkar dan memandu pengguna di sana.

Apakah ada cara untuk membuat pengguliran itu lancar?

Tetapi perhatikan bahwa dia menggunakan pustaka JavaScript khusus. Mungkin jQuery menawarkan sesuatu seperti ini?


Bisakah Anda tinjau jawaban terbaik? Solusi satu baris css murni sulit ditemukan di antara semua saran jquery besar: stackoverflow.com/a/51588820/1422553
Александр Киричек

Jawaban:


1160

Pembaruan April 2018: Sekarang ada cara asli untuk melakukan ini :

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

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

Saat ini hanya didukung di browser tepi paling berdarah.


Untuk dukungan browser yang lebih lama, Anda dapat menggunakan teknik jQuery ini:

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

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

Dan ini biola: http://jsfiddle.net/9SDLw/


Jika elemen target Anda tidak memiliki ID, dan Anda menautkannya dengan ID name, gunakan ini:

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

    return false;
});

Untuk peningkatan kinerja, Anda harus menyimpan cache $('html, body')pemilih itu, sehingga tidak berjalan setiap kali jangkar diklik:

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

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

    return false;
});

Jika Anda ingin URL diperbarui, lakukan di dalam animatepanggilan balik:

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
Ini tampaknya untuk menghapus ekstensi dari URL, melanggar fungsi kembali. Apakah ada jalan keluarnya?
Fletch

2
@JosephSilber harus tidak menjadi scrollTop: $(this.hash).offset().topbukan scrollTop: $(this.href).offset().top?
Gregory Pakosz

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

5
Saya berpendapat bahwa cache html, bodyobjek di sini tidak perlu, menjalankan pemilih sekali per klik tidak terlalu banyak.

2
Solusi pertama adalah yang terbaik dan paling modern, Anda dapat menggunakan polyfill ini untuk mendukung perilaku ini di browser lama dengan polyfill
Efe

166

Sintaks yang benar adalah:

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

Menyederhanakan : KERING

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

Penjelasan tentang href*=\\#:

  • *berarti cocok dengan apa yang mengandung #char. Jadi hanya cocok dengan jangkar . Untuk lebih lanjut tentang arti ini, lihat di sini
  • \\karena itu #adalah char khusus di pemilih css, jadi kita harus menghindarinya.

8
saya harus mengubah $('a')untuk $('a[href*=#]')hanya melayani jangkar url
okliv

2
@okliv Ini akan terlalu banyak ditayangkan, misalnya seperti tautan javascript <a href="javascript:$('#test').css('background-color', '#000')">Test</a>. Anda sebaiknya menggunakan $('a[href^=#]')untuk mencocokkan semua url yang dimulai dengan karakter hash.
Martin Braun

3
juga, '#' adalah karakter khusus dan perlu diloloskan seperti ini:a[href^=\\#]
QuinnFreedman

3
Ini menyebabkan tautan ke jangkar di halaman lain berhenti bekerja. Dipecahkan dengan menambahkan conditional if ($ ($ (this.hash) .selector) .length) {... smooth scroll. }
Liren

1
Bagaimana saya bisa menghidupkan ini ketika pertama kali bepergian ke halaman baru? Misalnya dengan mengklik: website.com/newpage/#section2. Saya ingin memuat halaman dan kemudian gulir ke bawah. Apakah itu mungkin?
Samyer

72

Panasnya baru di CSS3. Ini jauh lebih mudah daripada setiap metode yang tercantum pada halaman ini dan tidak memerlukan Javascript. Cukup masukkan kode di bawah ini ke Anda css dan semua tautan tiba-tiba menunjuk ke lokasi di dalam halaman Anda sendiri akan memiliki animasi bergulir mulus.

html{scroll-behavior:smooth}

Setelah itu, semua tautan yang mengarah ke div akan meluncur dengan lancar ke bagian-bagian tersebut.

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

Sunting: Bagi yang bingung dengan tag di atas. Pada dasarnya ini adalah tautan yang dapat diklik. Anda kemudian dapat memiliki tag div lain di suatu tempat di halaman web Anda suka

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

Dalam hal ini tautan akan dapat diklik dan akan menuju ke bagian apa pun, dalam hal ini adalah bagian kami yang kami sebut bagian.

BTW, saya menghabiskan berjam-jam mencoba untuk mendapatkan ini berfungsi. Menemukan solusinya di bagian komentar yang tidak jelas. Itu buggy dan tidak akan bekerja di beberapa tag. Tidak bekerja di dalam tubuh. Akhirnya berhasil ketika saya memasukkannya ke dalam html {} dalam file CSS.


4
Saya bisa sangat berguna tetapi mereka kekurangannya
Buzut

3
bagus, tapi hati-hati karena saat ini tidak didukung oleh Safari dan jelas oleh Explorer (03/2019)
Marco Romano

2
solusi yang bagus, hanya cakupannya dengan 74,8% terbatas. mungkin di masa depan
iepur1lla

1
Itu luar biasa. Terima kasih banyak.
Mikkel Fennefoss

1
Ini akan menjadi jawaban yang paling relevan di tahun-tahun mendatang.
Nurul Huda

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

ini bekerja sempurna untuk saya


1
"event.preventDefault ();" dapat menggantikan "return false;"
Andres Separated

Maaf untuk mengatakan, tetapi tidak bekerja dan tampil di halaman bernama jangkar dengan cepat tanpa kelancaran.
Kamlesh

18

Saya terkejut tidak ada yang memposting solusi asli yang juga menangani pembaruan hash lokasi browser agar sesuai. Ini dia:

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

Lihat tutorial: http://www.javascriptkit.com/javatutors/scrolling-html-bookmark-javascript.shtml

Untuk situs dengan header lengket, scroll-padding-topCSS dapat digunakan untuk memberikan offset.


1
Saya paling suka jawaban ini. Namun afais tidak ada cara untuk memberikan offset. Seperti yang akan diperlukan dalam kasus header tetap.
bskool

Sayangnya, dukungan buruk yang sama seperti untuk properti perilaku scroll CSS: developer.mozilla.org/en-US/docs/Web/CSS/…
Dmitry Nevzorov

15

Hanya CSS

html {
    scroll-behavior: smooth !important;
}

Yang perlu Anda tambahkan hanya ini. Sekarang perilaku pengguliran tautan internal Anda akan menjadi lancar seperti aliran-arus.

Catatan : Semua browser terbaru ( Opera, Chrome, Firefoxdll) mendukung fitur ini.

untuk pemahaman detail, baca artikel ini


1
bagus! Mengapa ini bukan jawaban yang diterima? kita tidak perlu semua javascript itu!
Trevor de Koekkoek

1
Ini bekerja dengan baik, ini harus menjadi jawaban yang diterima.
makam

Periksa dukungan browser di sini
Ryan Zhou

1
ini bekerja seperti pesona. tidak perlu untuk js
Navbro

Ini adalah solusi terbaik untuk pengguliran yang mulus yang pernah ada! Terima kasih!
yehanny

10

Saya sarankan Anda membuat kode umum ini:

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

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

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

return false;});

Anda dapat melihat artikel yang sangat bagus di sini: jquery-effet-smooth-scroll-defilement-fluide


9
Ini bukan generik, ini jQuery.
AnrDaemon

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
ini sepertinya hanya berfungsi untuk tautan anchor halaman dalam, tetapi tautan anchor dari halaman lain tidak berfungsi, misalnya situs
web.com/about-us/#who-we-are

5

Sudah ada banyak jawaban bagus di sini - namun semuanya kehilangan fakta bahwa jangkar kosong harus dikecualikan . Kalau tidak, skrip-skrip tersebut menghasilkan kesalahan JavaScript segera setelah jangkar kosong diklik.

Menurut pendapat saya, jawaban yang benar adalah seperti ini:

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

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

4

Menggunakan JQuery:

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


3

Jawaban yang diberikan berfungsi tetapi menonaktifkan tautan keluar. Di bawah versi dengan bonus tambahan memudahkan keluar (ayunan) dan menghormati tautan keluar.

$(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 untuk stop()remah url tidak berfungsi seperti yang diharapkan: tombol Kembali tidak membawa kembali, ini karena ketika remah diatur dalam url setelah animasi selesai. Lebih baik tanpa remah-remah di url, misalnya begitulah cara airbnb.
Eric

3

HTML

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

atau Dengan URL Lengkap absolut

<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

Browser modern sedikit lebih cepat akhir-akhir ini. SetInterval mungkin berfungsi. Fungsi ini bekerja dengan baik di Chrome dan Firefox hari ini. (Agak lambat dalam safari, tidak repot dengan IE)

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

Ada cara css untuk melakukan ini menggunakan perilaku scroll. Tambahkan properti berikut.

    scroll-behavior: smooth;

Dan itu dia. Tidak diperlukan 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: silakan periksa kompatibilitas browser.


ke wadah mana saya harus menggunakan scroll-behaviour: smooth;
CraZyDroiD

Jika ragu, tambahkan ke tag tubuh @CraZyDroiD
Santosh

2

Menambahkan ini:

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

entah bagaimana membatalkan offset vertikal

top - 72

di Firefox dan IE, ut bukan di Chrome. Pada dasarnya, halaman bergulir dengan lancar ke titik di mana ia harus berhenti berdasarkan offset, tetapi kemudian melompat ke bawah ke mana halaman akan pergi tanpa offset.

Itu menambahkan hash ke akhir url, tetapi menekan kembali tidak membawa Anda kembali ke atas, itu hanya menghilangkan hash dari url dan meninggalkan jendela penglihatan di mana ia duduk.

Inilah js lengkap yang saya gunakan:

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

Solusi ini juga akan berfungsi untuk URL berikut, tanpa memutus tautan anchor ke halaman yang berbeda.

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

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

dll.

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

Saya belum menguji ini di semua browser.


2

Ini akan membuatnya mudah untuk mengizinkan jQuery untuk melihat hash target Anda dan tahu kapan dan di mana harus berhenti.

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

Kode yang Diuji dan Diverifikasi

<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

Saya melakukan ini untuk jangkar href "/ xxxxx # asdf" dan "#asdf"

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

Inilah solusi yang saya terapkan untuk banyak tautan dan jangkar, untuk gulir yang lancar:

http://www.adriantomic.se/development/jquery-localscroll-tutorial/ jika Anda mengatur tautan navigasi di div navigasi dan menyatakan dengan struktur ini:

<a href = "#destinationA">

dan tujuan tag anchor yang sesuai adalah:

<a id = "destinationA">

Kemudian muat saja ini ke kepala dokumen:

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

Terima kasih kepada @Adriantomic


1

Jika Anda memiliki tombol sederhana di halaman untuk menggulir ke bawah ke div dan ingin tombol kembali berfungsi dengan melompat ke atas, tambahkan saja kode ini:

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

Ini dapat diperluas untuk melompat ke div yang berbeda juga, dengan membaca nilai hash, dan menggulir seperti Joseph Silbers menjawab.


1

Jangan pernah lupa bahwa fungsi offset () memberi posisi elemen Anda pada dokumen. Jadi ketika Anda perlu menggulir elemen Anda relatif terhadap induknya, Anda harus menggunakan ini;

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

Titik kuncinya adalah mendapatkan scrollTop dari scroll-div dan menambahkannya ke scrollTop. Jika Anda tidak akan melakukan fungsi posisi itu () selalu memberi Anda nilai posisi yang berbeda.


1

Anda dapat menggunakan window.scroll()dengan behavior: smoothdan topmengatur ke atas offset jangkar yang memastikan bahwa tag jangkar akan berada di bagian atas viewport.

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:

Anda bisa mengatur properti CSS scroll-behaviorke smooth(yang didukung sebagian besar browser modern) yang menyingkirkan kebutuhan untuk Javascript.


0

terima kasih sudah berbagi, Joseph Silber. Di sini solusi 2018 Anda sebagai ES6 dengan sedikit perubahan untuk menjaga perilaku standar (gulir ke atas):

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

Memerlukan jquery dan animasi untuk melabuhkan tag dengan nama yang ditentukan alih-alih id, sambil menambahkan hash ke url browser. Juga memperbaiki kesalahan dalam sebagian besar jawaban dengan jquery di mana tanda # tidak diawali dengan backslash yang lolos. Tombol kembali, sayangnya, tidak menavigasi kembali dengan benar ke tautan hash sebelumnya ...

$('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);
});
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.