Komponente für die Bildlaufleiste für Medien erstellen

Eine grundlegende Übersicht zum Erstellen einer responsiven horizontalen ScrollView für Fernseher, Smartphones, Computer usw.

In diesem Beitrag möchte ich darüber sprechen, wie horizontales Scrollen für das Web gestaltet werden kann, das minimal, responsiv und barrierefrei ist und über verschiedene Browser und Plattformen (z. B. Fernseher) funktioniert. Demo ansehen

Demo

Falls du lieber ein Video hast, findest du hier eine YouTube-Version dieses Beitrags:

Überblick

Wir erstellen ein horizontales Scroll-Layout, das für Miniaturansichten von Medien oder Produkten vorgesehen ist. Die Komponente beginnt als einfache <ul>-Liste, wird aber mit CSS in ein zufriedenstellendes und flüssiges Scrollen umgewandelt, in dem Bilder präsentiert und an einem Raster ausgerichtet werden. JavaScript wird hinzugefügt, um den Wechselindex zu erleichtern, sodass Tastaturnutzer mehr als 100 Elemente überspringen können. Außerdem wird die experimentelle Medienabfrage prefers-reduced-data verwendet, um den Medien-Scroller in ein schlankes Scroller-Erlebnis für den Titel umzuwandeln.

Mit barrierefreiem Markup beginnen

Ein Medien-Scroller besteht aus nur ein paar Kernkomponenten, einer Liste mit Elementen. Eine Liste in ihrer einfachsten Form kann um die ganze Welt reisen und eindeutig von allen aufgerufen werden. Ein Nutzer, der auf diese Seite gelangt, kann eine Liste durchsuchen und auf einen Link klicken, um einen Artikel aufzurufen. Das ist die barrierefreie Basis.

Stelle eine Liste mit einem <ul>-Element bereit:

<ul class="horizontal-media-scroller">
  <li></li>
  <li></li>
  <li></li>
  ...
<ul>

Gestalten Sie die Listeneinträge mit einem <a>-Element interaktiv:

<li>
  <a href="#">
    ...
  </a>
</li>

Verwenden Sie ein <figure>-Element, um ein Bild und seinen Untertitel 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 in <img>. Der Alt-Text für einen Medien-Scroller ist eine UX-Chance, um der Miniaturansicht zusätzlichen Kontext zu bieten, oder als Fallback-Text, wenn das Bild nicht geladen wurde, oder als Fallback-Text für Nutzer, die auf assistive Technologien wie einen Screenreader angewiesen sind. Weitere Informationen finden Sie unter Fünf goldene Regeln für konformen Alt-Text.

Das Attribut loading akzeptiert das Schlüsselwort lazy als Signal dafür, dass diese Bildquelle nur abgerufen werden soll, wenn sich das Bild im Darstellungsbereich befindet. Das kann bei großen Listen wirklich hilfreich sein, da Nutzer nur Bilder für Elemente herunterladen, zu denen sie gescrollt haben.

Unterstützt die bevorzugten Farbschemata der Nutzenden.

Verwende color-scheme als <meta>-Tag, um dem Browser zu signalisieren, dass deine Seite sowohl den hellen als auch den dunklen User-Agent-Stil verwenden möchte. Je nachdem, wie man es sieht, ist der dunkle oder der helle Modus kostenlos:

<meta name="color-scheme" content="dark light">

Das Meta-Tag liefert das frühestmögliche Signal, sodass der Browser eine dunkle Standard-Canvasfarbe auswählen kann, wenn der Nutzer ein dunkles Design bevorzugt. Das bedeutet, dass beim Navigieren zwischen Seiten der Website zwischen dem Laden kein weißer Canvas-Hintergrund eingeblendet wird. Nahtloses dunkles Design zwischen Ladevorgängen, deutlich besser für die Augen.

Weitere Informationen von Thomas Steiner finden Sie unter https://web.dev/color-scheme/.

Inhalt hinzufügen

Angesichts der obigen Inhaltsstruktur von ul > li > a > figure > picture > img besteht die nächste Aufgabe darin, Bilder und Titel hinzuzufügen, um durchzuscrollen. Ich habe die Demo mit statischen Platzhalterbildern und -text gepackt, aber Sie können dies auch mit Ihrer bevorzugten Datenquelle unterstützen.

Stil mit CSS hinzufügen

Jetzt ist es an der Zeit, dass das CSS diese allgemeine Inhaltsliste in ein Erlebnis umwandelt. Netflix, App-Shops und viele weitere Websites und Apps verwenden horizontale Scrollbereiche, um den Darstellungsbereich mit Kategorien und Optionen zu füllen.

