Smooth scrolling (die animierte Positionsänderung innerhalb des Viewports von einem ausgehenden Link zu einem Zielanker) kann ein schönes Interaktionsdetail sein, das einer Website hinzugefügt wird und dem Erlebnis ein poliertes Gefühl verleiht. Wenn Sie mir das nicht glauben, sehen Sie sich an, wie viele Leute auf den Smooth Scrolling-Snippet hier auf CSS-Tricks reagiert haben.

Unabhängig davon, wie Sie die Funktion implementieren, gibt es einige Barrierefreiheitsprobleme, die angegangen werden sollten: Fokusmanagement und Animation.
Fokusmanagement
Es ist wichtig sicherzustellen, dass alle Inhalte allein mit der Tastatur zugänglich sind, da einige Benutzer 100% auf die Tastatur für die Navigation angewiesen sind. Wenn also ein Tastaturnutzer durch die Inhalte navigiert und auf einen Link stößt, der Smooth Scrolling verwendet, sollte er diesen verwenden können, um zum Zielanker-Element zu navigieren.
Mit anderen Worten: Wenn Sie einem Link folgen, sollte der Tastatur-Fokus ihm ebenfalls folgen und in der Lage sein, auf das nächste Element nach dem Ziel zuzugreifen. Hier ist ein Beispiel für Links zu Seitenankern, bei denen der Fokus erhalten bleibt, da kein JavaScript verwendet wird

