
🖱 Mjuk skrollning till ankare: CSS, JavaScript och jQuery - tre fungerande metoder
Användaren klickar på en länk med ett ankare, och sidan hoppar omedelbart till målplatsen. Ingen animation, ingen mjukhet, ingen förståelse för var man hamnade. Den hackiga övergången är desorienterande, särskilt på långa landningssidor och i dokumentation.
Att lägga till mjuk scroll till ankare tar 5 minuter. Men djävulen sitter i detaljerna: länken kan komma från en extern webbplats, URL:en har redan en hash, och det finns en fast header högst upp som täcker ankaret. Vanlig scroll-behavior: smooth löser inte dessa nyanser.
Här är tre fungerande tillvägagångssätt: ren CSS, native JavaScript, och jQuery. Var och en med kod du kan kopiera och klistra in i ditt projekt. Dessutom täcker vi separat externa övergångar så att scrollningen fungerar även när användaren kommer från en annan sida eller från sökresultat.
💡 Snabb översikt:
- Aktivera mjuk scroll med en CSS-rad, ingen JavaScript alls
- Lägg till offset för fast header med
scroll-margin-top - Skriv native JS med
scrollIntoViewför externa övergångar och finjustering - Täck jQuery-varianten med
animate()när du behöver anpassad hastighet och kontroll - Hantera extern hash: sidan laddad, ankare i URL:en, och mjuk scroll till målet
Varför mjuk scroll spelar roll
Ett abrupt hopp till ett ankare är desorienterande. Användaren tappar sammanhanget: var var jag, var hamnade jag, vad missade jag? Mjuk scrollning upprätthåller rumslig orientering och ger ögat något att följa medan sidan rör sig.
Ur ett uppfattningsperspektiv ser en webbplats med mjuk scroll polerad ut. Detta märks särskilt på långa sidor: landningssidor, dokumentation, FAQ-sektioner, innehållsförteckningar i artiklar. Användaren klickar på "Priser" i menyn, och sidan rycker inte till utan glider mjukt till prisblocket.
Tekniskt sett delas uppgiften i två: scroll vid klick på en intern länk (användaren är redan på sidan) och scroll vid extern övergång (URL:en innehåller redan #anchor). I det andra fallet hoppar webbläsaren som standard till ankaret omedelbart, även innan full laddning, och detta måste fångas upp.
CSS scroll-behavior, en rad istället för ett skript
Det enklaste och mest moderna tillvägagångssättet. Webbläsare lärde sig mjuk scroll native, det räcker med en CSS-regel:
1 html { 2 scroll-behavior: smooth; 3 }
Det är allt. Varje övergång via ankarlänk blir mjuk. Ingen JavaScript, inga bibliotek.
Stöd: alla moderna webbläsare sedan 2022: Chrome 61+, Firefox 36+, Safari 15.4+, Edge 79+. Det enda undantaget är IE11, men dess trafikandel närmar sig noll.
Fast header: scroll-margin-top
Om en fast header (sticky header) hänger ovanför innehållet kommer ankaret efter scrollning att hamna under den. Fixas med en rad:
1 h2, h3, [id] { 2 scroll-margin-top: 80px; /* header height + offset */ 3 }
Webbläsaren lägger automatiskt till offset när den scrollar till målelementet. Tidigare skrev folk hacks med padding-top och negativ margin, nu behövs det inte.
Rena CSS-begränsningar
CSS-metoden har ingen kontroll över animationshastighet och easing-funktion. Webbläsaren använder en inbyggd kurva, vanligtvis ease-in-out. Om du behöver anpassad hastighet eller icke-linjär animation, gå vidare till JavaScript.
Native JavaScript: scrollIntoView
När enbart CSS inte räcker kommer scrollIntoView()-metoden med alternativet behavior: 'smooth' till undsättning:
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 });
Denna kod fångar upp klick på alla länkar med #, avbryter standardövergången och startar mjuk scroll. Fungerar utan jQuery och utan ytterligare bibliotek.
Fördelen: du kan styra det programmatiskt: ändra hastighet via CSS scroll-behavior på <html>, lägga till villkor (till exempel exkludera vissa länkar), kombinera med scroll-margin-top för headern.
Nackdelen: scrollIntoView låter dig inte ställa in animationshastighet direkt. För anpassad scrolltid (säg 800 ms istället för webbläsarens ~500 ms) behöver du antingen jQuery eller manuell requestAnimationFrame.
JQuery animate, full kontroll över animationen
Om projektet redan använder jQuery eller du behöver finjustering (hastighet, offset för header, länkfiltrering), här är det aktuella skriptet. Nedan finns en anpassad version av den klassiska metoden, omskriven för modern jQuery:
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 });
Vad som ändrats här jämfört med gamla versioner som flyter runt på bloggar:
.bind()ersatt med.on(),.bind()förklarades föråldrat i jQuery 3.0 och kommer att tas bort i jQuery 4.0.- Selektor
'a:not(.spu-clickable)[href*="#"]:not([href="#"])'förenklad, den specifika klassen.spu-clickablerelaterad till en specifik plugin (Popups by OptinMonster) och behövs i allmänhet inte. jQuery(window).bind("load", ...)borttagen, den andra delen av skriptet för extern hash ligger nu i$(document).ready()och kräver ingen separatload-händelse.- Tillagd fördröjning
setTimeout(..., 100)så att DOM garanterat är renderat innan ankarets position beräknas (relevant för sidor med lazy loading av bilder och dynamiskt innehåll).
Var du ska infoga koden
Tre alternativ att välja mellan:
- Via temafil. Lägg till skriptet i
functions.phpviawp_enqueue_script(), standardmetoden för ett barntema. - Plugin Code Snippets. Infoga koden som en ny snippet med auto-run, försvinner inte vid temauppdatering.
- Anpassat JS-plugin. Om webbplatsen redan använder ett plugin för att infoga godtycklig JavaScript (till exempel WPCode), lägg till koden där.
Hantering av extern övergång med hash, detaljerad genomgång
Den mest knepiga delen av uppgiften. Användaren följer en länk https://site.com/page/#pricing från en annan webbplats eller från sök. Webbläsaren hoppar som standard omedelbart till #pricing så snart elementet dyker upp i DOM, utan animation och ofta innan sidan är fulladdad.
jQuery-skriptet ovan löser detta i två steg:
- Upptäcker hash-närvaro via
window.location.hash. Om hash finns, läser dess värde (utan#). - Hittar mål och scrollar.
$('#' + hash)hittar elementet,setTimeoutger sidan tid att renderas,animate()leder till målet med 80 pixlars offset.
Fördröjningen på 100 millisekunder är empirisk. På snabba sidor räcker 50 ms, på tunga (landningssidor med bakgrundsvideo, kartor, diagram) är det bättre att öka till 200-300 ms. Alternativ: vänta på window.load-händelsen istället för document.ready, men då sker scrollning först efter att alla bilder laddats, vilket kan ta ett tag.
Vad du ska göra om ankare inte hittar mål
Ibland pekar hashen i URL:en på ett icke-existerande element. Till exempel gjorde användaren ett stavfel eller sidan ändrades. I detta fall kommer varken CSS- eller JS-metoden att misslyckas med ett fel, helt enkelt kommer ingenting att hända. Webbläsaren ignorerar det icke-existerande ankaret. Mjuk scroll kommer också att fungera tyst (villkoret if (target.length) låter det inte fortsätta).
Jämförelse av tre tillvägagångssätt
Kriterium | CSS scroll-behavior | JS scrollIntoView | jQuery animate |
|---|---|---|---|
Implementeringskomplexitet | 1 rad CSS | 10-15 rader JS | 25-30 rader JS + jQuery |
Hastighetskontroll | Nej | Nej (webbläsarens standard) | Ja (ms) |
Extern hash | Ja, native | Kräver extra kod | Kräver extra kod |
Header-offset |
|
| Manuell i |
Beroenden | Inga | Inga | jQuery 3.x |
Webbläsarstöd | 96%+ | 96%+ | 99%+ (med jQuery) |
För de flesta moderna projekt är CSS-metoden optimal: en rad, noll beroenden, native prestanda. Om du behöver offset för header, lägg till scroll-margin-top. Om du behöver anpassad hastighet eller stöd för uråldriga webbläsare, jQuery med animate().
Nedan finns en video med livedemonstration av alla tre tillvägagångssätt, från CSS till jQuery:
⁉️🤔 Vanliga frågor
Varför fungerar inte mjuk scroll på mobila enheter?
I iOS Safari före version 15.4 stöddes inte
scroll-behavior: smooth. Nu finns stöd (Safari 15.4+, mars 2022). Om scroll inte fungerar på gamla iPhones, lägg till en JavaScript-fallback medscrollIntoViewellerrequestAnimationFrame. Kontrollera också att scroll inte blockeras avoverflow: hiddenpåbody, vissa mobila menyer sätter det när de öppnas. I juni 2026 är det globala stödet förscroll-behavior96,3% av webbläsarna (Can I Use data).
Hur gör man mjuk scroll inte till ett ankare utan till ett godtyckligt element vid knappklick?
Ge elementet ett
idoch använd samma JavaScript, men bundet till en knapp istället för en ankarlänk. Till exempel "Tillbaka till toppen"-knapp:document.querySelector('#back-to-top').addEventListener('click', () => window.scrollTo({ top: 0, behavior: 'smooth' })). För jQuery-varianten:$('#back-to-top').on('click', () => $('html, body').animate({ scrollTop: 0 }, 600)). Inga ankare behövs, scroll till koordinater.
Är det nödvändigt att inkludera jQuery bara för mjuk scroll år 2026?
Nej. jQuery väger cirka 87 KB i min-version (30 KB gzip). Om jQuery inte används någon annanstans på webbplatsen är det irrationellt att inkludera det för en scroll. Ta CSS-metoden med
scroll-behavior: smootheller nativescrollIntoView. jQuery är motiverat endast om webbplatsen redan är byggd på det (jQuery-teman, äldre projekt) och du vill lägga till scroll till den befintliga kodbasen.
Kan man animera scroll med olika hastighet, snabbt först, sedan långsamt?
Ja, genom
$.animate()med jQuery UI eller genomrequestAnimationFramemed en easing-funktion. Standard jQueryanimate()använder linjär eller swing-funktion. För icke-standardkurvor, inkluderajquery.easingeller skriv din egen loop pårequestAnimationFramemed en anpassad easing-funktion, till exempel easeInOutQuad. Detta ger full kontroll över hastighet, bana och kräver inga externa bibliotek.
Hur verifierar man att scroll fungerar vid extern övergång med hash?
Öppna en ny flik, klistra in URL med ankare (till exempel
https://yoursite.com/page/#contacts) och tryck Enter. Sidan ska laddas och mjukt scrolla till blocket. Andra alternativet: i webbläsarkonsolen på den öppna sidan, körlocation.hash = '#contacts'. Om scroll är mjuk fungerar skriptet. Om sidan ryckte till omedelbart är den externa hash-hanteraren inte konfigurerad.
Vilket tillvägagångssätt du ska välja för din uppgift
Om webbplatsen är modern, utan jQuery, täcker CSS scroll-behavior: smooth de allra flesta scenarier. En rad, omedelbart resultat. Lägg till scroll-margin-top för headern, och du är klar.
Om webbplatsen är på WordPress med jQuery i temat, jQuery-skript med animate(). Ger kontroll över hastighet och offset, hanterar externa övergångar, krockar inte med andra plugins.
Om du skriver från grunden och inte vill dra in ett bibliotek, native scrollIntoView() med extern hash-hanterare. Den gyllene medelvägen: ren, snabb, inga beroenden.
Ta koden från artikeln, klistra in den i ditt projekt och kontrollera extern övergång, detta är det enda fall som är lätt att missa under testning.