Scroller-Layout erstellen

Es ist wichtig, zu vermeiden, dass Inhalte in Layouts abgeschnitten werden und Text durch Auslassungspunkte abgeschnitten wird. Viele Fernseher haben wie dieser Scroller, aber allzu oft sind Inhalte mit Auslassungspunkte zu sehen. Bei diesem Layout ist das nicht der Fall. Außerdem kann die Spaltengröße durch den Medieninhalt überschrieben werden, sodass ein Layout flexibel genug ist, um viele interessante Kombinationen zu verarbeiten.

2 scrolling-Zeilen angezeigt. Eine hat keine Auslassungspunkte, was bedeutet, dass sie höher und jeder Titel vollständig lesbar ist. Der andere ist kürzer und viele Titel sind durch Auslassungspunkte abgeschnitten.

Der Container kann die Spaltengröße überschreiben, indem er die Standardgröße als benutzerdefinierte Eigenschaft angibt. Dieses Rasterlayout bezieht sich auf die Spaltengröße. Es verwaltet nur den Abstand und die Richtung:

.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 Eigenschaft wird dann vom <picture>-Element verwendet, um unser grundlegendes Seitenverhältnis zu erstellen: ein Feld:

.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 noch ein paar kleinen Stilen kannst du die grundlegenden Elemente des Medien-Scrollers vervollständigen:

.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);
  }
}

Wenn Sie overflow festlegen, wird <ul> so eingerichtet, dass das Scrollen und die Tastaturnavigation durch die Liste möglich ist. Für jedes direkt untergeordnete <li>-Element wird ::marker entfernt, indem der neue Anzeigetyp inline-block abgerufen wird.

Die Bilder sind jedoch noch nicht responsiv und platzen direkt aus den Boxen, in denen sie sich befinden. Passen Sie sie mit Größen, Passform und Rahmenstilen sowie einem Farbverlauf für den Hintergrund an, um sie beim Lazy Loading zu verwenden:

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%)
    );
}

Abstand scrollen

Die Ausrichtung an den Seiteninhalten sowie eine randlose Scroll-Oberfläche sind entscheidend für eine harmonische und minimale Komponente.

Um das von Rand zu Rand scrollende Layout zu erreichen, das mit unseren Typografie- und Layoutzeilen ü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 */
}

Fehlerkorrektur beim horizontalen Scrollen beim Padding Das Beispiel oben zeigt, wie einfach es sein sollte, einen Scroll-Container mit Auffüllung zu füllen. Allerdings gibt es noch offene Kompatibilitätsprobleme damit. Diese wurden aber in Chromium 91 und höher behoben. Hier finden Sie einen Teil des Verlaufs. Kurz gesagt: Der Innenrand wurde in Scroll-Ansichten nicht immer berücksichtigt.

Am Inline-Ende des letzten Listenelements wird ein Kästchen hervorgehoben. Der Abstand und das Element haben dieselbe Breite wie bei der gewünschten Ausrichtung.

Um Browser dazu zu bringen, den Innenrand am Ende des Scrollers einzufügen, wähle ich die letzte Zahl in jeder Liste aus und füge ein Pseudoelement hinzu, das dem gewünschten Abstand 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);
  }
}

Die Verwendung logischer Eigenschaften ermöglicht es dem Medien-Scroller, in jedem Schreibmodus und in jeder Dokumentrichtung zu arbeiten.

Scroll Snap

Ein scrollbarer Container mit Überlauf kann zu einem flexiblen Darstellungsbereich mit einer CSS-Zeile werden. Anschließend müssen bei untergeordneten Elementen festgelegt werden, wie sie an diesen Darstellungsbereich 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 ist ihre enorme Beliebtheit auf Fernsehern, in App-Shops und mehr. Auf vielen Videospielplattformen wird ein Medien-Scroller als primäres Layout für den Startbildschirm verwendet. Fokus ist hier ein großer UX- Moment, nicht nur eine Kleinigkeit. Stellen Sie sich vor, Sie könnten diesen Medien-Scroller von Ihrem Sofa aus mit einer Fernbedienung verwenden. Erweitern Sie diese Interaktion um ein paar kleine Verbesserungen:

.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 Stil des Fokusumrisses 7px vom Feld entfernt, um etwas mehr Platz zu schaffen. Wenn der Nutzer keine Präferenzen bei der Reduzierung von Bewegungen hat, wird der Offset umgestellt, sodass dem Fokusereignis eine subtile Bewegung zugewiesen wird.

Roving-Index

