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 można przewijać, wyświetlając obrazy i umieszczając 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łatwiających dostępność

Scroller multimediów 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 altloading w elementach <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, aby zasygnalizować, że źródło obrazu powinno być pobierane tylko wtedy, gdy obraz znajduje się w obszarze widoku. 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 tagu color-scheme jako tagu <meta>, aby zasygnalizować przeglądarce, że Twoja strona chce wyświetlać zarówno jasny, jak i ciemny styl użytkownika. Jest to bezpłatny tryb ciemny lub jasny, w zależności od tego, jak na to spojrzysz:

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

Metatag 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 znacznie 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

Teraz usługa porównywania cen musi wziąć tę ogólną listę treści i przekształcić ją 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 skracania tekstu za pomocą wielokropka. 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 jednak tak dobry. Pozwala też na zastąpienie rozmiaru kolumny przez rozmiar treści multimedialnych, dzięki czemu 1 szablon jest na tyle elastyczny, że można go stosować w wielu ciekawych kombinacjach.

2. Wyświetlane są przewijane wiersze. Jeden nie ma wielokropka, co oznacza, że jest wyższy, a każdy tytuł jest w pełni czytelny. 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 ma wpływ na rozmiar kolumny, ponieważ zarządza tylko 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 obrazy 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%)
    );
}

Odstęp od krawędzi

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

Aby uzyskać układ przewijania od krawędzi do krawędzi, który jest zgodny z naszą typografią i liniami układu, użyj padding, który pasuje 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 na ten temat znajdziesz tutaj. Krótko mówiąc, w przypadku widoku przewijania nie zawsze uwzględniano wypełnienie.

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, a potem elementy podrzędne muszą określić, jak chcą się do niego dopasować.

.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ą na telewizorach, w sklepach z aplikacjami i w 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 treści i opcji. Typowym wzorcem rozwiązania tego problemu jest indeks 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ć osiągnięcie tego efektu, 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 funkcja rovingIndex() wysyła zapytanie do dokumentu dotyczące listy przewijania i dla każdego elementu wywołuje funkcję rovingIndex(). Przekaż element rovingIndex(), aby uzyskać możliwość przemieszczania się po elementach, np. kontenerze listy, oraz selektorze zapytań docelowych, jeśli cele nie są bezpośrednimi potomkami.

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.

Format obrazu

W momencie pisania tego posta obsługa aspect-ratio jest dostępna w Firefoxie za pomocą flagi, ale w przeglądarkach opartych na Chromium i w urządzeniach set-top box. Ponieważ układ siatki scrollerów multimediów określa tylko kierunek i odstępy, rozmiar może się zmieniać w ramach zapytania o multimedię, które sprawdza obsługę proporcji. stopniowe ulepszanie niektórych bardziej dynamicznych scrollerów multimediów;

Obok innych współczynników proporcji 16:9 i 4:3 wyświetla się pole z współczynnikiem proporcji 4:4.

@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 w wersji roboczej każda fotografia zmienia współczynnik proporcji w zależności od tego, czy znajduje się w pierwszej, drugiej czy trzeciej kolumnie. Składnia zagnieżdżania umożliwia też wprowadzanie drobnych korekt widocznego obszaru w ramach logiki ustawiania 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.

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

Treści nadal można przeglądać, ale bez konieczności pobierania dużych obrazów. Oto witryna 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

Teraz, gdy już wiesz, jak to zrobić, jak Ty to zrobisz? 🙂

Zróżnicujemy nasze podejścia i poznamy wszystkie sposoby tworzenia stron internetowych. Utwórz Codepen lub prześlij 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