
🔧 JQuery — płynne przewijanie do kotwicy przy przejściu z innej strony
Dodał Pan kotwicę na stronie, wpisał #section w URL i oczekuje Pan płynnego, eleganckiego przejścia. Użytkownik klika z innej strony, przeglądarka uczciwie podstawia hash... i szarpnięciem przeskakuje w docelowe miejsce. Żadnego przewijania. Po prostu natychmiastowy skok.
Problem polega na tym, że przeglądarka domyślnie obsługuje hash natychmiast, zanim DOM jest w pełni gotowy, a skrypty zdążą przechwycić zdarzenie. A gdy użytkownik wchodzi z zewnętrznego linku, Pana procedura obsługi click w ogóle się nie uruchamia, nie było zdarzenia kliknięcia, było bezpośrednie przejście przez URL.
Zebraliśmy dwa sprawdzone rozwiązania jQuery: podstawowy skrypt do prostych przypadków i zaawansowany wariant z obsługą kliknięć, ładowania strony oraz omijaniem konfliktów. Oba przetestowane na rzeczywistych projektach i działają z aktualnymi wersjami jQuery.
💡 Szybki przegląd:
- Zapisanie hasha z URL do zmiennej tymczasowej
- Wyczyszczenie
location.hash, aby przeglądarka nie skoczyła szarpnięciem - Przewinięcie do kotwicy przez
animate()z wymaganym odstępem - Przywrócenie hasha dla prawidłowego URL w pasku adresu
Po co w ogóle płynne przewijanie do kotwicy
Gdy odwiedzający przechodzi przez link site.com/page/#pricing, oczekuje zobaczyć blok z cenami, a nie górę strony. Gwałtowny skok dezorientuje, użytkownik nie rozumie, gdzie się znalazł i co było wcześniej. Płynne przewijanie daje kontekst: oczy zdążą zahaczyć o pośrednie sekcje, mózg buduje trasę „skąd → dokąd".
Z natywną właściwością CSS scroll-behavior: smooth sprawa jest prosta, dodał Pan do arkusza stylów i przeglądarka sama przewija do kotwicy. Ale to podejście psuje się dokładnie w momencie, gdy potrzebuje Pan niestandardowego odstępu pod stały nagłówek. 110 pikseli odstępu i blok nie wjeżdża pod header, tylko pozostaje dokładnie tam, gdzie oczekuje go użytkownik. Rozwiązanie jQuery daje tę kontrolę.
Plus, kompatybilność między przeglądarkami. scroll-behavior: smooth nie działa w Internet Explorer (tak, takie projekty wciąż żyją), a metoda jQuery animate() działa wszędzie tak samo.
Podstawowy skrypt: minimum kodu, maksimum korzyści
Pierwszy wariant, kompaktowy, na 10 linijek. Rozwiązuje dokładnie jedno zadanie: płynnie przewinąć do kotwicy, gdy użytkownik przyszedł z innej strony lub przez bezpośredni link z hashem.
1 jQuery(document).ready(function ($) { 2 var myHash = location.hash; // сохраняем хеш 3 location.hash = ''; // очищаем — браузер перестаёт дёргаться 4 if (myHash[1] != undefined) { // хеш не пустой? 5 $('html, body').animate( 6 { scrollTop: $(myHash).offset().top - 110 }, 7 700 // длительность в миллисекундах 8 ); 9 location.hash = myHash; // возвращаем хеш обратно 10 } 11 });
Analiza krok po kroku, ponieważ trzy linijki czynią magię, ale ważne jest zrozumienie mechaniki:
var myHash = location.hash, odczytujemy hash z paska adresu (na przykład#pricing). Na tym etapie przeglądarka jeszcze niczego nie przewinie.location.hash = '', kluczowa sztuczka. Czyścimy hash, a przeglądarka traci cel dla natychmiastowego skoku. Bez tej linijki skrypt będzie „walczył" z wbudowanym zachowaniem przeglądarki i przegra.$(myHash).offset().top - 110, obliczamy pozycję kotwicy od góry dokumentu i odejmujemy 110 pikseli. To Pana odstęp pod stały nagłówek. Jeśli nagłówekposition: fixedma wysokość 80px, proszę ustawić 80 (lub 90 z zapasem). Jeśli nagłówka nie ma, proszę całkowicie usunąć odejmowanie.$('html, body').animate(...), płynnie przewijamy przez 700 milisekund. Selektor'html, body', to nie kaprys: różne przeglądarki przewijają albohtml, albobody, dlatego piszemy oba dla niezawodności.location.hash = myHash, przywracamy hash. Teraz pasek adresu ponownie pokazuje#pricing, a strona jest już ładnie zaparkowana przy żądanym bloku.
Skrypt wstawia się do functions.php motywu, do niestandardowego pliku JS lub przez wtyczkę typu Code Snippets. Najważniejsze, musi być w bloku jQuery(document).ready().
Zaawansowany wariant: obsługa kliknięć, ładowanie strony i ochrona przed konfliktami
Podstawowy skrypt pokrywa większość scenariuszy, ale zdarzają się sytuacje, gdy location.hash = '' nie zadziała: przeglądarka zdąży skoczyć przed wyczyszczeniem hasha. Wtedy włączamy drugi wariant, jest cięższy, ale bardziej niezawodny.
1 jQuery(document).ready(function () { 2 jQuery(window).bind('load', function () { 3 jQuery('a:not(.spu-clickable)[href*="#"]:not([href="#"])').click(function () { 4 if ( 5 location.pathname.replace(/^\//, '') == this.pathname.replace(/^\//, '') || 6 location.hostname == this.hostname 7 ) { 8 var target = jQuery(this.hash); 9 target = target.length ? target : jQuery('[name=' + this.hash.slice(1) + ']'); 10 if (target.length) { 11 jQuery('html, body').animate( 12 { scrollTop: target.offset().top - 37 }, 13 1000 14 ); 15 return false; 16 } 17 } 18 }); 19 }); 20 }); 21 22 jQuery(window).load(function () { 23 function goToByScroll(id) { 24 jQuery('html, body').animate( 25 { scrollTop: jQuery('#' + id).offset().top - 38 }, 26 1000 27 ); 28 } 29 if (window.location.hash != '') { 30 goToByScroll(window.location.hash.substr(1)); 31 } 32 });
Co tu się dzieje, blokami:
Blok pierwszy, procedura obsługi kliknięcia w wewnętrzne linki z kotwicą. jQuery(window).bind('load', ...) gwarantuje, że wszystkie elementy strony (włącznie z obrazkami i iframe) są załadowane przed podpięciem procedury. Filtr a:not(.spu-clickable) wyklucza linki, które już obsługuje wtyczka popup (SPU, WordPress PopUp), aby animacje nie kolidowały. Proszę dodać własne klasy wyjątków analogicznie.
Blok drugi, obsługa przejścia z zewnętrznej strony. jQuery(window).load() uruchamia się później niż document.ready i gwarantuje, że wszystkie elementy, włącznie z kotwicą, są już w DOM. Funkcja goToByScroll(id) robi dokładnie to samo, co podstawowy skrypt, ale jest wywoływana dopiero po pełnym załadowaniu okna. substr(1) odcina znak # od hasha.
Ważny niuans: jQuery(window).load() jest uważane za przestarzałe począwszy od jQuery 3.0. Jeśli Pana projekt jest na aktualnej wersji jQuery, proszę zamienić na:
1 jQuery(window).on('load', function () { 2 // код здесь 3 });
Różnica w składni, zachowanie identyczne.
Dostrajanie: odstępy, selektory i pułapki
Skrypt jest działający, ale każdy układ jest indywidualny. Trzy częste poprawki, które ratowały na rzeczywistych projektach.
Problem pierwszy, offset().top zwraca nie te współrzędne. Zdarza się tak, gdy bloki nadrzędne mają ustawioną właściwość CSS transform, filter lub will-change, tworzą one nowy kontekst pozycjonowania, a offset() liczy względem niego, a nie dokumentu. Rozwiązanie, wariant z offset({top: -0}):
1 jQuery('html, body').animate( 2 { scrollTop: jQuery('#' + id).offset({ top: -0 }).top }, 3 1000 4 );
Parametr {top: -0} zmusza jQuery do przeliczenia pozycji od krawędzi dokumentu, ignorując pośrednie konteksty. Wygląda jak magia, ale działa.
Problem drugi, selektor 'html, body' przewija nie ten element. W niektórych motywach kontenerem przewijania jest nie html lub body, a konkretny blok, na przykład body.home dla strony głównej lub .main-content dla wewnętrznych. Proszę określić swój kontener przez DevTools (zakładka Elements → wyszukiwanie overflow: scroll lub overflow: auto) i podstawić do selektora:
1 jQuery('body.home').animate( 2 { scrollTop: target.offset().top - 37 }, 3 1000 4 );
Problem trzeci, hash zawiera cyrylicę lub znaki specjalne. location.hash zwróci sekwencję zakodowaną URL zamiast czytelnego ciągu, a selektor jQuery $(myHash) nie znajdzie elementu. Rozwiązanie, zdekodować hash przez decodeURIComponent() przed podstawieniem do selektora.
Wideo: żywy przykład przewijania z zewnętrznym przejściem
Krótkie demo od John Smith, płynne przewijanie do kotwicy przez jQuery animate() na rzeczywistej stronie ze stałym nagłówkiem i zewnętrznym przejściem.
⁉️🤔 Często zadawane pytania
Skrypt działa wewnątrz strony, ale nie działa przy przejściu z innego URL. Dlaczego?
Dlatego, że procedura
clicknie uruchamia się, nie było kliknięcia. Użytkownik przeszedł przez bezpośredni link, a przeglądarka sama obsłużyła hash przed wykonaniem Pana JS. Leczy się to zestawemlocation.hash = ''+animate()+location.hash = myHash, dokładnie w tej kolejności. Wyczyszczenie hasha anuluje wbudowany skok, animacja przewija płynnie, przywrócenie hasha zachowuje prawidłowy URL w pasku adresu.
Jaki odstęp ustawić pod stały nagłówek?
Dokładną wysokość nagłówka plus kilka pikseli powietrza. Proszę otworzyć DevTools (F12), zaznaczyć element
headerPana strony, sprawdzić jegoheightw zakładce Computed. Na przykład, nagłówek 80px, proszę ustawić 90 w kodzie. Jeśli w wersji mobilnej nagłówek ma inną wysokość, proszę dodać media query z dynamicznym obliczaniem odstępu.
Czy jQuery jest nadal aktualne w 2026?
Tak, szczególnie w ekosystemie WordPress. jQuery pozostaje w jądrze WP, mnóstwo wtyczek i motywów od niego zależy, a migracja całego ekosystemu na natywny JS zajmie lata. Dla nowych projektów na czystym JavaScript płynne przewijanie robi się przez
element.scrollIntoView({ behavior: 'smooth' })lubscroll-behavior: smoothw CSS, linijek kodu znacznie mniej. Ale jeśli poprawia Pan istniejącą stronę WP, rozwiązanie jQuery jest nadal niezawodne i odpowiednie.
Czy można obejść się bez jQuery?
Można i trzeba, jeśli projekt jest nowy. Natywny odpowiednik podstawowego skrypta:
1 document.addEventListener('DOMContentLoaded', () => { 2 const hash = window.location.hash; 3 if (hash) { 4 window.location.hash = ''; 5 const target = document.querySelector(hash); 6 if (target) { 7 window.scrollTo({ 8 top: target.getBoundingClientRect().top + window.pageYOffset - 110, 9 behavior: 'smooth' 10 }); 11 } 12 window.location.hash = hash; 13 } 14 });
Ta sama zasada, zapisać hash, wyczyścić, przewinąć, przywrócić. Różnica polega na tym, że
behavior: 'smooth'używa natywnego silnika CSS przeglądarki, a nie timera jQuery. Szybkość nie jest konfigurowalna, za to kod jest lżejszy o 30 KB (waga jQuery).
Dlaczego $('html, body'), a nie po prostu $('html')?
Firefox przewija
html, Chrome używabody, Safari zależy od wersji. Podanie obu selektorów wanimate()gwarantuje działanie na wszystkich przeglądarkach: jQuery wyśle animację tam, gdzie zostanie ona faktycznie zastosowana.
Czy warto stawiać jQuery dla płynnego przewijania w 2026
Jeśli ma Pan stronę WordPress lub projekt legacy, gdzie jQuery jest już podłączone, proszę wziąć skrypt z artykułu i nie komplikować. Dziesięć linijek kodu, które działają wszędzie, z każdą przeglądarką i nie wymagają polyfilli. Dla nowego układu na czystym JavaScript, proszę używać natywnego scroll-behavior: smooth lub scrollIntoView(). Oba warianty dają płynne przewijanie, ale podejście jQuery pozostawia Panu kontrolę nad szybkością, odstępem i selektorem kontenera przewijania, w natywnej implementacji będzie to wymagało osobnych sprawdzeń.
Główna zasada, którą wynieśliśmy z kilkunastu projektów: zawsze proszę czyścić hash przed przewijaniem. Bez tej sztuczki żadna procedura obsługi nie pokona wbudowanego zachowania przeglądarki, a użytkownik nadal będzie skakał szarpnięciem.



