smoothscroll-anchor-polyfill
⚓ Apply smooth scroll to anchor links to replicate CSS scroll-behavior
Start
The
Scroll Behavior
specification allows for native smooth scrolling in browsers – both by using JavaScript
scroll APIs like window.scrollTo
and
Element.scrollIntoView
or by simply setting the property scroll-behavior
to smooth
in
CSS, which will then make any scrolling smooth by default. This includes scrolls
that are triggered by an anchor link pointing to an element on the page by targeting it's
id
in the hash, like <a href="#target">
.
By using this CSS property, you can build a one-page design with smooth scroll between the
different sections without having to write a single line of JS – just like this page is
doing!
Unfortunately, the Scroll Behavior spec is not supported in all major browsers yet. 👎🏻
There are several Polyfills available to fix this, for example
smoothscroll-polyfill
. But even if you use those, navigation happening due to clicks on anchor elements is
still instant without any smoothness: only the JavaScript APIs are polyfilled.
This little script aims to fix this. If the browser does not support native Scroll
Behavior, it will wire up all matching anchor links so they use the (polyfilled and thus
smooth) JS APIs for navigation. Let the scrolling begin!
Usage
⚠ Since this script uses the JavaScript scroll APIs and relies on their smooth scroll
functionality to operate, you'll need a polyfill for the Scroll Behavior spec in order for
this script to make a difference. It just wires up <a>
tags and
hashchange
events to use window.scroll()
and
Element.scrollIntoView()
.
smoothscroll-polyfill
is
used as example throughout this site, but you may just as well use another polyfill – or
write your own implementation. If you are using jQuery on your site, you could use
$.animate()
to provide smooth scroll for these scroll APIs, for example.
1. Setting scroll-behavior
in CSS
Browsers don't parse CSS properties they don't recognize. For this reason, reading the
scroll-behavior
property from your regular stylesheets is unfortunately not
possible (without a performance hit). Instead, you need to additionally specify
scroll-behavior
using a CSS variable:
<style>
html {
/* CSS custom property for the polyfill */
--scroll-behavior: smooth;
/* Normal CSS property for browsers with native support */
scroll-behavior: smooth;
}
<style>
You can treat it like any other property, for example use media queries or toggle
classes.
The following only enables smooth scroll on Desktop devices:
<style>
html {
--scroll-behavior: auto;
scroll-behavior: auto;
}
@media screen and (min-width: 1150px) {
html {
--scroll-behavior: smooth;
scroll-behavior: smooth;
}
}
<style>
Need to support Internet Explorer?
In legacy browsers like Internet Explorer,
CSS Custom Properties are not supported. To specify scroll-behavior
, use one of the following options instead:
Using the inline style
attribute:
<html style="scroll-behavior: smooth;">
...
</html>
This way, the polyfill can read the property using getAttribute('style')
even
if the browser doesn't parse it.
Using font-family
as workaround
Alternatively, you can specify the property as the name of a custom font family. Your
actual fonts will still work the way they should (plus, you can simply declare actual
fonts on body
instead of html
).
As with CSS variables (and unlike inline styles), this allows you to use normal CSS
features like media queries or classes.
<style>
html {
/* Normal CSS property for browsers with native support */
scroll-behavior: smooth;
/* Defined as the name of a font, so the polyfill can read it */
font-family: "scroll-behavior: smooth", sans-serif;
}
<style>
💡 Redeclaring your scroll-behavior
properties to work with this polyfill can
be automated using a
PostCSS plugin. You simply write regular CSS and the plugin will intelligently transform it using one
of the above options, depending on your supported browsers (detected via
browserslist). It just works™
2. Installing the polyfill
Option 1: Using <script>
Simply drop in <script>
tags linking to the polyfill(s) and you're good to
go.
<!-- Any polyfill to enable smoothscroll for the JavaScript APIs -->
<script src="https://unpkg.com/smoothscroll-polyfill/dist/smoothscroll.min.js"></script>
<!-- This package, to apply the smoothscroll to anchor links -->
<script src="https://unpkg.com/smoothscroll-anchor-polyfill"></script>
Option 2: With npm
Alternatively, if you're using npm, you can install using
npm install smoothscroll-anchor-polyfill
and then use the polyfill by
requiring/importing it in your JS.
// Import any polyfill to enable smoothscroll for JS APIs
import smoothscrollPolyfill from 'smoothscroll-polyfill';
// Import this package to apply the smoothscroll to anchor links
import smoothscrollAnchorPolyfill from 'smoothscroll-anchor-polyfill';
// (Unlike this package, smoothscroll-polyfill needs to be actively invoked: )
smoothscrollPolyfill.polyfill();
👉🏻 The polyfill is also provided in ES module format as
index.mjs
and index.min.mjs
.
Advanced installation (with Code Splitting)
If you're using a build system with support for code splitting like Parcel or Webpack, you can use dynamic imports to load the polyfills – this way, browsers won't even download the polyfill code if they already have support for the Scroll Behavior spec natively:
// Only continue if polyfills are actually needed
if (!('scrollBehavior' in document.documentElement.style)) {
// Wait until the Polyfills are loaded
Promise.all([
import('smoothscroll-polyfill'),
import('smoothscroll-anchor-polyfill')
])
// then use the modules however you want
.then(([smoothscrollPolyfill, smoothscrollAnchorPolyfill]) => {
// (Unlike this package, smoothscroll-polyfill needs to be actively invoked: )
smoothscrollPolyfill.polyfill();
});
}
Docs
For 90% of use cases, there should not be much more to it than loading this polyfill – it will execute immediately no matter if loaded through a script tag or in a module environment. If the Scroll Behavior spec is supported natively, the code won't do anything.
Changing the scroll behavior
The prefered way to dynamically adjust the scroll behavior is through CSS, e.g. toggling a
class or using a media query. The documentation site is using this method: click the
"Toggle smooth scroll" button and notice how the class
smooth-scroll
is toggled on <html>
.
Valid property values for scroll-behavior
are smooth
to enable
smooth scroll, or auto
, initial
, inherit
or
unset
to use instant, jumping scroll.
You can also assign these values directly to
document.documentElement.style.scrollBehavior
, it will have precedence over all other ways of specyfing the scroll behavior.
Assigning to .scrollBehavior
is not recommened however, as some
packages use this property for feature detection and can break if you mess with it.
Using the polyfill even if there is native support
This package exports two methods, destroy
and polyfill
.
If loaded through a script tag, these methods are exposed on
window.smoothscrollAnchorPolyfill
.
polyfill({ force: boolean })
:
The polyfill
method starts the polyfill. If it is already active, it will
simply restart – so you can safely call it without running
destroy()
first.
The method takes an (optional) Object as argument, if you set the property
force
to true, anchor navigation will be handled by this script even if
the browser supports native smooth scroll. Not recommended.
destroy()
:
Disables the polyfill and removes all EventListeners.
Limitations
scroll-behavior
is not detected in regular stylesheets
As already explained in the Usage section,
scroll-behavior
can not be set in regular CSS, as accessing the property there from JavaScript is not
possible without a performance hit. This is caused by browsers not parsing a CSS property
if it isn't recognized as valid. If you need the flexiblity of CSS, consider the
font-family
workaround.
scroll-behavior
is only supported as global setting
In browsers with native support, you can define
scroll-behavior
at multiple points in your document, e.g. auto
on the document itself, but
smooth
on a slideshow container that has separate scrolling. This polyfill
does not allow for that, either all anchors on the page scroll smoothly by setting
scroll-behavior
at document level, or none.
scroll-behavior
doesn't affect scrolling triggered from JavaScript
This polyfill only affects scrolling triggered by clicks on
<a>
tags and through hashchange
events. You'll still have to pass
{ behavior: 'smooth' }
when using APIs like
window.scroll()
unless your polyfill for these APIs has it's own CSS property check.
Inconsistencies in native implementations
While Scroll Behavior has native support in a couple of browsers already, they behave differently than expected in some situations. The following are not bugs of this polyfill, but inconsistencies of browsers' native behavior and workarounds you might want to know about.
Blink (e.g. Chrome, Opera):
While 'normal' scrolling is smooth, if you click a couple of links and then navigate back
and forth using the browser's forwards/backwards buttons (which triggers a
hashchange
everytime), it jumps from anchor to anchor instead of scrolling
smoothly.
If this is important to you, you can fix it by detecting the Blink engine
and force-enabling this polyfill. Load
browsengine.js, then do (before
the polyfill runs):
if (window.webpage.engine.blink) {
window.__forceSmoothscrollAnchorPolyfill__ = true;
}
Gecko (Firefox):
Anchors pointing to #top
don't smooth scroll.
Use anchors pointing at #
for an easy fix.
FAQ
Will this break Server Side Rendering?
No.
Will this work if anchors are inserted after the script was loaded?
The polyfill uses Event Delegation to detect clicks, so even if an anchor is added to the page after the polyfill was loaded, everything should work.
Does this support prefers-reduced-motion
?
prefers-reduced-motion
is a relatively new CSS media query that hints at
whether a client prefers less motion, which can be important for people with certain
illnesses. Firefox currently is the only browser to support both
scroll-behavior
and prefers-reduced-motion
and thus acts as a
reference for the interplay between these two properties – and in Firefox, smooth
scrolling is not disabled automatically if this media query matches.
So no, this polyfill does not automatically disable itself if the client prefers less
motion, but yes, it supports
prefers-reduced-motion
the same way Firefox does – via a media query:
@media (prefers-reduced-motion: reduce) {
html {
--scroll-behavior: auto;
scroll-behavior: auto;
}
}
Rechtliches
Hinweis: die folgenden rechtlichen Hinweise betreffen diese Website als solche entsprechend deutschem und europäischem Recht, nicht das vorgestellte Software-Paket "smoothscroll-anchor-polyfill". "smoothscroll-anchor-polyfill" selbst ist lizensiert nach der MIT-Lizenz, mehr Informationen können dem GitHub Repository entnommen werden.
Impressum
Angaben gemäß §5 TMG
Jonas KuskeSielstraße 5
27568 Bremerhaven
Kontakt
Telefon: +491603336948
Mail: mail@jonaskuske.com
Verantwortlich für Inhalte gemäß 55 Abs. 2 RStV:
Jonas Kuske
Sielstraße 5
27568 Bremerhaven
Haftungsauschluss
Haftung für Inhalte
Die Inhalte dieser Seite wurden mit größter Sorgfalt erstellt. Für die Richtigkeit, Vollständigkeit und Aktualität der Inhalte kann ich jedoch keine Gewähr übernehmen. Als Diensteanbieter bin ich gemäß § 7 Abs.1 TMG für eigene Inhalte auf diesen Seiten nach den allgemeinen Gesetzen verantwortlich. Nach §§ 8 bis 10 TMG bin ich als Diensteanbieter jedoch nicht verpflichtet, übermittelte oder gespeicherte fremde Informationen zu überwachen oder nach Umständen zu forschen, die auf eine rechtswidrige Tätigkeit hinweisen. Verpflichtungen zur Entfernung oder Sperrung der Nutzung von Informationen nach den allgemeinen Gesetzen bleiben hiervon unberührt. Eine diesbezügliche Haftung ist jedoch erst ab dem Zeitpunkt der Kenntnis einer konkreten Rechtsverletzung möglich. Bei Bekanntwerden von entsprechenden Rechtsverletzungen werde ich diese Inhalte umgehend entfernen.
Haftung für Links
Mein Angebot enthält Links zu externen Webseiten Dritter, auf deren Inhalte ich keinen Einfluss habe. Deshalb kann ich für diese fremden Inhalte auch keine Gewähr übernehmen. Für die Inhalte der verlinkten Seiten ist stets der jeweilige Anbieter oder Betreiber der Seiten verantwortlich. Die verlinkten Seiten wurden zum Zeitpunkt der Verlinkung auf mögliche Rechtsverstöße überprüft. Rechtswidrige Inhalte waren zum Zeitpunkt der Verlinkung nicht erkennbar. Eine permanente inhaltliche Kontrolle der verlinkten Seiten ist jedoch ohne konkrete Anhaltspunkte einer Rechtsverletzung nicht zumutbar. Bei Bekanntwerden von Rechtsverletzungen werde ich derartige Links umgehend entfernen.
Urheberrecht
Die durch die Seitenbetreiber erstellten bzw. verwendeten Inhalte und Werke auf diesen Seiten unterliegen dem deutschen Urheberrecht.
Soweit die Inhalte auf dieser Seite nicht vom Betreiber erstellt wurden, werden die Urheberrechte Dritter beachtet. Insbesondere werden Inhalte Dritter als solche gekennzeichnet. Sollten Sie trotzdem auf eine Urheberrechtsverletzung aufmerksam werden, bitte ich um einen entsprechenden Hinweis. Bei Bekanntwerden von Rechtsverletzungen werde ich derartige Inhalte umgehend entfernen.
Datenschutz
Durch die Nutzung dieser Website erklären Sie sich mit der Erhebung, Verarbeitung und Nutzung von Daten gemäß der nachfolgenden Beschreibung einverstanden. Die Website kann grundsätzlich ohne Registrierung besucht werden. Dabei werden folgende Daten ggf. zu statistischen Zwecken auf dem Server, verwaltet von GitHub, in sogenannten "Server Log-Files" gespeichert, ohne dass diese Daten unmittelbar auf Ihre Person bezogen werden:
- Besuchte Website
- Uhrzeit zum Zeitpunkt des Zugriffes
- Menge der gesendeten Daten in Bytes
- Quelle/Verweis, von welchem Sie auf diese Seite gelangten
- Verwendeter Browser
- Verwendetes Betriebssystem
- Verwendete IP-Adresse
Diese Seite verwendet den Dienst Google Fonts, um verschiedene Schriftarten einzubinden. Beim Abrufen der Schriftdateien, was bei Seitenaufruf automatisch geschieht, können die Daten, die oben aufgelistet sind, auch vom Dienstleister Google eingesehen werden.
Nehmen Sie mit dem Websitebetreiber durch die angebotenen Kontaktmöglichkeiten Verbindung auf, werden Ihre Angaben gespeichert, damit auf diese zur Bearbeitung und Beantwortung Ihrer Anfrage zurückgegriffen werden kann. Ohne Ihre Einwilligung werden diese Daten nicht an Dritte weitergegeben; auf Wunsch können Sie Einsicht in die gesammelten Daten bekommen oder eine vollständige Löschung selbiger veranlassen.
Legal
Note: the legalities discussed here concern this website itself, not the software package "smoothscroll-anchor-polyfill", and are required for compliance with German & European law. "smoothscroll-anchor-polyfill" itself is licensed under a plain MIT license, for more information check out the respective GitHub repository.
Imprint
Information in accordance with section §5 TMG
Jonas KuskeSielstraße 5
27568 Bremerhaven
Contact
Phone: +491603336948
Mail: mail@jonaskuske.com
Person responsible for content in accordance with 55 Abs. 2 RStV:
Jonas Kuske
Sielstraße 5
27568 Bremerhaven
Disclaimer
Accountability for content
The contents of our pages have been created with the utmost care. However, we cannot guarantee the contents' accuracy, completeness or topicality. According to statutory provisions, we are furthermore responsible for our own content on these web pages.In this context, please note that we are accordingly not obliged to monitor merely the transmitted or saved information of third parties, or investigate circumstances pointing to illegal activity. Our obligations to remove or block the use of information under generally applicable laws remain unaffected by this as per §§ 8 to 10 of the Telemedia Act(TMG).
Accountability for links
Responsibility for the content of external links (to web pages of third parties) lies solely with the operators of the linked pages. No violations were evident to us at the time of linking. Should any legal infringement become known to us, we will remove the respective link immediately.
Copyright
Our web pages and their contents are subject to German copyright law.
Privacy
With the use of this website you agree to the collection and processing of data as described below. The website can be visited with out prior sign-up, when visiting the site the following data might be stored on the server (managed by GitHub) in the form of so-called "server log files" for statistical use.
- Visited website
- Time when website was loaded
- Amount of data sent in bytes
- Source/referer which lead you to this site
- Used browser
- Used operating system
- Used IP address
This website is using service Google Fonts to load font files. While loading the font files – which happens automatically when visiting this site – the pieces of data listed above might be gathered and stored by service provider Google as well.
If you contact the operator of this website through the given contact possibilities your given information will be stored solely to reply to and process your inquiry. Without your permission collected information will never be shared with third parties. At your request you can gain insight into or request the complete deletion of all data collected about you.