วิธีการเลื่อนหน้า HTML เพื่อยึดที่กำหนด?


264

ฉันต้องการให้เบราว์เซอร์เลื่อนหน้าไปที่จุดยึดที่กำหนดเพียงใช้ JavaScript

ฉันได้ระบุnameหรือidแอตทริบิวต์ในรหัส HTML ของฉัน:

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

หรือ

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

http://server.com/path#anchorNameฉันต้องการที่จะได้รับผลเช่นเดียวกับที่คุณจะได้รับโดยไปที่ หน้าควรเลื่อนเพื่อให้สมออยู่ใกล้กับส่วนบนของส่วนที่มองเห็นได้ของหน้า

คำตอบ:


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

ไม่ต้องใช้ jQuery เลย!


91
ที่ไม่ได้เลื่อนจริง ๆ เพียงแค่กระโดด ณ จุดนี้คุณอาจเชื่อมโยงไปยังจุดยึด<a href="#anchorName">link</a>
Ryan

52
โปรดทราบว่านี่จะใช้งานได้เพียงครั้งเดียว เมื่อตั้งค่าแฮชแล้วเพจจะไม่เลื่อนไปที่แฮชเดียวกันเว้นแต่คุณจะเปลี่ยนเป็นดัมมี่จากนั้นตั้งค่าอีกครั้ง
Cristian Vrabie

13
คุณไม่ควรใช้ scrollTo เพราะมันถูกใช้โดยวัตถุหน้าต่างทั่วโลกแล้ว นอกจากนี้พารามิเตอร์ไม่ควรตั้งชื่อแฮชเนื่องจาก location.hash ถูกกำหนดเช่นกัน คุณอาจใช้รหัสนี้:function scrollToHash(hashName) { location.hash = "#" + hashName; }
Markus Zeller

3
@ MarkusZeller ทำไมพารามิเตอร์ไม่ควรเรียกว่าแฮช มันไม่ได้ชนกับที่ตั้งใช่ไหม?
Gherman

3
สิ่งนี้จะเลื่อนหากคุณตั้งค่า "scroll-behavior: smooth;" ในองค์ประกอบ html
stackers

225

วิธีที่ง่ายกว่า:

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
ตอนแรกฉันคิดว่ามันซ์หลอกตัวเองจากนั้นฉันก็ลองทำมันและมันก็ใช้ได้ เกินกว่าที่ฉันไม่เคยเจอวิธีนี้มาก่อน Mozilla Docs สำหรับวิธีนี้ นอกจากนี้ดูเหมือนว่าสิ่งนี้จะได้รับการสนับสนุนเป็นอย่างดีในเบราว์เซอร์
Jonathan Dumaine

2
ฉันมีปัญหามากมายเกี่ยวกับการแก้ปัญหา jquery ที่ไม่ได้เลื่อน สิ่งนี้ทำให้ฉันหงุดหงิดมาก
NuclearPeon

1
คำเตือน! วิธีการนี้อาจมีปัญหาหากกองข้างต้นมีองค์ประกอบลอยและไม่สามารถกำหนดขนาดได้อย่างง่ายดาย
vogomatix

5
นี่เป็นวิธีการแก้ปัญหาที่สะอาด แต่ ณ ตอนนี้มันไม่อนุญาตให้ปรับแต่งใด ๆ มันเป็นการเลื่อนที่ยาก มีพารามิเตอร์ทดลองscrollIntoViewOptionsที่มีbehavior: "smooth"ตัวเลือก แต่ปัจจุบันสามารถใช้งานได้กับ Firefox เท่านั้น
rocha

วิธีทำภาพเคลื่อนไหวนี้?
SkuraZZ

124

คุณสามารถใช้ jQuerys .animate () , .offset ()scrollTopและ ชอบ

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

ลิงค์ตัวอย่าง: http://jsbin.com/unasi3/edit

หากคุณไม่ต้องการใช้ภาพเคลื่อนไหว. scrollTop ()เช่น

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

หรือจาวาสคริปต์location.hashเช่น

location.hash = '#' + anchorid;

1
เท่าที่มีการสร้างตัวเลือกเพื่อค้นหา<h1 id="anchorName">หรือ<a name="anchorName">ใช้$('#'+hash+',a[name='+hash+']')หรือปรับให้เหมาะสมเล็กน้อย$(document.getElementById(hash) || 'a[name='+hash+']')ซึ่งจะค้นหาองค์ประกอบตามรหัสก่อนและหันไปค้นหาสิ่งเดียวถ้าไม่พบ
แคระ

@gnarf - ไม่จำเป็นต้องเพิ่มประสิทธิภาพตัวเลือก '#' ใน jQuery - สิ่งเหล่านี้เหมาะสำหรับคุณแล้ว มันค่อนข้างง่ายที่จะดูว่าคุณได้อ่านซอร์สโค้ด jQuery หรือไม่
CodeJoust