Probieren Sie es selbst aus: Verwenden Sie die Tabulatortaste, um mit dieser Demo zu navigieren. Bitte beachten Sie, dass Safari/WebKit einen offenen Fehler bezüglich des Tastaturfokus aufweist.
Original jQuery-Beispiel
Schauen wir uns das jQuery-Beispiel aus dem Originalbeitrag an
$(function() {
$('a[href*="#"]:not([href="#"])').click(function() {
if (location.pathname.replace(/^\//,'') == this.pathname.replace(/^\//,'') && location.hostname == this.hostname) {
var target = $(this.hash);
target = target.length ? target : $('[name=' + this.hash.slice(1) +']');
if (target.length) {
$('html, body').animate({
scrollTop: target.offset().top
}, 1000);
return false;
}
}
});
});
Dies ist auf einer Seite des W3C implementiert

:focus auf den Inhalt haben, aber dies ändert den Fokus nichtHier sehen wir, dass der Link „Skip to Content“ den Fokus nicht auf den Inhalt setzt, zu dem navigiert wurde. Wenn wir also dieses Beispiel verwenden, verschlechtern wir die Navigation für Benutzer, die die Tastatur verwenden, da der Benutzer erwartet, zu dem Zielinhalt zu navigieren, dies aber nicht tut, da der Fokus nicht aktualisiert wird, um die Änderung widerzuspiegeln.
Probieren Sie es selbst aus, indem Sie die Tabulatortaste verwenden, um mit dieser Demo zu navigieren.
Was lief falsch?
Warum funktioniert das nicht? Wir verwenden JavaScript, um das normale Browser-Verhalten von Links zu übernehmen (beachten Sie, dass sich die URL nie mit dem /#target aktualisiert), was bedeutet, dass wir den Fokus mit JavaScript setzen müssen. In jQuery wäre das $(target).focus();.
Damit dies auf nicht fokussierbaren Zielelementen (Abschnitt, div, span, h1-6 usw.) funktioniert, müssen wir ihnen tabindex="-1" zuweisen, um $(target).focus(); verwenden zu können. Wir können entweder tabindex="-1" direkt auf nicht fokussierbare Zielelemente im HTML-Markup setzen oder es mit JavaScript hinzufügen, wie hier gezeigt.
$(function() {
$('a[href*="#"]:not([href="#"])').click(function() {
if (location.pathname.replace(/^\//,'') == this.pathname.replace(/^\//,'') && location.hostname == this.hostname) {
var target = $(this.hash);
target = target.length ? target : $('[name=' + this.hash.slice(1) +']');
if (target.length) {
$('html, body').animate({
scrollTop: target.offset().top
}, 1000);
target.focus(); // Setting focus
if (target.is(":focus")){ // Checking if the target was focused
return false;
} else {
target.attr('tabindex','-1'); // Adding tabindex for elements not focusable
target.focus(); // Setting focus
};
return false;
}
}
});
});
Probieren Sie es selbst aus, indem Sie die Tabulatortaste verwenden, um mit dieser Demo zu navigieren. Vergessen Sie nicht Ihre :focus-Styling!

Ein besserer Weg?
Es könnte für Benutzer im Allgemeinen besser sein, wenn wir diese Funktion handhaben, ohne das normale Browser-Navigationsverhalten zu kapern. Wenn Sie beispielsweise einem Link folgen, können Sie mit der Zurück-Schaltfläche des Browsers zurückkehren. Außerdem können Sie die aktuelle URL als Lesezeichen speichern (oder kopieren und einfügen), und der Browser wird von dem zuletzt geklickten Link zu diesem bestimmten Ziel navigieren.
// URL updates and the element focus is maintained
// originally found via in Update 3 on http://www.learningjquery.com/2007/10/improved-animated-scrolling-script-for-same-page-links
// filter handling for a /dir/ OR /indexordefault.page
function filterPath(string) {
return string
.replace(/^\//, '')
.replace(/(index|default).[a-zA-Z]{3,4}$/, '')
.replace(/\/$/, '');
}
var locationPath = filterPath(location.pathname);
$('a[href*="#"]').each(function () {
var thisPath = filterPath(this.pathname) || locationPath;
var hash = this.hash;
if ($("#" + hash.replace(/#/, '')).length) {
if (locationPath == thisPath && (location.hostname == this.hostname || !this.hostname) && this.hash.replace(/#/, '')) {
var $target = $(hash), target = this.hash;
if (target) {
$(this).click(function (event) {
event.preventDefault();
$('html, body').animate({scrollTop: $target.offset().top}, 1000, function () {
location.hash = target;
$target.focus();
if ($target.is(":focus")){ //checking if the target was focused
return false;
}else{
$target.attr('tabindex','-1'); //Adding tabindex for elements not focusable
$target.focus(); //Setting focus
};
});
});
}
}
}
});

Hier aktualisiert sich die URL mit jedem angeklickten Anker. Probieren Sie es selbst aus, indem Sie die Tabulatortaste verwenden, um mit dieser Demo zu navigieren.
Natives Beispiel
Schauen wir uns das native Browser-Beispiel aus dem CSS-Tricks-Post an. (Es gibt auch einen Polyfill.)
document.querySelector('#target-of-thing-clicked-on').scrollIntoView({
behavior: 'smooth'
});
Leider stoßen wir bei dieser Methode auf dasselbe Problem wie bei der jQuery-Methode, bei der die Seite im Viewport scrollt, aber der Tastaturfokus nicht aktualisiert wird. Wenn wir also diesen Weg gehen wollen, müssten wir immer noch .focus() setzen und sicherstellen, dass nicht fokussierbare Zielelemente tabindex="-1" erhalten.
Eine weitere Überlegung ist das Fehlen einer Callback-Funktion für das Ende des Scrollens. Das kann ein Problem sein oder auch nicht. Sie würden den Fokus gleichzeitig mit dem Scrollen verschieben und nicht am Ende, was vielleicht ein wenig seltsam ist oder auch nicht. Wie auch immer, es wird Arbeit zu tun geben!
Bewegung und Barrierefreiheit
Manche Menschen können buchstäblich krank werden von der schnellen Bewegung auf dem Bildschirm. Ich würde eine langsame Geschwindigkeit der Bewegung empfehlen, denn wenn der Benutzer über viel Inhalt springt, kann dies zu Schwindelgefühlen führen, wenn es zu schnell ist.
Außerdem ist es keine schlechte Idee, Benutzern eine Möglichkeit zu bieten, Animationen auszuschalten. Glücklicherweise hat Safari 10.1 die Reduced Motion Media Query eingeführt, die Entwicklern eine Methode bietet, Animationen so einzubinden, dass sie auf Browser-Ebene deaktiviert werden können.
/* JavaScript MediaQueryList Interface */
var motionQuery = window.matchMedia('(prefers-reduced-motion)');
if (motionQuery.matches) {
/* reduce motion */
}
motionQuery.addListener( handleReduceMotionChanged );
Leider haben andere Browser diese Funktion noch nicht implementiert. Bis die Unterstützung über einen einzigen Browser hinaus verbreitet ist, können wir dem Benutzer über die Benutzeroberfläche eine Option zum Aktivieren/Deaktivieren von Animationen anbieten, die Probleme verursachen könnten.
<label>
<input type="checkbox" id="animation" name="animation" checked="checked">
Enable Animation
</label>
$(this).click(function(event) {
if ($('#animation').prop('checked')) {
event.preventDefault();
$('html, body').animate({scrollTop: $target.offset().top}, 1000, function() {
location.hash = target;
$target.focus();
if ($target.is(":focus")) {
return !1;
} else {
$target.attr('tabindex', '-1');
$target.focus()
}
})
}
});
Probieren Sie es selbst aus mit dieser Demo.
Dies ist ein wirklich interessantes Thema. Der Trend zu Bewegung und Animation soll die räumliche Orientierung in einer ansonsten zweidimensionalen Benutzeroberfläche verbessern, was ziemlich interessant ist – und offensichtlich beliebt. Sie erwähnen, dass
aber es sind nicht nur manche – es sind viele. Leichte vestibuläre Störungen sind bei Männern sehr verbreitet, und obwohl es die Leute nicht zum Erbrechen bringen wird, wird es definitiv eine negative Benutzererfahrung sein, schockierend und ansonsten unerwünscht.
Der Schlüssel ist Kontrolle: Wenn Sie mit der Tabulatortaste durchgehen und unter den Viewport tabben, dann smoothscrollt die Seite, meiner Erfahrung nach ist die Empfindung von Lag und unkontrollierter Bewegung. Zuerst denke ich: Äh, warum hat sich der Viewport noch nicht geändert? Zweitens: Brech-würg [Kotzgeräusch]. Sie verstehen schon.
Der Viewport sollte sich mit der Geschwindigkeit des Fokus ändern, und Sie können ziemlich schnell tabben.
Auf der anderen Seite, wenn Sie ein Scrollrad oder einen Wisch verwenden oder mit der Scrollleiste interagieren, um absichtlich zu scrollen – dann ist das Animieren dieses Scrollens ziemlich harmlos. Aber, würde ich argumentieren, Tastaturnavigation != Scroll-Absicht. Dies sind unterschiedliche und getrennte Eingaben mit unterschiedlichen und getrennten Konventionen.
@Michael Schofield – Ja! Wir wollen nie, dass Leute krank werden, nur weil sie eine Website besuchen. Hoffentlich werden mehr Websites den Leuten die Möglichkeit bieten, Animationen auszuschalten ODER mehr Browser werden eingreifen und eine Lösung anbieten, wie Safari sie hat (darauf hoffe ich).
Eine weitere Überlegung ist das Fehlen einer Callback-Funktion für das Ende des Scrollens. Das kann ein Problem sein oder auch nicht. Sie würden den Fokus gleichzeitig mit dem Scrollen verschieben und nicht am Ende, was vielleicht ein wenig seltsam ist oder auch nicht. Wie auch immer, es wird Arbeit zu tun geben!Ich kann bestätigen, dass es ein Problem ist. Die Tatsache, dass focus() das Ziel kapert, das Smooth Scrolling und es springt direkt zum Ziel, abrupt.
Ich schätze, die Lösung wäre ein setTimeout() mit der gleichen Dauer wie das Scrollen, und darin verschieben Sie den Fokus. Fühlt sich aber nicht besonders elegant an.
Oder greifen Sie auf das animationend-Event zurück
Die einfachste kommende Methode ist definitiv
scroll-behaviorin CSS:root {
scroll-behavior: smooth;
}
Großartig!
scroll-behaviorwürde die Notwendigkeit von JS (für die Scroll-Aktion) beseitigen und die Notwendigkeit des Fokusmanagements beim Bewegen zu fokussierbaren Elementen negieren. Ich freue mich sehr auf die Implementierung dieser Funktion durch Browser.Allerdings müssten wir auf die eine oder andere Weise immer noch unfokussierbare Elemente (Abschnitt, div, span, h1-6 usw.) mit
tabindex="-1"fokussierbar machen.Zusätzlich müssen wir immer noch eine Möglichkeit bieten, das Scrollen für Leute zu deaktivieren, die die Bewegung schwindelerregend finden.
Trotzdem sieht das nach einer tollen CSS-Funktion aus! Danke fürs Teilen!
Es ist erwähnenswert, dass es auch eine entsprechende CSS-Eigenschaft scroll-behavior gibt, die auf
smoothgesetzt werden kann. Ich denke, das macht es möglich, sowohl Smooth Scrolling als auch Tastatur-Barrierefreiheit ohne JavaScript zu haben (in unterstützenden Browsern natürlich).Sie können überprüfen, ob ein Element per Skript fokussierbar ist, mit dem folgenden Code
Sie könnten so etwas tun
Hinweis: Verwenden Sie
location.hash, nichtthis.hash.Reduced Motion Media Query. Das ist etwas, das ich nicht wusste und sehr froh bin, darüber zu lernen. Danke, Chris.
Um Tastatur-freundliches Smooth Scrolling als progressive Verbesserung und ohne jQuery zu erreichen, können Sie so etwas mit Fetch Injection tun
const el = document.querySelector('details summary')
el.onclick = (evt) => {
fetchInject([
'https://cdn.jsdelivr.net/smooth-scroll/10.2.1/smooth-scroll.min.js'
])
el.onclick = null
}
Zusätzliche Informationen zu Fetch Injection finden Sie auf Hack Cabin.
Schöner Artikel und mir gefällt die Idee, Benutzern die Möglichkeit zu geben, Animationen zu deaktivieren.
In der letzten Demo funktioniert die Zurück-Schaltfläche in FF 52.0.2 nicht richtig: Die URL hat „null“ als letzten Pfadbestandteil vor dem Hash.
Eigentlich habe ich die URL falsch gelesen: Es ist nicht „null“, sondern „nujibey“. Mein Fehler. Dennoch funktioniert die Zurück-Schaltfläche nicht wie erwartet :)
Übersehe ich etwas? Warum mit :focus herumspielen, wenn wir das Ereignis nach unserer Scroll-Animation auslösen können?
Wenn wir einen hashchange auslösen, setzen wir den tabindex automatisch zurück. So funktioniert es
http://codepen.io/ppscvalentin/pen/JNNBzQ
Wenn das Ziel nicht fokussierbar ist, sollten Sie einen negativen tabindex (oder 0) hinzufügen und dann den Fokus darauf setzen.
Eigentlich nicht. Der tabindex wird auf den richtigen Wert gesetzt, wenn Sie window.location ändern. Sehen Sie sich den Stift an