Tworzenie komponentu przewijającego multimedia

Podstawowy przegląd tworzenia elastycznego widoku przewijania poziomego na potrzeby telewizorów, telefonów, komputerów itp.

W tym poście chcę podzielić się z Wami sposobami na tworzenie w internecie minimalistycznych, responsywnych i dostępnych rozwiązań z przewijaniem poziomym, które działają w różnych przeglądarkach i na różnych platformach (np. telewizorach). Wypróbuj wersję demonstracyjną.

Demonstracja

Jeśli wolisz film, oto wersja tego posta w YouTube:

Omówienie

Będziemy tworzyć układ z poziomym przewijaniem przeznaczony do hostowania miniatur multimediów lub produktów. Komponent zaczyna się od zwykłej listy <ul>, ale dzięki CSS staje się przyjemnym i płynnym elementem, który wyświetla obrazy i umieszcza je w siatce. Dodaliśmy kod JavaScript, aby ułatwić interakcje z przeszukiwaniem indeksu ruchomego, co pozwala użytkownikom korzystającym z klawiatury pomijać ponad 100 elementów. Ponadto eksperymentalna definicja media prefers-reduced-data służy do zamiany przewijacza multimediów na lekki przewijacz tytułów.

Zacznij od znaczników ułatwień dostępu

Scroller multimedialny składa się tylko z kilku podstawowych elementów, czyli listy z elementami. Lista w najprostszej formie może podróżować po całym świecie i być łatwo dostępna dla wszystkich. Użytkownik, który otworzy tę stronę, może przejrzeć listę i kliknąć link, aby wyświetlić element. To jest nasza podstawa.

Prześlij listę z elementem <ul>:

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

Aby elementy listy były interaktywne, użyj elementu <a>:

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

Użyj elementu <figure>, aby semantycznie przedstawić obraz i jego podpis:

<figure>
  <picture>
    <img alt="..." loading="lazy" src="https://picsum.photos/500/500?1">
  </picture>
  <figcaption>Legends</figcaption>
</figure>

Zwróć uwagę na atrybuty alt i loading <img>. Tekst alternatywny dla scrollera multimediów to możliwość zwiększenia użyteczności, która pomoże w dodaniu kontekstu do miniatury. Może też służyć jako tekst zastępczy, jeśli obraz nie załaduje się, lub jako element interfejsu głosowego dla użytkowników korzystających z technologii wspomagającej, takich jak czytnik ekranu. Dowiedz się więcej z 5 złotych zasad dotyczących zgodnego tekstu alternatywnego.

Atrybut loading akceptuje słowo kluczowe lazy jako sygnał, że źródło obrazu powinno zostać pobrane tylko wtedy, gdy obraz znajduje się w widocznym obszarze. Może to być bardzo przydatne w przypadku dużych list, ponieważ użytkownicy będą pobierać tylko obrazy elementów, które są widoczne na ekranie.

Obsługa preferowanego schematu kolorów użytkownika

Użyj color-scheme jako tagu <meta>, aby zasygnalizować przeglądarce, że strona chce używać zarówno jasnego, jak i ciemnego stylu klienta użytkownika. Może to być bezpłatny tryb ciemny lub jasny, w zależności od tego, jak na to patrzysz:

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

Tag meta dostarcza możliwie najszybszy sygnał, dzięki czemu przeglądarka może wybrać ciemny domyślny kolor tła, jeśli użytkownik preferuje ciemny motyw. Oznacza to, że podczas przechodzenia między stronami witryny nie będzie się pojawiać białe tło. Bezproblemowe przełączanie się między ciemnym motywem podczas wczytywania, co jest przyjemniejsze dla oczu.

Dowiedz się więcej od Thomasa Steinera na stronie https://web.dev/color-scheme/.

Dodaj treść

Powyższa struktura treści ul > li > a > figure > picture > img wymaga dodania obrazów i tytułów, które będą się przewijać. Demo zawiera statyczne obrazy zastępcze i tekst, ale możesz też użyć ulubionego źródła danych.

Dodawanie stylów za pomocą kodu CSS

Nadszedł czas, aby usługa CSS przekształciła tę ogólną listę treści w doświadczenie. Netflix, sklepy z aplikacjami i wiele innych witryn i aplikacji używają obszarów przewijania poziomego, aby wypełnić widok z poziomu urządzenia kategoriami i opcjami.

Tworzenie układu przewijania

