Skip to content

Kaikki WordPressistä, web-kehityksestä — ja paljon muuta

🖱 Sulava rullaus ankkuriin: CSS, JavaScript ja jQuery - kolme toimivaa lähestymistapaa

🖱 Sulava rullaus ankkuriin: CSS, JavaScript ja jQuery - kolme toimivaa lähestymistapaa

Käyttäjä klikkaa linkkiä, jossa on ankkuri, ja sivu hyppää välittömästi kohdekohtaan. Ei animaatiota, ei pehmeyttä, ei käsitystä siitä, mihin päädyit. Töksähtelevä siirtymä on hämmentävä, erityisesti pitkillä laskeutumissivuilla ja dokumentaatioissa.

Pehmeän vierityksen lisääminen ankkureihin vie 5 minuuttia. Mutta piru piilee yksityiskohdissa: linkki voi tulla ulkoiselta sivustolta, URL-osoitteessa on jo hash, ja yläreunassa on kiinteä otsake, joka peittää ankkurin. Tavallinen scroll-behavior: smooth ei ratkaise näitä vivahteita.

Alla on kolme toimivaa lähestymistapaa: puhdas CSS, natiivi JavaScript ja jQuery. Jokaisesta on koodi, jonka voit kopioida ja liittää projektiisi. Lisäksi käsittelemme erikseen ulkoiset siirtymät, jotta vieritys toimii silloinkin, kun käyttäjä saapuu toiselta sivulta tai hakutuloksista.

💡 Pikakatsaus:

  • Ota pehmeä vieritys käyttöön yhdellä CSS-rivillä, ilman JavaScriptiä
  • Lisää kiinteän otsakkeen offset käyttäen scroll-margin-top-ominaisuutta
  • Kirjoita natiivia JS:ää scrollIntoView-metodilla ulkoisia siirtymiä ja hienosäätöä varten
  • Käsittele jQuery-variantti animate()-metodilla, kun tarvitset mukautettua nopeutta ja hallintaa
  • Käsittele ulkoinen hash: sivu latautuu, ankkuri URL-osoitteessa, ja pehmeä vieritys kohteeseen

Miksi pehmeä vieritys on tärkeää

Äkillinen hyppääminen ankkuriin on hämmentävää. Käyttäjä menettää kontekstin: missä olin, mihin päädyin, mitä jäi huomaamatta? Pehmeä vieritys ylläpitää tilan hahmottamista ja antaa silmälle jotain seurattavaa sivun liikkuessa.

Käyttökokemuksen kannalta sivusto, jossa on pehmeä vieritys, näyttää viimeistellyltä. Tämä korostuu erityisesti pitkillä sivuilla: laskeutumissivut, dokumentaatio, UKK-osiossa, artikkelien sisällysluetteloissa. Käyttäjä klikkaa valikosta "Hinnoittelu", eikä sivu nytkähdä vaan liukuu kevyesti hinnoittelulohkoon.

