Jak przewinąć stronę HTML do danej kotwicy?

264

Chciałbym, aby przeglądarka przewijała stronę do danej kotwicy, używając tylko JavaScript.

I została określona namelub idatrybut w moim kod HTML:

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

lub

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

Chciałbym uzyskać taki sam efekt, jak przy nawigowaniu do http://server.com/path#anchorName. Stronę należy przewinąć, aby kotwica znajdowała się w górnej części widocznej części strony.

Juha Syrjälä
źródło

Odpowiedzi:

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

W ogóle nie jest wymagane jQuery!

Dean Harding
źródło
91
To tak naprawdę nie przewija się, tylko skacze. W tym momencie równie dobrze możesz po prostu link do kotwicy<a href="#anchorName">link</a>
Ryan
52
Pamiętaj, że zadziała to tylko raz. Po ustawieniu skrótu strona nie przewinie się do tego samego skrótu, chyba że zmienisz go na fikcyjny, a następnie ustawisz ponownie.
Cristian Vrabie
13
Nie należy używać scrollTo, ponieważ jest on już używany przez globalny obiekt okna. Nie należy również nazywać parametru hash, ponieważ zdefiniowano także parametr location.hash. Możesz użyć tego kodu:function scrollToHash(hashName) { location.hash = "#" + hashName; }
Markus Zeller
3
@MarkusZeller, dlaczego parametr nie powinien być nazywany skrótem? To nie koliduje z lokalizacją, prawda?
Gherman,
3
przewija się, jeśli ustawisz „zachowanie przewijania: gładkie;” na elemencie HTML
układacze
225

O wiele prościej:

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();
Armando Pérez Marqués
źródło
22
Na początku myślałem, że Mandx trolluje, a potem spróbowałem i zadziałało. Poza mną, jak nigdy wcześniej nie spotkałem tej metody. Mozilla Docs dla tej metody . Wydaje się również, że będzie to bardzo dobrze obsługiwane w przeglądarkach.
Jonathan Dumaine
2
Miałem wiele problemów z nie przewijaniem rozwiązań jquery. To zaoszczędziło mi dużo frustracji.
NuclearPeon
1
OSTRZEŻENIE! Ta metoda może mieć problemy, jeśli div powyżej zawiera elementy pływające i nie może łatwo określić jej rozmiaru.
vogomatix
5
Jest to czyste rozwiązanie, jednak na razie nie pozwala na żadne modyfikacje, robi ciężkie przewijanie. Istnieje parametr eksperymentalny scrollIntoViewOptionsz behavior: "smooth"opcją, ale obecnie jest zgodny tylko z Firefoksem.
rocha
Jak to animować?
SkuraZZ
124

Możesz użyć jQuerys .animate () , .offset () i scrollTop. Lubić

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

przykładowy link: http://jsbin.com/unasi3/edit

Jeśli nie chcesz animować, użyj .scrollTop () jak

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

lub javascripts native location.hashjak

location.hash = '#' + anchorid;
jAndy
źródło
1
Jeśli chodzi o tworzenie selektora w celu znalezienia <h1 id="anchorName">lub <a name="anchorName">, użyj $('#'+hash+',a[name='+hash+']')lub lekko zoptymalizowany, $(document.getElementById(hash) || 'a[name='+hash+']')który najpierw wyszuka element według identyfikatora i ucieka się do wyszukiwania a tylko wtedy, gdy nie zostanie znaleziony.
gnarf
@gnarf - Nie ma potrzeby optymalizacji selektorów „#” w jQuery - są już dla Ciebie zoptymalizowane. Dość łatwo jest sprawdzić, czy przeczytałeś kod źródłowy jQuery.
CodeJoust
3
@CodeJoust - Jestem w zespole jQuery, czytałem to wiele razy i tak $("#selector")jest zoptymalizowany, ale $("#selector,a[name='selector']")nie przejdzie takich samych optymalizacji tak szybko. Przypuszczam, że mój komentarz z 2,5 roku jest trochę dziwny. „Optymalizacja” pozwala uniknąć a[name='selector']wyszukiwania, jeśli znajdzie identyfikator, a nie optymalizuje wyszukiwanie identyfikatora.
gnarf
1
Miałem trochę szczęścia z tym podejściem: <a data-hash="about"> Informacje </a> <script> $ („[data-hash]”). Click (function () {var data = $ (this) .attr ("hash danych"); $ (document.body) .animate ({'scrollTop': $ ("#" + data) .offset (). top}, 500);}); </script>
Jazzy
32

Świetne rozwiązanie jAndy, ale wydaje się, że płynne przewijanie ma problemy z działaniem w firefoxie.

Pisanie w ten sposób działa również w przeglądarce Firefox.

(function($) {
    $(document).ready(function() {
         $('html, body').animate({
           'scrollTop':   $('#anchorName2').offset().top
         }, 2000);
    });
})(jQuery);
5hahiL
źródło
W najnowszej wersji Chrome jest to jedyna metoda, którą znalazłem, która konsekwentnie działa. Dzięki za wskazówkę!
wredny
32

2018-2020 Pure js:

Istnieje bardzo wygodny sposób przewijania do elementu:

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

Ale o ile rozumiem, nie ma on tak dobrego wsparcia, jak poniższe opcje.

wprowadź opis zdjęcia tutaj

Dowiedz się więcej o metodzie.


Jeśli konieczne jest, aby element był na górze:

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

Przykład demonstracyjny na Codepen


Jeśli chcesz, aby element był na środku:

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

Przykład demonstracyjny na Codepen


Wsparcie:

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

