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 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ł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ć zrozumiała 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 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%)
    );
}

Odstęp od krawędzi

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 odnośnie przewijania Powyższe pokazuje, jak łatwo powinno być przesunąć kontener przewijania, ale występują z tym problemy ze zgodnością (poprawka 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 suwaka, 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ą 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 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, 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 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 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 zapytanie do dokumentu zwraca listę przewijanych elementów i dla każdego z nich 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ż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 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 zmniejszyć wykorzystanie danych. Zapytanie dotyczące multimediów o poziomie 5 umożliwia sprawdzenie, czy urządzenie jest w stanie ograniczonego zużycia danych, np. w trybie oszczędzania danych.prefers-reduced-data 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 widocznym obszarze (testy przeprowadzone na wyświetlaczu panoramicznym) tej karty 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