Gamepad- und Tastaturnutzer benötigen in diesen langen Listen mit scrollbaren Inhalten und Optionen besondere Aufmerksamkeit. Das gängige Muster zur Lösung dieses Problems wird als Roving-Index bezeichnet. Das ist der Fall, wenn ein Container mit Elementen mit der Tastatur fokussiert ist, aber immer nur ein untergeordnetes Element gleichzeitig den Fokus halten darf. Dieses einzelne fokussierbare Element ist so konzipiert, dass die potenziell lange Liste von Elementen umgangen werden kann, anstatt die Tabulatortaste mehr als 50-mal zu drücken, um das Ende zu erreichen.

Der erste Scroller der Demo enthält 300 Elemente. Wir können sie besser machen, als sie alle durchlaufen zu lassen, um zum nächsten Abschnitt zu gelangen.

Dazu muss JavaScript Tastaturereignisse erfassen und fokussieren. Ich habe auf npm eine kleine Open-Source-Bibliothek erstellt, um diese Nutzererfahrung zu vereinfachen. So verwenden Sie ihn für die drei Scroller:

import {rovingIndex} from 'roving-ux';

rovingIndex({
  element: someElement
});

In dieser Demo wird das Dokument nach den Scrollern abgefragt und für jeden wird die Funktion rovingIndex() aufgerufen. Übergeben Sie das Element rovingIndex(), um die Umgebung zu erhalten, z. B. einen Listencontainer und einen Zielabfrageselektor, für den Fall, dass die Fokusziele keine direkten Nachfolger 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 Erstellung dieses Beitrags ist die Unterstützung für aspect-ratio in Firefox hinter einer Markierung verborgen, aber in Chromium-Browsern oder Set-Top-Boxen verfügbar. Da das Rasterlayout für das Media-Scroller nur Richtung und Abstände vorgibt, kann sich die Größe innerhalb einer Medienabfrage ändern, die die Unterstützung des Seitenverhältnisses prüft. Progressive Enhancement in einige dynamischere Medien-Scroller.

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

@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 Scroller-Bilder auf die aspect-ratio-Größe aktualisiert. Mithilfe der Verschachtelungssyntax ändert jedes Bild sein Seitenverhältnis, je nachdem, ob es sich um die erste, zweite oder dritte Zeile handelt. Dank der verschachtelten Syntax können auch einige kleine Anpassungen des Darstellungsbereichs direkt mit der anderen Logik für die Größenanpassung festgelegt werden.

Mit diesem CSS wird ein einfach zu verwaltendes, aber optisch ansprechenderes Layout gerendert, da die Funktion in mehr Browser-Engines verfügbar ist.

Bevorzugt weniger Daten

Diese nächste Technik ist zwar nur hinter einem Flag in Canary verfügbar, aber ich wollte Ihnen zeigen, wie ich mit ein paar CSS-Zeilen eine erhebliche Seitenladezeit und Datennutzung einsparen kann. Mit der prefers-reduced-data-Medienabfrage von Ebene 5 kann erfragt werden, ob sich das Gerät in einem reduzierten Datenstatus befindet, z. B. im Datensparmodus. Falls ja, kann ich das Dokument bearbeiten und die Bilder in diesem Fall ausblenden.

ALT_TEXT_HERE

figure {
  @media (prefers-reduced-data: reduce) {
    & {
      min-inline-size: var(--size);

      & > picture {
        display: none;
      }
    }
  }
}

Die Inhalte sind weiterhin navigierbar, allerdings ohne die Kosten für den Download umfangreicher Bilder. Hier ist die Website, bevor das prefers-reduced-data-CSS hinzugefügt wird:

(7 Anfragen, 100 KB an Ressourcen in 131 ms)

ALT_TEXT_HERE

Hier ist die Websiteleistung nach dem Hinzufügen des CSS-Codes prefers-reduced-data:

ALT_TEXT_HERE

(71 Anfragen, 1,2 MB Ressourcen in 1,07 Sek.)

64 weniger Anfragen. Das wären die etwa 60 Bilder im Darstellungsbereich (Tests auf einem Breitbilddisplay) dieses Browsertabs, eine Steigerung der Seitenladezeit um ca. 80 % und 10% der übertragenen Daten. Ziemlich leistungsstarkes CSS

Fazit

Jetzt, wo du weißt, wie ich es gemacht habe, wie würdest du es tun?! 🙂

Diversifizieren wir unsere Ansätze und lernen Sie alle Möglichkeiten kennen, wie wir das Web nutzen können. Erstelle einen Codepen oder veranstalte deine eigene Demo, twittere mich mit ihr und ich füge sie unten zum Abschnitt „Community-Remixe“ hinzu.

Quelle

Community-Remixe

Hier gibt es noch nichts zu sehen.