Unikaj obcinania treści w układach lub stosowania wielokropka do obcinania tekstu. Wiele telewizorów ma scrollery mediów takie jak ten, ale zbyt często uciekają się do pomijania treści. Ten układ nie jest odpowiedni. Pozwala to też zastępować rozmiar kolumny przez treści multimedialne, dzięki czemu 1 układ jest wystarczająco elastyczny, aby obsłużyć wiele interesujących kombinacji.

2. Wyświetlane są przewijane wiersze. Jeden tytuł nie ma wielokropka, co oznacza, że jest wyższy i wszystkie tytuły są w pełni czytelne. Drugi jest krótszy, a wiele tytułów jest obcięte.

Kontener umożliwia zastąpienie rozmiaru kolumny przez podanie domyślnego rozmiaru jako właściwości niestandardowej. Ten układ siatki uwzględnia tylko rozmiar kolumny – zarządza jedynie odstępami i kierunkiem:

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

Właściwość niestandardowa jest następnie używana przez element <picture> do utworzenia podstawowego formatu obrazu: prostokąta:

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

Wystarczy dodać jeszcze kilka drobnych stylów, aby uzupełnić podstawowe elementy scrollera multimediów:

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

Ustawienie overflow powoduje skonfigurowanie elementu <ul> w celu umożliwienia przewijania i przechodzenia po liście za pomocą klawiatury. Następnie każdy bezpośredni element podrzędny <li> ma ::marker usunięty, ponieważ ma nowy typ wyświetlania inline-block.

Zdjęcia nie są jeszcze responsywne i wychodzą poza pudełka, w których się znajdują. Możesz je dostosować, wybierając rozmiary, dopasowanie i styl obramowania, a także gradient tła, gdy są ładowane z opóźnieniem:

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

Dopełnienie przewijania

Dopasowanie do zawartości strony oraz powierzchnia przewijania od krawędzi do krawędzi są kluczowe dla harmonijnego i minimalistycznego komponentu.

Aby utworzyć układ przewijania od krawędzi do krawędzi, który jest zgodny z naszymi liniami typografii i układu, użyj elementu padding pasującego do scroll-padding:

.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 */
}

Poprawka błędu związanego z wypełnieniem poziomego pola nawigacji Powyższe pokazuje, jak łatwo powinno być przesunąć kontener nawigacji, ale występują z tym problemy ze zgodnością (poprawione w Chromium 91+). Więcej informacji znajdziesz tutaj. W skrócie mówimy, że w widoku przewijania dopełnienie nie zawsze było uwzględniane.

Pole jest wyróżnione po stronie końcowej ostatniego elementu listy, co pokazuje, że element i wypełnienie mają taką samą szerokość, aby zapewnić prawidłowe wyrównanie.

Aby oszukać przeglądarki i zmusić je do umieszczenia wypełniacza na końcu scrollera, będę kierować się ostatnią liczbą w każdej liście i dodawać pseudoelement, który będzie odpowiadać pożądanej ilości wypełniacza.

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

Korzystanie z właściwości logicznych umożliwia działanie scrollera multimediów w dowolnym trybie pisania i w dowolnym kierunku dokumentu.

Przewijanie z przyciąganiem

Scrollowany kontener z przepełnieniem może stać się Viewportem z wyrównaniem za pomocą jednego wiersza kodu CSS. Następnie elementy podrzędne muszą określić, jak mają się wyrównać do tego Viewportu.

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

Koncentracja

Ten komponent został zainspirowany jego ogromną popularnością w telewizji, sklepach z aplikacjami i innych miejscach. Wiele platform gier wideo używa suwaka multimediów bardzo podobnego do tego jako głównego układu ekranu głównego. W tym przypadku skupienie się na UX to nie tylko małe uzupełnienie, ale bardzo ważny element. Wyobraź sobie, że używasz scrollera multimediów na kanapie z pilotem. Wprowadź kilka drobnych ulepszeń:

.horizontal-media-scroller a {
  outline-offset: 12px;

  &:focus {
    outline-offset: 7px;
  }

  @media (prefers-reduced-motion: no-preference) {
    & {
      transition: outline-offset .25s ease;
    }
  }
}

Spowoduje to ustawienie stylu obrysu 7px z dala od pola, co zapewni mu odpowiednią przestrzeń. Jeśli użytkownik nie ma preferencji dotyczących redukcji ruchu, przesunięcie jest przekształcane, co powoduje subtelny ruch w zdarzeniu fokusa.

indeks przemieszczania się,

