Làm cách nào để cuộn trang HTML đến neo nhất định?


264

Tôi muốn làm cho trình duyệt cuộn trang đến một neo nhất định, chỉ bằng cách sử dụng JavaScript.

Tôi đã chỉ định một namehoặc idthuộc tính trong mã HTML của mình:

 <a name="anchorName">..</a>

hoặc là

 <h1 id="anchorName2">..</h1>

Tôi muốn có được hiệu ứng tương tự như bạn nhận được bằng cách điều hướng đến http://server.com/path#anchorName. Trang nên được cuộn để neo ở gần đầu của phần hiển thị của trang.

Câu trả lời:


349
function scrollTo(hash) {
    location.hash = "#" + hash;
}

Không yêu cầu jQuery nào cả!


91
Điều đó không thực sự cuộn mặc dù, nó chỉ nhảy. Tại thời điểm đó, bạn cũng có thể chỉ cần liên kết đến mỏ neo<a href="#anchorName">link</a>
Ryan

52
Lưu ý rằng điều này sẽ chỉ hoạt động một lần. Khi hàm băm được thiết lập, trang sẽ không cuộn sang cùng một hàm băm trừ khi bạn thay đổi nó thành hình nộm rồi đặt lại.
Cristian Vrabie

13
Bạn không nên sử dụng scrollTo, vì nó đã được sử dụng bởi đối tượng cửa sổ toàn cầu. Ngoài ra, tham số không nên được đặt tên băm, bởi vì location.hash cũng được xác định. Bạn có thể sử dụng mã này:function scrollToHash(hashName) { location.hash = "#" + hashName; }
Markus Zeller

3
@MarkusZeller, tại sao tham số không được gọi là hàm băm? Nó không va chạm với vị trí, phải không?
Gherman

3
điều này không cuộn nếu bạn đặt "cuộn-behavior: smooth;" trên phần tử html
xếp chồng

225

Cách đơn giản hơn:

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

22
Lúc đầu, tôi nghĩ Mandx đang bị troll, sau đó tôi đã thử nó và nó đã hoạt động. Ngoài tôi, tôi chưa bao giờ bắt gặp phương pháp này trước đây. Tài liệu Mozilla cho phương pháp này . Ngoài ra, có vẻ như điều này sẽ được hỗ trợ rất tốt trong các trình duyệt.
Jonathan Dumaine

2
Tôi đã có rất nhiều vấn đề với các giải pháp jquery không cuộn. Điều này đã tiết kiệm cho tôi rất nhiều thất vọng.
NuclePeon

1
CẢNH BÁO! Phương pháp này có thể có vấn đề nếu một div ở trên nó chứa các phần tử nổi và không thể xác định kích thước của nó một cách dễ dàng.
vogomatix

5
Đây là một giải pháp sạch, tuy nhiên hiện tại nó không cho phép bất kỳ tinh chỉnh nào, nó thực hiện một cuộn cứng. Có một tham số thử nghiệm scrollIntoViewOptionsbehavior: "smooth"tùy chọn, nhưng hiện tại nó chỉ tương thích với Firefox.
rocha

Làm thế nào để hoạt hình này?
SkuraZZ

124

Bạn có thể sử dụng jQuery .animate () , .offset ()scrollTop. Giống

$(document.body).animate({
    'scrollTop':   $('#anchorName2').offset().top
}, 2000);

liên kết ví dụ: http://jsbin.com/unasi3/edit

Nếu bạn không muốn làm động, hãy sử dụng .scrollTop () như

$(document.body).scrollTop($('#anchorName2').offset().top);

hoặc javascripts location.hashgiống như

location.hash = '#' + anchorid;

1
Theo như việc tạo một bộ chọn để tìm <h1 id="anchorName">hoặc một <a name="anchorName">, sử dụng $('#'+hash+',a[name='+hash+']')hoặc tối ưu hóa một chút $(document.getElementById(hash) || 'a[name='+hash+']')sẽ tìm kiếm phần tử theo id trước và chỉ tìm kiếm một phần tử nếu không tìm thấy.
gnarf

@gnarf - Không cần phải tối ưu hóa các bộ chọn '#' trong jQuery - chúng đã được tối ưu hóa cho bạn. Khá dễ dàng để xem bạn đã đọc mã nguồn jQuery chưa.
CodeJoust