Piszą, że scrolljest to ta sama metoda scrollTo, ale wsparcie pokazuje się lepiej scrollTo.

Więcej o metodzie

Илья Зеленько
źródło
To rozwiązanie działa bardzo dobrze! Dzięki za udostępnienie!
wredny
29

Czyste rozwiązanie javascript bez JQuery. Testowane na Chrome i Ie, nie testowane na 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;
  }
}

demo: https://jsfiddle.net/jd7q25hg/12/

Michael Whinfrey
źródło
1
Przepraszamy za komentowanie starego tematu, ale to działa najlepiej dla mnie, ponieważ mój projekt nie używa JQuery. Jedyny problem, jaki zauważyłem, to to, że brakuje około 5 pikseli, jeśli przewiniesz na samą górę.
AntBirch
Bardzo odświeżające, aby zobaczyć czystą wersję js. Uczę studentów, aby zawsze patrzyli pod maską i rozumieli, co robi dla nich JQuery, więc jest to dobry przykład.
Dave Everitt
2
To powinna być zaakceptowana odpowiedź: jest to czysty przykład ORAZ osiąga pożądany efekt animacji przewijania. Ustawiłem wartość limitu czasu na 20 i działa bezbłędnie.
Mark Barrasso,
Dziękuję Uwielbiam czyste rozwiązania JavaScript
R01010010
2
Działa w IOS właśnie go przetestowałem.
Debbie Kurth,
23

W 2018 roku nie potrzebujesz jQuery dla czegoś tak prostego. Wbudowana scrollIntoView()metoda obsługuje behaviorwłaściwość „ ” do płynnego przewijania dowolnego elementu na stronie. Możesz nawet zaktualizować adres URL przeglądarki za pomocą skrótu, aby uczynić go bukmacherskim.

Z tego samouczka na temat przewijania zakładek HTML , oto natywny sposób automatycznego dodawania płynnego przewijania do wszystkich linków zakotwiczenia na stronie:

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()
    })
}
ptysie kokosowe
źródło
2
Doskonała odpowiedź, która usuwa zależność od jQuery
zai chang 1'18
Łał! Działa niesamowicie!
Alexandru Trandafir Catalin
14

Płynnie przewiń do właściwej pozycji (2019)

Uzyskaj poprawną y współrzędną i użyjwindow.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'});

Z przesunięciem

scrollIntoViewjest również dobrą opcją, ale w niektórych przypadkach może nie działać idealnie. Na przykład, gdy potrzebujesz dodatkowego przesunięcia . Po scrollToprostu musisz dodać to przesunięcie w następujący sposób:

const yOffset = -10; 

window.scrollTo({top: y + yOffset, behavior: 'smooth'});
Arsenij II
źródło
Myślę, że powinieneś dodać do pliku CSS: css html { scroll-behavior: smooth; }
parismiguel
5
$(document).ready ->
  $("a[href^='#']").click ->
    $(document.body).animate
      scrollTop: $($(this).attr("href")).offset().top, 1000
kaktusy
źródło
5

Rozwiązanie z CSS-Tricks nie działa już w jQuery 2.2.0. Wyrzuci błąd selektora:

Błąd czasu wykonania JavaScript: błąd składni, nierozpoznane wyrażenie: a [href * = #]: not ([href = #])

Naprawiłem to, zmieniając selektor. Pełny fragment kodu jest następujący:

$(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;
    }
  }
 });
});
Bill Shihara
źródło
4

Większość odpowiedzi jest niepotrzebnie skomplikowana.

Jeśli chcesz tylko przejść do elementu docelowego, nie potrzebujesz JavaScript:

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

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

Jeśli chcesz animować przewijanie do celu , zapoznaj się z odpowiedzią @ Shahil.

Brian
źródło
Czasami jednak trzeba to robić dynamicznie; tzn. poprzez brak bezpośredniego działania użytkownika. Uważam, że tego właśnie chce OP.
jpaugh
1
Tak, najwyraźniej OP już wiedział o funkcjonalności linku kotwiczącego.
isherwood,
4

To działa:

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

  e.preventDefault();

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

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

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

  }, 2000);

});

https://jsfiddle.net/68pnkfgd/

Po prostu dodaj klasę „przewiń” do wszystkich linków, które chcesz animować

Chuck Le Butt
źródło
Ładne, proste w użyciu rozwiązanie. Dzięki!
Smitty-Werben-Jager-Manjenson
3

To działający skrypt, który przewinie stronę do kotwicy. Aby skonfigurować, wystarczy podać link do kotwicy id, który odpowiada atrybutowi nazwy kotwicy, do której chcesz przewinąć.

<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>
Rudy Lister
źródło
2

Wiem, że to pytanie jest naprawdę stare, ale znalazłem łatwe i proste rozwiązanie jQuery w trikach css . Tego właśnie używam.

$(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;
      }
    }
  });
});
Horacio
źródło
1
Selektor zgłasza wyjątek w jquery 2.2.0. 0x800a139e - Błąd czasu wykonania JavaScript: Błąd składni, nierozpoznane wyrażenie: a [href * = #]: not ([href = #])
Bill Shihara
2

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

Adam Pery
źródło
2

rozwiązanie vue2 ... dodaj prostą właściwość danych, aby po prostu wymusić aktualizację

  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;
 }
Yordan Georgiev
źródło
0

najłatwiejszym sposobem, aby przeglądarka przewinęła stronę do danej kotwicy, jest wpisanie swojego style.css * {przewijanie: gładkie;}, a w nawigacji HTML użyj #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>

eslam elameen
źródło