Teknisesti tehtävä jakautuu kahteen osaan: vieritys sisäisen linkin klikkauksesta (käyttäjä on jo sivulla) ja vieritys ulkoisessa siirtymässä (URL sisältää jo #anchor-merkinnän). Jälkimmäisessä tapauksessa selain oletuksena hyppää ankkuriin välittömästi jo ennen täyttä latausta, ja tämä täytyy siepata.

CSS scroll-behavior, yksi rivi skriptin sijaan

Yksinkertaisin ja modernein lähestymistapa. Selaimet oppivat pehmeän vierityksen natiivisti, vain yksi CSS-sääntö riittää:

1html {
2 scroll-behavior: smooth;
3}

Siinä kaikki. Mikä tahansa siirtymä ankkurilinkin kautta muuttuu pehmeäksi. Ei JavaScriptiä, ei kirjastoja.

Tuki: kaikki modernit selaimet vuodesta 2022 lähtien: Chrome 61+, Firefox 36+, Safari 15.4+, Edge 79+. Ainoa poikkeus on IE11, mutta sen liikenneosuus lähestyy nollaa.

Kiinteä otsake: scroll-margin-top

Jos sisällön yläpuolella on kiinteä otsake (sticky header), ankkuri jää vierityksen jälkeen sen alle. Korjataan yhdellä rivillä:

1h2, h3, [id] {
2 scroll-margin-top: 80px; /* header height + offset */
3}

Selain lisää automaattisesti offsetin vierittäessään kohde-elementtiin. Aiemmin tehtiin virityksiä padding-top- ja negatiivisella margin-arvolla, nyt niitä ei tarvita.

Puhtaan CSS:n rajoitukset

CSS-lähestymistavassa ei voi hallita animaation nopeutta eikä easing-funktiota. Selain käyttää sisäänrakennettua käyrää, yleensä ease-in-out. Jos tarvitset mukautettua nopeutta tai epälineaarista animaatiota, siirry JavaScriptiin.

Natiivi JavaScript: scrollIntoView

Kun pelkkä CSS ei riitä, scrollIntoView()-metodi behavior: 'smooth' -optiolla tulee avuksi:

1document.querySelectorAll('a[href^="#"]').forEach(anchor => {
2 anchor.addEventListener('click', function(e) {
3 e.preventDefault();
4 const target = document.querySelector(this.getAttribute('href'));
5 if (target) {
6 target.scrollIntoView({
7 behavior: 'smooth',
8 block: 'start'
9 });
10 }
11 });
12});

Tämä koodi sieppaa klikkaukset kaikista #-merkin sisältävistä linkeistä, peruuttaa vakiosiirtymän ja käynnistää pehmeän vierityksen. Toimii ilman jQueryä ja ilman lisäkirjastoja.

Etu: voit hallita sitä ohjelmallisesti: muuttaa nopeutta <html>-elementin CSS scroll-behavior-arvolla, lisätä ehtoja (esimerkiksi sulkea pois tietyt linkit), yhdistää scroll-margin-top-arvoon otsaketta varten.

Haittapuoli: scrollIntoView ei anna asettaa animaation nopeutta suoraan. Mukautettua vieritysaikaa varten (esimerkiksi 800 ms selaimen ~500 ms sijaan) tarvitset joko jQueryn tai manuaalisen requestAnimationFrame-silmukan.

JQuery animate, täysi hallinta animaatiosta

Jos projektissa on jo jQuery käytössä tai tarvitset hienosäätöä (nopeus, offset otsakkeelle, linkkien suodatus), tässä on ajankohtainen skripti. Alla on mukautettu versio klassisesta lähestymistavasta, uudelleenkirjoitettuna modernille jQuerylle:

1jQuery(document).ready(function($) {
2 // Smooth scroll on anchor link click
3 $('a[href*="#"]:not([href="#"])').on('click', function() {
4 if (
5 location.pathname.replace(/^\//, '') === this.pathname.replace(/^\//, '')
6 && location.hostname === this.hostname
7 ) {
8 var target = $(this.hash);
9 target = target.length ? target : $('[name="' + this.hash.slice(1) + '"]');
10 if (target.length) {
11 $('html, body').animate({
12 scrollTop: target.offset().top - 80
13 }, 800);
14 return false;
15 }
16 }
17 });
18
19 // Scroll on external transition with hash in URL
20 if (window.location.hash) {
21 var hash = window.location.hash.substring(1);
22 var $target = $('#' + hash);
23 if ($target.length) {
24 setTimeout(function() {
25 $('html, body').animate({
26 scrollTop: $target.offset().top - 80
27 }, 800);
28 }, 100);
29 }
30 }
31});

Mikä tässä muuttui verrattuna vanhoihin blogeissa kiertäviin versioihin:

  • .bind() korvattu .on()-metodilla, .bind() merkittiin vanhentuneeksi jQuery 3.0:ssa ja poistetaan jQuery 4.0:ssa.
  • Valitsin 'a:not(.spu-clickable)[href*="#"]:not([href="#"])' yksinkertaistettu, tietty luokka .spu-clickable liittyi tiettyyn lisäosaan (Popups by OptinMonster) eikä sitä yleensä tarvita.
  • jQuery(window).bind("load", ...) poistettu, skriptin toinen osa ulkoista hashia varten on nyt $(document).ready()-funktiossa eikä vaadi erillistä load-tapahtumaa.
  • Lisätty viive setTimeout(..., 100), jotta DOM on varmasti renderöity ennen ankkurin sijainnin laskemista (oleellista sivuille, joissa on laiskaa kuvien latausta ja dynaamista sisältöä).

Mihin koodi lisätään

Kolme vaihtoehtoa, joista valita:

  • Teematiedoston kautta. Lisää skripti functions.php-tiedostoon wp_enqueue_script()-funktiolla, standardi tapa child-teemalle.
  • Lisäosa Code Snippets. Lisää koodi uutena pätkänä automaattisella suorituksella, ei katoa teeman päivityksessä.
  • Mukautettu JS-lisäosa. Jos sivustolla on jo käytössä lisäosa mielivaltaisen JavaScriptin lisäämiseen (esimerkiksi WPCode), lisää koodi sinne.

Ulkoisen siirtymän käsittely hashilla, yksityiskohtainen erittely

Tehtävän hankalin osa. Käyttäjä seuraa linkkiä https://site.com/page/#pricing toiselta sivustolta tai hausta. Selain oletuksena hyppää välittömästi kohtaan #pricing heti, kun elementti ilmestyy DOMiin, ilman animaatiota ja usein ennen kuin sivu on täysin latautunut.

Yllä oleva jQuery-skripti ratkaisee tämän kahdessa vaiheessa:

  • Havaitsee hashin olemassaolon window.location.hash-arvon avulla. Jos hash on olemassa, lukee sen arvon (ilman #-merkkiä).
  • Etsii kohteen ja vierittää. $('#' + hash) löytää elementin, setTimeout antaa sivulle aikaa renderöityä, animate() vie kohteeseen 80 pikselin offsetilla.

100 millisekunnin viive on empiirinen. Nopeilla sivuilla 50 ms riittää, raskailla (laskeutumissivut, joissa on taustavideo, karttoja, kaavioita) on parempi nostaa 200-300 ms:iin. Vaihtoehto: odota window.load-tapahtumaa document.ready-tapahtuman sijaan, mutta silloin vieritys tapahtuu vasta, kun kaikki kuvat ovat latautuneet, mikä voi kestää hetken.

Mitä tehdä, jos ankkuri ei löydä kohdetta

Joskus URL:n hash osoittaa elementtiin, jota ei ole olemassa. Esimerkiksi käyttäjä teki kirjoitusvirheen tai sivua muutettiin. Tässä tapauksessa CSS- eikä JS-lähestymistapa kaadu virheeseen, mitään ei yksinkertaisesti tapahdu. Selain ohittaa olemattoman ankkurin. Pehmeä vieritys toimii myös äänettömästi (if (target.length) -ehto estää etenemisen pidemmälle).

Kolmen lähestymistavan vertailu

Kriteeri

CSS scroll-behavior

JS scrollIntoView

jQuery animate

Toteutuksen monimutkaisuus

1 rivi CSS:ää

10-15 riviä JS:ää

25-30 riviä JS:ää + jQuery

Nopeuden hallinta

Ei

Ei (selaimen oletus)

Kyllä (ms)

Ulkoinen hash

Kyllä, natiivisti

Vaatii lisäkoodia

Vaatii lisäkoodia

Otsakkeen offset

scroll-margin-top

scroll-margin-top

Manuaalinen offset().top-arvossa

Riippuvuudet

Ei mitään

Ei mitään

jQuery 3.x

Selain tuki

96%+

96%+

99%+ (jQueryn kanssa)

Useimpiin moderneihin projekteihin CSS-lähestymistapa on optimaalinen: yksi rivi, nolla riippuvuutta, natiivi suorituskyky. Jos tarvitset offsetin otsakkeelle, lisää scroll-margin-top. Jos tarvitset mukautettua nopeutta tai tukea muinaisille selaimille, jQuery animate()-metodilla.

Alla on video, jossa on live-demot kaikista kolmesta lähestymistavasta, CSS:stä jQueryyn:

⁉️🤔 Usein kysytyt kysymykset

Miksi pehmeä vieritys ei toimi mobiililaitteilla?

iOS Safarissa ennen versiota 15.4 scroll-behavior: smooth ei ollut tuettu. Nyt tuki on olemassa (Safari 15.4+, maaliskuu 2022). Jos vieritys ei toimi vanhoissa iPhoneissa, lisää JavaScript-fallback scrollIntoView- tai requestAnimationFrame-metodilla. Tarkista myös, ettei vieritystä ole estetty overflow: hidden -määrityksellä body-elementissä, jotkin mobiilivalikot asettavat sen avautuessaan. Kesäkuussa 2026 scroll-behavior-ominaisuuden globaali tuki on 96,3% selaimista (Can I Use -datan mukaan).

Miten tehdä pehmeä vieritys ei ankkuriin vaan mielivaltaiseen elementtiin napin painalluksella?

Anna elementille id ja käytä samaa JavaScriptiä, mutta sido se nappiin ankkurilinkin sijaan. Esimerkiksi "Takaisin ylös" -nappi: document.querySelector('#back-to-top').addEventListener('click', () => window.scrollTo({ top: 0, behavior: 'smooth' })). jQuery-variantille: $('#back-to-top').on('click', () => $('html, body').animate({ scrollTop: 0 }, 600)). Ankkureita ei tarvita, vieritys koordinaatteihin.

Onko tarpeen sisällyttää jQuery vain pehmeää vieritystä varten vuonna 2026?

Ei. jQuery painaa noin 87 KB minifioituna (30 KB gzip). Jos jQueryä ei käytetä missään muualla sivustolla, sen sisällyttäminen yhden vierityksen takia on järjetöntä. Ota CSS-lähestymistapa scroll-behavior: smooth-arvolla tai natiivi scrollIntoView. jQuery on perusteltu vain, jos sivusto on jo rakennettu sen varaan (jQuery-teemat, legacy-projektit) ja haluat lisätä vierityksen olemassa olevaan koodipohjaan.

Voiko vierityksen animoida eri nopeudella, ensin nopeasti, sitten hitaasti?

Kyllä, $.animate()-metodilla jQuery UI:n kautta tai requestAnimationFrame-metodilla easing-funktion avulla. Tavallinen jQueryn animate() käyttää lineaarista tai swing-funktiota. Epästandardeille käyrille sisällytä jquery.easing tai kirjoita oma silmukka requestAnimationFrame-metodille mukautetulla easing-funktiolla, esimerkiksi easeInOutQuad. Tämä antaa täyden hallinnan nopeudesta, liikeradasta eikä vaadi ulkoisia kirjastoja.

Miten varmistaa, että vieritys toimii ulkoisessa siirtymässä hashilla?

Avaa uusi välilehti, liitä URL ankkurilla (esimerkiksi https://yoursite.com/page/#contacts) ja paina Enter. Sivun pitäisi latautua ja vierittää pehmeästi lohkoon. Toinen vaihtoehto: selaimen konsolissa avoimella sivulla suorita location.hash = '#contacts'. Jos vieritys on pehmeä, skripti toimii. Jos sivu nytkähti välittömästi, ulkoisen hashin käsittelijää ei ole määritetty.

Mikä lähestymistapa valita omaan tehtävääsi

Jos sivusto on moderni, ilman jQueryä, CSS scroll-behavior: smooth kattaa valtaosan skenaarioista. Yksi rivi, välitön tulos. Lisää scroll-margin-top otsakkeelle, ja se on siinä.

Jos sivusto on WordPress ja teemassa on jQuery, jQuery-skripti animate()-metodilla. Antaa hallinnan nopeudesta ja offsetista, käsittelee ulkoiset siirtymät, ei ole ristiriidassa muiden lisäosien kanssa.

Jos kirjoitat puhtaalta pöydältä etkä halua vetää mukaan kirjastoa, natiivi scrollIntoView() ulkoisen hashin käsittelijällä. Kultainen keskitie: puhdas, nopea, ei riippuvuuksia.

Ota koodi artikkelista, liitä se projektiisi ja tarkista ulkoinen siirtymä, tämä on ainoa tapaus, joka on helppo ohittaa testauksessa.