3
@CodeJoust - Tôi thuộc nhóm jQuery, tôi đã đọc nó nhiều lần và có $("#selector")được tối ưu hóa nhưng $("#selector,a[name='selector']")sẽ không được tối ưu hóa nhanh như vậy. Tôi cho rằng nhận xét 2,5 năm tuổi của tôi là một âm thanh hơi lạ. "Tối ưu hóa" là tránh a[name='selector']tìm kiếm nếu tìm thấy id, không tối ưu hóa tìm kiếm id.
gnarf

1
Tôi đã có một số may mắn với cách tiếp cận này: <a data-hash="about"> Giới thiệu </a> <script> $ ("[data-hash]"). Click (function () {var data = $ (this) .attr ("data-hash"); $ (document.body) .animate ({'scrollTop': $ ("#" + data) .offset (). top}, 500);}); </ script>
Jazzy

32

Giải pháp tuyệt vời của jAndy, nhưng cuộn trơn tru dường như có vấn đề khi làm việc trong firefox.

Viết nó theo cách này cũng hoạt động trong Firefox.

(function($) {
    $(document).ready(function() {
         $('html, body').animate({
           'scrollTop':   $('#anchorName2').offset().top
         }, 2000);
    });
})(jQuery);

Trong bản phát hành Chrome mới nhất, đây là phương pháp duy nhất tôi thấy có hiệu quả nhất quán. Cảm ơn vì tiền hỗ trợ!
gabious

32

2018-2020 js tinh khiết:

Có một cách rất thuận tiện để cuộn đến phần tử:

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

Nhưng theo tôi hiểu thì anh ta không có sự hỗ trợ tốt như các lựa chọn dưới đây.

nhập mô tả hình ảnh ở đây

Tìm hiểu thêm về phương pháp.


Nếu cần thiết là phần tử nằm ở trên cùng:

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

Ví dụ trình diễn trên Codepen


Nếu bạn muốn phần tử nằm ở trung tâm:

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

Ví dụ trình diễn trên Codepen


Ủng hộ:

Làm thế nào để làm gì đó

Họ viết đó scrolllà phương pháp tương tự nhưscrollTo , nhưng hỗ trợ cho thấy tốt hơn trong scrollTo.

Thêm về phương pháp


Giải pháp này hoạt động rất rất tốt! Cám ơn vì đã chia sẻ!
ngày

29

Một giải pháp javascript thuần túy không có JQuery. Đã thử nghiệm trên Chrome & Ie, không được thử nghiệm trên 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;
  }
}

bản demo: https://jsfiddle.net/jd7q25hg/12/


1
Xin lỗi vì đã bình luận về một chủ đề cũ nhưng điều này phù hợp nhất với tôi vì dự án của tôi không sử dụng JQuery. Vấn đề duy nhất tôi nhận thấy là nó bị mất 5 pixel hoặc hơn nếu bạn cuộn lên trên cùng.
AntBirch

Rất mới mẻ để xem một phiên bản js tinh khiết. Tôi dạy các sinh viên luôn nhìn dưới mui xe và hiểu JQuery làm gì cho họ, vì vậy đây là một ví dụ hay.
Dave Everitt

2
Đây phải là câu trả lời được chấp nhận: đó là một ví dụ thuần js VÀ nó đạt được hiệu ứng hoạt hình cuộn mong muốn. Tôi đã điều chỉnh giá trị thời gian chờ thành 20 và nó hoạt động hoàn hảo.
Mark Barrasso

Cảm ơn bạn Tôi yêu các giải pháp javascript thuần túy
R01010010

2
Hoạt động trong iOS chỉ cần thử nghiệm nó.
Debbie Kurth

23

Năm 2018, bạn không cần jQuery cho một cái gì đó đơn giản như thế này. Việc xây dựng trong scrollIntoView()phương pháp hỗ trợ "behavior " tài sản để di chuyển thông suốt đến bất kỳ yếu tố trên trang. Bạn thậm chí có thể cập nhật URL trình duyệt bằng hàm băm để làm cho nó có thể đánh dấu được.

Từ hướng dẫn này về cách cuộn Dấu trang HTML , đây là một cách tự nhiên để thêm cuộn dễ dàng vào tất cả các liên kết neo trên trang của bạn:

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