3
@CodeJoust - ฉันอยู่ในทีม jQuery ฉันได้อ่านหลายครั้งและใช่ได้$("#selector")รับการปรับให้เหมาะสม แต่$("#selector,a[name='selector']")จะไม่ผ่านการปรับแต่งแบบเดียวกันให้เร็วที่สุด ฉันคิดว่าความคิดเห็น 2.5 ปีของฉันเป็นเสียงแปลก ๆ "การปรับให้เหมาะสม" กำลังหลีกเลี่ยงการa[name='selector']ค้นหาหากพบ id ไม่ปรับการค้นหา id ให้เหมาะสม
แคระ

1
ฉันโชคดีกับวิธีการนี้: <a data-hash="about"> เกี่ยวกับ </a> <script> $ ("[data-hash]") คลิก (ฟังก์ชัน () {var data = $ (นี่) .attr ("data-hash"); $ (document.body) .animate ({'scrollTop': $ ("#" + data) .offset (). top}, 500);}); </script>
Jazzy

32

วิธีแก้ปัญหาที่ยอดเยี่ยมโดย jAndy แต่การเลื่อนที่ราบรื่นดูเหมือนจะมีปัญหาในการทำงานของ Firefox

การเขียนวิธีนี้ทำงานใน Firefox เช่นกัน

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

ใน Chrome รุ่นล่าสุดนี้เป็นวิธีเดียวที่ฉันได้พบว่าทำงานได้อย่างต่อเนื่อง ขอบคุณสำหรับทิป!
gaborous

32

2018-2020 เพียว js:

มีวิธีที่สะดวกมากในการเลื่อนไปที่องค์ประกอบ:

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

แต่เท่าที่ฉันเข้าใจเขาไม่ได้รับการสนับสนุนที่ดีเช่นตัวเลือกด้านล่าง

ป้อนคำอธิบายรูปภาพที่นี่

เรียนรู้เพิ่มเติมเกี่ยวกับวิธีการ


หากจำเป็นต้องมีองค์ประกอบอยู่ด้านบน:

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

ตัวอย่างการสาธิตบน Codepen


หากคุณต้องการให้องค์ประกอบอยู่ตรงกลาง:

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

ตัวอย่างการสาธิตบน Codepen


สนับสนุน:

введитесюдаописаниеизображения

พวกเขาเขียนว่าscrollเป็นวิธีการเดียวกับแต่การสนับสนุนการแสดงที่ดีขึ้นในscrollToscrollTo

เพิ่มเติมเกี่ยวกับวิธีการ


วิธีนี้ใช้ได้ดีมาก! ขอบคุณสำหรับการแบ่งปัน!
gaborous

29

วิธีการแก้ปัญหาจาวาสคริปต์ที่บริสุทธิ์โดยไม่ต้อง JQuery ทดสอบบน Chrome & Ie ไม่ใช่ทดสอบบน 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;
  }
}

ตัวอย่าง: https://jsfiddle.net/jd7q25hg/12/


1
ขออภัยในการแสดงความคิดเห็นในหัวข้อเก่า แต่สิ่งนี้ดีที่สุดสำหรับฉันเนื่องจากโครงการของฉันไม่ได้ใช้ JQuery ปัญหาเดียวที่ฉันสังเกตเห็นคือมันขาดหายไป 5 พิกเซลหรือมากกว่านั้นถ้าคุณเลื่อนไปด้านบนสุด
AntBirch

สดชื่นมากที่จะเห็นรุ่น js บริสุทธิ์ ฉันสอนให้นักเรียนดูใต้กระโปรงหน้ารถเสมอและเข้าใจสิ่งที่ JQuery ทำเพื่อพวกเขาดังนั้นนี่เป็นตัวอย่างที่ดี
Dave Everitt

2
นี่ควรเป็นคำตอบที่ได้รับการยอมรับ: มันเป็นตัวอย่าง js บริสุทธิ์และบรรลุเอฟเฟ็กต์ภาพเคลื่อนไหวการเลื่อนที่ต้องการ ฉันปรับค่าการหมดเวลาเป็น 20 และทำงานได้อย่างไม่มีที่ติ
Mark Barrasso

ขอบคุณฉันรักโซลูชั่นจาวาสคริปต์ที่บริสุทธิ์
R01010010

2
ทำงานใน IOS เพียงทดสอบ
Debbie Kurth

23

ในปี 2018 คุณไม่ต้องการ jQuery สำหรับสิ่งที่ง่ายเช่นนี้ scrollIntoView()วิธีการในตัวรองรับbehaviorคุณสมบัติ "" เพื่อเลื่อนไปยังองค์ประกอบใด ๆ ในหน้าได้อย่างราบรื่น คุณสามารถอัปเดต URL เบราว์เซอร์ด้วยแฮชเพื่อให้สามารถคั่นหน้าได้

