
🖱 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ää:
1 html { 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ä:
1 h2, 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:
1 document.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:
1 jQuery(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-clickableliittyi 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-tiedostoonwp_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,setTimeoutantaa 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 |
|
| Manuaalinen |
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: smoothei ollut tuettu. Nyt tuki on olemassa (Safari 15.4+, maaliskuu 2022). Jos vieritys ei toimi vanhoissa iPhoneissa, lisää JavaScript-fallbackscrollIntoView- tairequestAnimationFrame-metodilla. Tarkista myös, ettei vieritystä ole estettyoverflow: hidden-määritykselläbody-elementissä, jotkin mobiilivalikot asettavat sen avautuessaan. Kesäkuussa 2026scroll-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
idja 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 natiiviscrollIntoView. 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 tairequestAnimationFrame-metodilla easing-funktion avulla. Tavallinen jQuerynanimate()käyttää lineaarista tai swing-funktiota. Epästandardeille käyrille sisällytäjquery.easingtai kirjoita oma silmukkarequestAnimationFrame-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 suoritalocation.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.