2
Câu trả lời tuyệt vời giúp loại bỏ sự phụ thuộc vào jQuery
zai chang

Ồ Hoạt động tuyệt vời!
Alexandru Trandafir Catalin

14

Di chuyển nhẹ nhàng đến vị trí thích hợp (2019)

Nhận phối hợp chính xác y và sử dụngwindow.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'});

Có bù

scrollIntoViewcũng là một lựa chọn tốt nhưng nó có thể không hoạt động hoàn hảo trong một số trường hợp. Ví dụ khi bạn cần bù thêm . Với scrollTobạn chỉ cần thêm phần bù như thế này:

const yOffset = -10; 

window.scrollTo({top: y + yOffset, behavior: 'smooth'});

Tôi nghĩ bạn nên thêm phần sau vào tệp kiểu CSS: css html { scroll-behavior: smooth; }
parismiguel

5
$(document).ready ->
  $("a[href^='#']").click ->
    $(document.body).animate
      scrollTop: $($(this).attr("href")).offset().top, 1000

5

Giải pháp từ CSS-Tricks không còn hoạt động trong jQuery 2.2.0. Nó sẽ đưa ra một lỗi chọn:

Lỗi thời gian chạy JavaScript: Lỗi cú pháp, biểu thức không được nhận dạng: a [href * = #]: không ([href = #])

Tôi đã sửa nó bằng cách thay đổi bộ chọn. Đoạn trích đầy đủ là đây:

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

4

Hầu hết các câu trả lời là phức tạp không cần thiết.

Nếu bạn chỉ muốn nhảy tới phần tử mục tiêu, bạn không cần JavaScript:

# the link:
<a href="#target">Click here to jump.</a>

# target element:
<div id="target">Any kind of element.</div>

Nếu bạn muốn cuộn đến mục tiêu một cách sinh động , vui lòng tham khảo câu trả lời của @ Shahil.


Đôi khi, bạn cần phải làm điều đó một cách linh hoạt, mặc dù; tức là thông qua không có hành động trực tiếp của người dùng. Tôi tin rằng đó là những gì OP muốn.
jpaugh

1
Vâng, rõ ràng OP đã biết về chức năng liên kết neo.
isherwood

4

Những công việc này:

$('.scroll').on("click", function(e) {

  e.preventDefault();

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

  $("html, body").animate({

    'scrollTop':   $(dest).offset().top

  }, 2000);

});

https://jsfiddle.net/68pnkfgd/

Chỉ cần thêm lớp 'cuộn' vào bất kỳ liên kết nào bạn muốn tạo hiệu ứng


Đẹp, đơn giản để sử dụng giải pháp. Cảm ơn!
Smitty-Werben-Jager-Manjenson

3

Đây là một kịch bản làm việc sẽ cuộn trang đến neo. Để thiết lập, chỉ cần cung cấp cho liên kết neo một id khớp với thuộc tính tên của neo mà bạn muốn cuộn đến.

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

2

Tôi biết đây là câu hỏi thực sự cũ, nhưng tôi đã tìm thấy một giải pháp jQuery đơn giản và dễ dàng trong các thủ thuật css . Đó là cái tôi đang sử dụng.

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

1
Bộ chọn đang ném một ngoại lệ trong jquery 2.2.0. 0x800a139e - Lỗi thời gian chạy JavaScript: Lỗi cú pháp, biểu thức không được nhận dạng: a [href * = #]: không ([href = #])
Bill Shihara

2

jQuery("a[href^='#']").click(function(){
    jQuery('html, body').animate({
        scrollTop: jQuery( jQuery(this).attr('href') ).offset().top
    }, 1000);
    return false;
});


2

một giải pháp vue2 ... thêm thuộc tính dữ liệu đơn giản để buộc cập nhật

  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 - works in html5 only */
 html, body {
     scroll-behavior: smooth;
 }

0

cách dễ nhất để làm cho trình duyệt cuộn trang đến một neo nhất định là nhập kiểu style.css * {scroll-behavior: smooth;} và trong điều hướng html của bạn, hãy sử dụng #NameOfTheSection

*{scroll-behavior: smooth;}
<a href="#scroll-to">Home<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>

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.