Użytkownicy kontrolerów i klawiatur muszą zwracać szczególną uwagę na długie listy przewijanych treści i opcji. Typowy wzorzec rozwiązania tego problemu to wskaźnik ruchomy. Jest to sytuacja, gdy kontener elementów jest zaznaczony za pomocą klawiatury, ale tylko 1 element podrzędny może być zaznaczony naraz. Ta funkcja umożliwiająca skupienie się na jednym elemencie naraz ma na celu umożliwienie pomijania potencjalnie długiej listy elementów zamiast naciskania klawisza tabulacji ponad 50 razy, aby dotrzeć do końca.

W pierwszym okienku w prezentacji jest 300 elementów. Możemy zrobić coś więcej niż kazać im przejść przez wszystkie, aby dotrzeć do następnej sekcji.

Aby to umożliwić, JavaScript musi obserwować zdarzenia związane z klawiaturą i skupieniem. Aby ułatwić tworzenie tego typu interfejsu użytkownika, utworzyłem małą bibliotekę open source w npm. Oto jak go używać w przypadku 3 rolki:

import {rovingIndex} from 'roving-ux';

rovingIndex({
  element: someElement
});

W tym pokazie zapytanie do dokumentu zwraca listę przewijanych elementów i dla każdego z nich wywołuje funkcję rovingIndex(). Przekaż element rovingIndex(), aby rozpocząć korzystanie z aplikacji, np. kontener listy i selektor zapytania docelowego, na wypadek, gdyby docelowe elementy docelowe nie są bezpośrednimi elementami podrzędnymi.

document.querySelectorAll('.horizontal-media-scroller')
  .forEach(scroller =>
    rovingIndex({
      element: scroller,
      target: 'a',
}))

Więcej informacji o tym efekcie znajdziesz w bibliotece open source roving-ux.

Współczynnik proporcji

W momencie pisania tego posta obsługa aspect-ratio kryje się za flagą w Firefoksie, ale jest ona dostępna w przeglądarkach Chromium i na dekoderach. Ponieważ układ siatki scrollerów multimediów określa tylko kierunek i odstępy, rozmiar może się zmieniać w ramach zapytania o multimedium, które sprawdza obsługę proporcji. Stopniowe ulepszenie w bardziej dynamicznych przewijanych treściach.

Ramka o współczynniku proporcji 4:4 wyświetla się obok innych formatów obrazu 16:9 i 4:3.

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

Jeśli przeglądarka obsługuje składnię aspect-ratio, obrazy w scrollerze multimediów są przekształcane do rozmiaru aspect-ratio. Dzięki użyciu składni zagnieżdżania projektu każdy obraz zmienia format w zależności od tego, czy znajduje się w pierwszej, drugiej czy trzeciej kolumnie. Składnia gniazda umożliwia też wprowadzanie drobnych korekt widocznego obszaru w ramach innej logiki rozmiarów.

Dzięki temu kodowi CSS, który jest dostępny w większej liczbie silników przeglądarek, będzie można renderować łatwy w zarządzaniu, ale bardziej atrakcyjny wizualnie układ.

Preferowane są ograniczone dane

Chociaż ta technika jest dostępna tylko za pomocą flagi w wersji Canary, chcę pokazać, jak za pomocą kilku linii kodu CSS udało mi się znacznie skrócić czas wczytywania strony i ograniczyć wykorzystanie danych. Zapytanie o multimedia prefers-reduced-data na poziomie 5 umożliwia sprawdzenie, czy urządzenie jest w stanie ograniczonego zużycia danych, np. w trybie oszczędzania danych. Jeśli tak, mogę zmodyfikować dokument, a w tym przypadku ukryć obrazy.

ALT_TEXT_HERE

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

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

Nadal można poruszać się po witrynie, ale nie wiąże się to z kosztami pobierania ciężkich obrazów. Oto strona przed dodaniem kodu CSS prefers-reduced-data:

(7 żądań, 100 KB zasobów w 131 ms)

ALT_TEXT_HERE

Skuteczność witryny po dodaniu prefers-reduced-data CSS:

ALT_TEXT_HERE

(71 żądań, 1,2 MB zasobów w 1,07 s)

64 mniej żądań, czyli około 60 obrazów w widoku (testy przeprowadzone na wyświetlaczu panoramicznym) na tej karcie przeglądarki, przyspieszenie wczytywania strony o około 80% i 10% danych przesyłanych przez sieć. dość potężny kod CSS.

Podsumowanie

Skoro już wiesz, jak to robię, jak Ty?! 🙂

Stosujmy różne podejścia i poznajmy sposoby budowania obecności w internecie. Utwórz Codepen lub opublikuj własne demo, tweetuj je, a ja dodam je do sekcji Remixe społeczności poniżej.

Źródło

Remiksy społeczności

Na razie jest tu pusto