Tworzenie komponentu przewijanego obrazu

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 stron z poziomym przewijaniem, które są minimalne, responsywne, dostępne i działają w różnych przeglądarkach i na różnych platformach (np. na telewizorach). Wypróbuj wersję demonstracyjną.

Demo

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ć, a 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. Dodatkowo eksperymentalne zapytanie o multimedia prefers-reduced-data służy do przekształcenia przewijacza multimediów w lekki przewijacz tytułów.

Zacznij od znaczników ułatwiających dostępność

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ć 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 baza z dostępem dla niepełnosprawnych.

Przesyłanie listy 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 w <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 mówionego dla użytkowników korzystających z technologii wspomagającej, takiej 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 używać zarówno jasnego, jak i ciemnego stylu 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 wczytywanie ciemnego motywu, który jest łagodniejszy 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ć. W pliku demonstracyjnym znajdują się 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 odpowiedni. Umożliwia też, aby treści multimedialne zastępowały rozmiar kolumny, 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 określony rozmiar kolumny, a jedynie zarządza 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 przesunięcia

Wyrównanie 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 przewijania Powyższe pokazuje, jak łatwo powinno być przesunąć kontener przewijania, 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łnienia na końcu paska przewijania, będę kierować się ostatnią liczbą w każdej liście i dodawać pseudoelement, który będzie odpowiadać pożądanej ilości wypełnienia.

.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ą być wyrównane 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, korzystając z pilota. 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. Typowy wzorzec rozwiązania tego problemu to 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 została zaprojektowana tak, aby umożliwić pominięcie potencjalnie długiej listy elementów, zamiast 50 razy naciskać klawisz tabulacji, aby dotrzeć do końca.

W pierwszym okienku w tym pokazie 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 wysyłane jest zapytanie do dokumentu dotyczące listy przewijania, a dla każdego z nich wywoływana jest funkcja 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 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 suwaków do przewijania dynamicznych 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żenia umożliwia również 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 ograniczenie danych;

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 zmniejszyć 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 pliku 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