จากบทช่วยสอนนี้เกี่ยวกับการเลื่อนที่คั่นหน้า HTMLนี่เป็นวิธีดั้งเดิมในการเพิ่มการเลื่อนอย่างนุ่มนวลไปยังลิงก์จุดยึดทั้งหมดบนหน้าของคุณโดยอัตโนมัติ:

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
คำตอบที่ยอดเยี่ยมที่จะลบการพึ่งพา jQuery
zai chang

ว้าว! ทำงานได้ยอดเยี่ยม!
Alexandru Trandafir Catalin

14

เลื่อนไปที่ตำแหน่งที่เหมาะสมอย่างราบรื่น (2019)

รับการประสานงานและการใช้งานที่ถูกต้อง ywindow.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'});

ด้วยค่าชดเชย

scrollIntoViewเป็นตัวเลือกที่ดีเช่นกัน แต่มันอาจไม่ทำงานอย่างสมบูรณ์ในบางกรณี ตัวอย่างเช่นเมื่อคุณต้องการเพิ่มเติมชดเชย เมื่อscrollToคุณต้องเพิ่มออฟเซ็ตแบบนี้:

const yOffset = -10; 

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

ฉันคิดว่าคุณควรเพิ่มสิ่งต่อไปนี้ลงในไฟล์สไตล์ CSS: css html { scroll-behavior: smooth; }
parismiguel


5

โซลูชันจาก CSS-Tricks ไม่สามารถใช้งานได้ใน jQuery 2.2.0 อีกต่อไป มันจะโยนข้อผิดพลาดของตัวเลือก:

ข้อผิดพลาดรันไทม์ JavaScript: ข้อผิดพลาดทางไวยากรณ์, นิพจน์ที่ไม่รู้จัก: a [href * = #]: not ([href = #])

ฉันแก้ไขโดยเปลี่ยนตัวเลือก ตัวอย่างเต็มคือ:

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

คำตอบส่วนใหญ่มีความซับซ้อนเกินความจำเป็น

หากคุณต้องการข้ามไปยังองค์ประกอบเป้าหมายคุณไม่จำเป็นต้องใช้ JavaScript:

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

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

หากคุณต้องการเลื่อนไปยังเป้าหมายแบบเคลื่อนไหวโปรดดูคำตอบของ @ Shahil


บางครั้งคุณต้องทำแบบไดนามิกแม้ว่า; เช่นผ่านการกระทำโดยตรงของผู้ใช้ ฉันเชื่อว่าเป็นสิ่งที่ OP ต้องการ
jpaugh

1
ใช่เห็นได้ชัดว่า OP ทราบแล้วเกี่ยวกับการทำงานของลิงค์ลิงค์
isherwood

4

งานนี้:

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

  e.preventDefault();

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

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

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

  }, 2000);

});

https://jsfiddle.net/68pnkfgd/

เพียงเพิ่มคลาส 'เลื่อน' ลงในลิงก์ใด ๆ ที่คุณต้องการทำให้เคลื่อนไหว


วิธีแก้ปัญหาที่ดีใช้งานง่าย ขอบคุณ!
Smitty-Werben-Jager-Manjenson

3

นี่คือสคริปต์ทำงานที่จะเลื่อนหน้าไปที่จุดยึด หากต้องการตั้งค่าเพียงระบุสมอลิงก์ที่ตรงกับแอตทริบิวต์ชื่อของจุดยึดที่คุณต้องการเลื่อนไป

<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

ฉันรู้ว่านี้คือคำถามเก่าจริงๆ แต่ผมพบว่าวิธีการแก้ปัญหา jQuery ง่ายและง่ายในCSS เทคนิค นั่นคือสิ่งที่ฉันกำลังใช้อยู่

$(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
ตัวเลือกกำลังส่งข้อยกเว้นใน jquery 2.2.0 0x800a139e - ข้อผิดพลาดรันไทม์ JavaScript: ข้อผิดพลาดทางไวยากรณ์, นิพจน์ที่ไม่รู้จัก: a [href * = #]: ไม่ ([href = #])
Bill Shihara


2

โซลูชัน vue2 ... เพิ่มคุณสมบัติของข้อมูลอย่างง่าย ๆ เพื่อบังคับให้มีการอัปเดต

  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

วิธีที่ง่ายที่สุดในการทำให้เบราว์เซอร์เลื่อนหน้าไปที่จุดยึดที่กำหนดคือพิมพ์ style.css ของคุณ * {scroll-behavior: smooth;} และในการนำทาง html ของคุณใช้ #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>

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.