Eine grundlegende Übersicht darüber, wie Sie eine reaktionsfähige horizontale Scrollview für Fernseher, Smartphones, Computer usw. erstellen.
In diesem Beitrag möchte ich einige Ideen für die Erstellung von horizontalen Scroll-Erlebnissen für das Web vorstellen, die minimal, responsiv und barrierefrei sind und in allen Browsern und auf allen Plattformen (z. B. Fernsehern) funktionieren. Demo ansehen
Wenn du lieber ein Video ansehen möchtest, findest du hier eine YouTube-Version dieses Beitrags:
Übersicht
Wir entwickeln ein horizontales Scroll-Layout, das für die Anzeige von Miniaturansichten von Medien oder Produkten gedacht ist. Die Komponente beginnt als einfache <ul>
-Liste, wird aber mit CSS in eine ansprechende und flüssige Scroll-Erfahrung umgewandelt, in der Bilder in einem Raster angezeigt werden. JavaScript wird hinzugefügt, um die Interaktion mit dem roving index zu erleichtern. So können Tastaturnutzer mehr als 100 Elemente überspringen.
Außerdem wird eine experimentelle Media-Query, prefers-reduced-data
, verwendet, um den Media-Scroller in einen einfachen Titel-Scroller zu verwandeln.
Mit barrierefreiem Markup beginnen
Ein Media-Scroller besteht aus nur wenigen Kernkomponenten, nämlich einer Liste mit Elementen. Eine Liste kann in ihrer einfachsten Form überall auf der Welt verwendet werden und ist für alle verständlich. Nutzer, die auf dieser Seite landen, können eine Liste durchsuchen und auf einen Link klicken, um einen Artikel aufzurufen. Das ist unsere barrierefreie Basis.
Stelle eine Liste mit einem <ul>
-Element bereit:
<ul class="horizontal-media-scroller">
<li></li>
<li></li>
<li></li>
...
<ul>
Machen Sie die Listenelemente mit einem <a>
-Element interaktiv:
<li>
<a href="#">
...
</a>
</li>
Verwenden Sie ein <figure>
-Element, um ein Bild und seine Bildunterschrift semantisch darzustellen:
<figure>
<picture>
<img alt="..." loading="lazy" src="https://picsum.photos/500/500?1">
</picture>
<figcaption>Legends</figcaption>
</figure>
Beachten Sie die Attribute alt
und loading
für das <img>
. Alt-Text für einen Media-Scroller ist eine UX-Möglichkeit, um dem Thumbnail zusätzlichen Kontext zu geben oder als Fallback-Text zu dienen, wenn das Bild nicht geladen wurde. Außerdem bietet er eine gesprochene Benutzeroberfläche für Nutzer, die auf assistive Technologien wie einen Screenreader angewiesen sind. Fünf goldene Regeln für konformen Alt-Text
Das Attribut loading
akzeptiert das Keyword lazy
, um anzugeben, dass diese Bildquelle nur abgerufen werden soll, wenn sich das Bild im Viewport befindet. Das ist besonders bei großen Listen nützlich, da Nutzer nur Bilder für Elemente herunterladen, die sie sich ansehen.
Farbschema des Nutzers unterstützen
Verwenden Sie color-scheme
als <meta>
-Tag, um dem Browser mitzuteilen, dass Ihre Seite sowohl die hellen als auch die dunklen User-Agent-Stile benötigt. Es ist ein kostenloser dunkler oder heller Modus, je nachdem, wie Sie es sehen:
<meta name="color-scheme" content="dark light">
Das Meta-Tag liefert das frühestmögliche Signal, sodass der Browser eine dunkle Standard-Canvas-Farbe auswählen kann, wenn der Nutzer ein dunkles Design bevorzugt. Das bedeutet, dass beim Wechsel zwischen Seiten der Website kein weißer Canvas-Hintergrund zwischen den Ladevorgängen angezeigt wird. Das dunkle Design wird nahtlos zwischen den Ladevorgängen angewendet, was angenehmer für die Augen ist.
Thomas Steiner hat https://web.dev/color-scheme/ einen ausführlichen Artikel dazu geschrieben.
Inhalt hinzufügen
Angesichts der oben genannten Inhaltsstruktur von ul > li > a > figure > picture > img
besteht die nächste Aufgabe darin, Bilder und Titel hinzuzufügen, durch die gescrollt werden kann. Die Demo enthält statische Platzhalterbilder und ‑text. Sie können aber auch Ihre bevorzugte Datenquelle verwenden.
Stil mit CSS hinzufügen
Jetzt ist es an der Zeit, dass CSS diese allgemeine Liste von Inhalten in ein Erlebnis verwandelt. Netflix, App-Stores und viele andere Websites und Apps verwenden Bereiche mit horizontalem Scrollen, um den Viewport mit Kategorien und Optionen zu füllen.
Scroller-Layout erstellen
Es ist wichtig, dass Inhalte in Layouts nicht abgeschnitten werden und dass Text nicht durch Ellipsen gekürzt wird. Viele Fernseher haben Media-Scroller wie diesen, aber allzu oft werden Inhalte ausgelassen. Bei diesem Layout ist das nicht der Fall. Außerdem kann der Media-Inhalt die Spaltengröße überschreiben. So ist ein Layout flexibel genug, um viele interessante Kombinationen zu ermöglichen.
Im Container kann die Spaltengröße überschrieben werden, indem die Standardgröße als benutzerdefinierte Eigenschaft angegeben wird. Bei diesem Rasterlayout wird die Spaltengröße festgelegt. Es werden nur Abstände und Richtung verwaltet:
.horizontal-media-scroller {
--size: 150px;
display: grid;
grid-auto-flow: column;
gap: calc(var(--gap) / 2); /* parent owned value for children to be relative to*/
margin: 0;
}
Die benutzerdefinierte Property wird dann vom <picture>
-Element verwendet, um unser Basis-Seitenverhältnis zu erstellen: ein Rechteck:
.horizontal-media-scroller {
--size: 150px;
display: grid;
grid-auto-flow: column;
gap: calc(var(--gap) / 2);
margin: 0;
& picture {
inline-size: var(--size);
block-size: var(--size);
}
}
Mit nur wenigen weiteren untergeordneten Stilen können Sie das Grundgerüst des Media-Scrollers fertigstellen:
.horizontal-media-scroller {
--size: 150px;
display: grid;
grid-auto-flow: column;
gap: calc(var(--gap) / 2);
margin: 0;
overflow-x: auto;
overscroll-behavior-inline: contain;
& > li {
display: inline-block; /* removes the list-item bullet */
}
& picture {
inline-size: var(--size);
block-size: var(--size);
}
}
Durch die Einstellung overflow
wird das <ul>
so eingerichtet, dass Scrollen und Tastaturnavigation in der Liste möglich sind. Anschließend wird bei jedem direkten untergeordneten <li>
-Element das ::marker
entfernt, indem ein neuer Anzeigetyp vom Typ inline-block
festgelegt wird.
Die Bilder sind jedoch noch nicht responsiv und ragen über die Grenzen der umgebenden Elemente hinaus. Mit einigen Größen-, Anpassungs- und Rahmenstilen sowie einem Hintergrundgradienten für das Lazy Loading können Sie sie zähmen:
img {
/* smash into whatever box it's in */
inline-size: 100%;
block-size: 100%;
/* don't squish but do cover the space */
object-fit: cover;
/* soften the edges */
border-radius: 1ex;
overflow: hidden;
/* if empty, show a gradient placeholder */
background-image:
linear-gradient(
to bottom,
hsl(0 0% 40%),
hsl(0 0% 20%)
);
}
Scroll-Padding
Die Ausrichtung am Seiteninhalt sowie eine Scrolling-Oberfläche, die sich über die gesamte Breite erstreckt, sind entscheidend für eine harmonische und minimalistische Komponente.
Um das Edge-to-Edge-Scroll-Layout zu erreichen, das mit unserer Typografie und unseren Layoutlinien übereinstimmt, verwenden Sie padding
, das mit scroll-padding
übereinstimmt:
.horizontal-media-scroller {
--size: 150px;
display: grid;
grid-auto-flow: column;
gap: calc(var(--gap) / 2);
margin: 0;
overflow-x: auto;
overscroll-behavior-inline: contain;
padding-inline: var(--gap);
scroll-padding-inline: var(--gap);
padding-block: calc(var(--gap) / 2); /* make space for scrollbar and focus outline */
}
Fehlerbehebung für horizontalen Scroll-Padding Das obige Beispiel zeigt, wie einfach es sein sollte, einen Scroll-Container mit Padding zu versehen. Es gibt jedoch noch Kompatibilitätsprobleme damit (in Chromium 91+ behoben). Hier finden Sie weitere Informationen zur Geschichte. Kurz gesagt: Padding wurde nicht immer in einer Scrollansicht berücksichtigt.
Damit Browser das Padding am Ende des Scrollers platzieren, richte ich das Targeting auf die letzte Abbildung in jeder Liste aus und hänge ein Pseudoelement an, das dem gewünschten Padding entspricht.
.horizontal-media-scroller > li:last-of-type figure {
position: relative;
&::after {
content: "";
position: absolute;
inline-size: var(--gap);
block-size: 100%;
inset-block-start: 0;
inset-inline-end: calc(var(--gap) * -1);
}
}
Durch die Verwendung logischer Eigenschaften kann der Media-Scroller in jedem Schreibmodus und jeder Dokumentrichtung verwendet werden.
Scroll Snap
Ein Scrolling-Container mit Überlauf kann mit einer Zeile CSS zu einem Snap-Viewport werden. Dann müssen die untergeordneten Elemente angeben, wie sie an diesem Viewport ausgerichtet werden sollen.
.horizontal-media-scroller {
--size: 150px;
display: grid;
grid-auto-flow: column;
gap: calc(var(--gap) / 2);
margin: 0;
overflow-x: auto;
overscroll-behavior-inline: contain;
padding-inline: var(--gap);
scroll-padding-inline: var(--gap);
padding-block-end: calc(var(--gap) / 2);
scroll-snap-type: inline mandatory;
& figure {
scroll-snap-align: start;
}
}
Fokus
Die Inspiration für diese Komponente stammt von ihrer enormen Beliebtheit auf Fernsehern, in App-Shops und mehr. Viele Videospielplattformen verwenden einen Media-Scroller, der diesem sehr ähnlich ist, als primäres Startbildschirmlayout. Der Fokus ist hier ein wichtiger UX-Moment und nicht nur eine kleine Ergänzung. Stellen Sie sich vor, Sie verwenden diesen Media-Scroller mit einer Fernbedienung von Ihrem Sofa aus. Diese Interaktion lässt sich noch etwas verbessern:
.horizontal-media-scroller a {
outline-offset: 12px;
&:focus {
outline-offset: 7px;
}
@media (prefers-reduced-motion: no-preference) {
& {
transition: outline-offset .25s ease;
}
}
}
Dadurch wird der Fokusumrissstil 7px
vom Feld entfernt, sodass etwas Platz entsteht. Wenn der Nutzer keine Einstellungen zur Reduzierung von Bewegungen hat, wird der Offset überblendet, wodurch das Fokusereignis subtil animiert wird.
Roving-Index
Gamepad- und Tastaturnutzer benötigen besondere Aufmerksamkeit bei diesen langen Listen mit scrollbaren Inhalten und Optionen. Die gängige Methode zur Lösung dieses Problems wird als roving index bezeichnet. Das ist der Fall, wenn ein Container mit Elementen mit der Tastatur fokussiert wird, aber nur ein untergeordnetes Element gleichzeitig den Fokus haben darf. Diese Funktion, bei der jeweils nur ein Element fokussiert wird, soll das Umgehen der möglicherweise langen Liste von Elementen ermöglichen. Nutzer müssen also nicht 50-mal oder öfter die Tabulatortaste drücken, um zum Ende zu gelangen.
Im ersten Scroller der Demo sind 300 Elemente enthalten. Wir können es besser machen, als sie alle durchlaufen zu lassen, um zum nächsten Abschnitt zu gelangen.
Damit diese Funktion genutzt werden kann, muss JavaScript Tastaturereignisse und Fokusereignisse beobachten. Ich habe eine kleine Open-Source-Bibliothek auf npm erstellt, um diese Nutzerfreundlichkeit zu ermöglichen. So verwenden Sie die Funktion für die drei Scroller:
import {rovingIndex} from 'roving-ux';
rovingIndex({
element: someElement
});
In dieser Demo wird das Dokument nach Scrollbereichen durchsucht und für jeden von ihnen die Funktion rovingIndex()
aufgerufen. Übergeben Sie das rovingIndex()
-Element, um das Roving-Erlebnis zu erhalten, z. B. einen Listencontainer, und einen Zielauswahl für die Abfrage, falls die Fokusziele keine direkten untergeordneten Elemente sind.
document.querySelectorAll('.horizontal-media-scroller')
.forEach(scroller =>
rovingIndex({
element: scroller,
target: 'a',
}))
Weitere Informationen zu diesem Effekt finden Sie in der Open-Source-Bibliothek roving-ux.
Seitenverhältnis
Zum Zeitpunkt der Veröffentlichung dieses Beitrags ist die Unterstützung für aspect-ratio
in Firefox noch nicht standardmäßig aktiviert, sondern muss über ein Flag aktiviert werden. In Chromium-Browsern oder Set-Top-Boxen ist sie jedoch verfügbar. Da im Rasterlayout für den Media-Scroller nur Richtung und Abstand angegeben werden, kann sich die Größe in einer Media-Query ändern, in der das Seitenverhältnis geprüft wird.
Progressive Enhancement in dynamischere Media-Scroller.
@supports (aspect-ratio: 1) {
.horizontal-media-scroller figure > picture {
inline-size: auto; /* for a block-size driven ratio */
aspect-ratio: 1; /* boxes by default */
@nest section:nth-child(2) & {
aspect-ratio: 16/9;
}
@nest section:nth-child(3) & {
/* double the size of the others */
block-size: calc(var(--size) * 2);
aspect-ratio: 4/3;
/* adjust size to fit more items into the viewport */
@media (width <= 480px) {
block-size: calc(var(--size) * 1.5);
}
}
}
}
Wenn der Browser die aspect-ratio
-Syntax unterstützt, werden die Bilder im Media-Scroller auf die aspect-ratio
-Größe aktualisiert. Bei Verwendung der Syntax für das Verschachteln von Entwürfen ändert sich das Seitenverhältnis der einzelnen Bilder je nachdem, ob sie sich in der ersten, zweiten oder dritten Zeile befinden. Mit der Nest-Syntax lassen sich auch einige kleine Anpassungen des Viewports direkt zusammen mit der anderen Größenanpassungslogik festlegen.
Mit diesem CSS wird, sobald die Funktion in weiteren Browser-Engines verfügbar ist, ein einfach zu verwaltendes, aber optisch ansprechenderes Layout gerendert.
Bevorzugt reduzierte Daten
Die folgende Technik ist zwar nur hinter einem Flag in Canary verfügbar, aber ich möchte Ihnen zeigen, wie ich mit ein paar Zeilen CSS eine erhebliche Menge an Seitenladezeit und Datennutzung sparen konnte. Mit der Media-Anfrage prefers-reduced-data
aus Level 5 lässt sich abfragen, ob sich das Gerät in einem Modus mit reduziertem Datenverbrauch befindet, z. B. im Datensparmodus. Wenn das der Fall ist, kann ich das Dokument ändern und die Bilder ausblenden.
figure {
@media (prefers-reduced-data: reduce) {
& {
min-inline-size: var(--size);
& > picture {
display: none;
}
}
}
}
Die Inhalte sind weiterhin navigierbar, ohne dass die großen Bilder heruntergeladen werden müssen. So sieht die Website vor dem Hinzufügen des prefers-reduced-data
-CSS aus:
(7 Anfragen, 100 KB Ressourcen in 131 ms)
So sieht die Websiteleistung nach dem Hinzufügen des prefers-reduced-data
-CSS aus:
(71 Anfragen, 1,2 MB Ressourcen in 1,07 Sekunden)
64 Anfragen weniger, das wären die etwa 60 Bilder im sichtbaren Bereich (Tests auf einem Breitbildschirm) dieses Browser-Tabs, eine Steigerung des Seitenaufrufs um etwa 80 % und 10% der Daten über die Leitung. Sehr leistungsstarkes CSS.
Fazit
Jetzt wissen Sie, wie ich es gemacht habe. Wie würden Sie es machen? 🙂
Wir möchten unsere Ansätze diversifizieren und alle Möglichkeiten kennenlernen, die das Web bietet. Erstelle einen Codepen oder hoste deine eigene Demo, sende mir einen Tweet mit dem Link und ich füge sie unten im Abschnitt „Community-Remixe“ hinzu.
Quelle
Community-Remixe
Noch keine Aktivität hierzu.