Medien-Scroller-Komponente erstellen

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

Demo

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.

2
scrollende Zeilen werden angezeigt. Bei der einen gibt es keine Auslassungspunkte, was bedeutet, dass sie höher ist und jeder Titel vollständig lesbar ist. Die andere ist kürzer und viele Titel werden mit Auslassungspunkten abgeschnitten.

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.

Auf der Inline-End-Seite des letzten Listenelements wird ein Feld hervorgehoben, das zeigt, dass das Padding und das Element dieselbe Breite haben, um die gewünschte Ausrichtung zu erzielen.

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-ratioin 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.

Neben den anderen verwendeten Seitenverhältnissen von 16:9 und 4:3 ist ein Feld mit einem Seitenverhältnis von 4:4 zu sehen.

@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.

ALT_TEXT_HERE

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)

ALT_TEXT_HERE

So sieht die Websiteleistung nach dem Hinzufügen des prefers-reduced-data-CSS aus:

ALT_TEXT_HERE

(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.