Dobrze kontrolowane przewijanie za pomocą funkcji CSS Scroll Snap

Twórz dobrze kontrolowane przewijanie, deklarując pozycje przyciągania przewijania.

Robert Flack
Robert Flack
Majid Valipour
Majid Valipour

Funkcja CSS Scroll Snap umożliwia deweloperom tworzenie dobrze kontrolowanych przewijanych treści przez deklarowanie pozycji przyciągania przewijania. Przykładami tego są artykuły podzielone na strony i karuzele obrazów. CSS Scroll Snap udostępnia łatwy w użyciu i spójny interfejs API do tworzenia tych popularnych wzorców UX.

Tło

Argumenty za przyciąganiem przewijania

Przewijanie to popularny i naturalny sposób interakcji z treściami w internecie. Jest to natywny sposób platformy na udostępnianie większej ilości informacji niż ta, która jest widoczna na ekranie jednocześnie. Jest to szczególnie ważne na platformach mobilnych o ograniczonej przestrzeni ekranu. Nie dziwi więc, że autorzy stron internetowych coraz częściej wolą organizować treści w postaci płaskich list z możliwością przewijania, a nie głębokich hierarchii.

Główną wadą przewijania jest brak precyzji. Rzadko zdarza się, aby przewijanie kończyło się na akapicie lub zdaniu. Jest to jeszcze bardziej widoczne w przypadku treści podzielonych na strony lub elementów z wyraźnymi granicami, gdy przewijanie kończy się w połowie strony lub obrazu, pozostawiając je częściowo widoczne. W tych przypadkach użycia przydaje się dobrze kontrolowane przewijanie.

Aby rozwiązać ten problem, programiści stron internetowych od dawna korzystają z rozwiązań opartych na JavaScript, które umożliwiają kontrolowanie przewijania. Rozwiązania oparte na JavaScript nie zapewniają jednak pełnej wierności ze względu na brak podstawowych elementów dostosowywania przewijania lub dostępu do przewijania złożonego. CSS Scroll Snap zapewnia szybkie, dokładne i łatwe w użyciu rozwiązanie, które działa spójnie w różnych przeglądarkach.

CSS Scroll Snap umożliwia autorom stron internetowych oznaczanie każdego kontenera przewijania granicami, w których ma się kończyć przewijanie. Przeglądarki wybierają najbardziej odpowiednią pozycję końcową w zależności od szczegółów operacji przewijania, układu i widoczności kontenera przewijania oraz szczegółów pozycji przyciągania, a następnie płynnie animują do niej przewijanie. Wróćmy do wcześniejszego przykładu. Gdy użytkownik przestanie przewijać karuzelę, widoczny obraz zatrzaśnie się na swoim miejscu. Nie wymaga dostosowywania przewijania za pomocą JavaScriptu.

Przykład użycia przyciągania przewijania CSS w karuzeli obrazów.
Przykład użycia funkcji przyciągania przewijania CSS w karuzeli obrazów. W tym przypadku przyciąganie przewijania zapewnia, że po zakończeniu przewijania poziomy środek obrazu jest wyrównany z poziomym środkiem kontenera przewijania.

CSS Scroll Snap

Przyciąganie przewijania to dostosowywanie przesunięcia przewijania kontenera przewijania do preferowanej pozycji przyciągania po zakończeniu operacji przewijania.

Kontener przewijania może włączyć przyciąganie przewijania za pomocą właściwości scroll-snap-type. Informuje to przeglądarkę, że powinna rozważyć przyciąganie tego kontenera przewijania do pozycji przyciągania wygenerowanych przez jego elementy podrzędne. scroll-snap-type określa oś, wzdłuż której następuje przewijanie: x, y lub both, oraz dokładność przyciągania: mandatory, proximity. Więcej informacji na ten temat znajdziesz poniżej.

Pozycję przyciągania można uzyskać, deklarując żądane wyrównanie elementu. Ta pozycja to przesunięcie przewijania, przy którym najbliższy kontener przewijania elementu nadrzędnego i element są wyrównane zgodnie z określeniem dla danej osi. W przypadku każdej osi możliwe są te rodzaje wyrównania: start, end, center.

Wyrównanie start oznacza, że początkowa krawędź punktu przyciągania kontenera przewijania powinna być zrównana z początkową krawędzią obszaru przyciągania elementu. Podobnie wyrównania endcenter oznaczają, że końcowa krawędź lub środek punktu przyciągania kontenera przewijania powinny być wyrównane z końcową krawędzią lub środkiem obszaru przyciągania elementu.

Przykład różnych wyrównań na osi przewijania poziomego.

Poniższe przykłady pokazują, jak korzystać z tych pojęć.

Typowym zastosowaniem przyciągania przewijania jest karuzela obrazów. Na przykład aby utworzyć poziomą karuzelę obrazów, która przy przewijaniu przyciąga każdy obraz, możemy określić, że kontener przewijania ma obowiązkowe scroll-snap-type na osi poziomej. Ustawiamy każdy obraz na scroll-snap-align: center, aby przyciąganie wyśrodkowało obraz w karuzeli.

#gallery {
  scroll-snap-type: x mandatory;
  overflow-x: scroll;
  display: flex;
}

#gallery img {
   scroll-snap-align: center;
}
<div id="gallery">
  <img src="cat.jpg">
  <img src="dog.jpg">
  <img src="another_cute_animal.jpg">
</div>

Pozycje przyciągania są powiązane z elementem, więc algorytm przyciągania może inteligentnie określać, kiedy i jak przyciągać element, biorąc pod uwagę jego rozmiar i rozmiar kontenera przewijania. Rozważmy na przykład sytuację, w której jeden obraz jest większy niż karuzela. Prosty algorytm przyciągania może uniemożliwić użytkownikowi przesuwanie obrazu, aby zobaczyć go w całości. Jednak specyfikacja wymaga, aby implementacje wykrywały ten przypadek i umożliwiały użytkownikowi swobodne przewijanie obrazu, przyciągając go tylko do krawędzi.

Przykład: strona produktu z informacjami o dostawie

Innym typowym przypadkiem, w którym przydatne jest przyciąganie przewijania, są strony z wieloma logicznymi sekcjami do przewijania w pionie, np. typowa strona produktu. scroll-snap-type: y proximity; lepiej pasuje do takich przypadków. Nie przeszkadza, gdy użytkownik przewija do środka określonej sekcji, ale też przyciąga uwagę do nowej sekcji, gdy przewija wystarczająco blisko.

Można to osiągnąć w następujący sposób:

article {
  scroll-snap-type: y proximity;
  /* Reserve space for header plus some extra space for sneak peeking. */
  scroll-padding-top: 15vh;
  overflow-y: scroll;
}
section {
  /* Snap align start. */
  scroll-snap-align: start;
}
header {
  position: fixed;
  height: 10vh;
}
<article>
  <header> Header </header>
  <section> Section One </section>
  <section> Section Two </section>
  <section> Section Three </section>
</article>

Dopełnienie i margines przewijania

Strona produktu ma nagłówek u góry o stałej pozycji. W projekcie przewidziano też, że część górnej sekcji ma pozostać widoczna po zatrzaśnięciu kontenera przewijania, aby użytkownicy mogli zobaczyć, co znajduje się powyżej.

Właściwość scroll-padding to nowa właściwość CSS, której można używać do dostosowywania efektywnego widocznego obszaru kontenera przewijania lub snapportu, który jest używany podczas obliczania wyrównania przyciągania przewijania. Właściwość określa wcięcie względem pola dopełnienia kontenera przewijania. W naszym przykładzie do góry dodano 15vh dodatkowe wcięcie,15vh które nakazuje przeglądarce traktować niższą pozycję, poniżej górnej krawędzi kontenera przewijania, jako pionową krawędź początkową dla przyciągania przewijania. Podczas przyciągania początkowa krawędź elementu docelowego przyciągania zostanie wyrównana do tej nowej pozycji, pozostawiając miejsce powyżej.

Właściwość scroll-margin określa wartość odsunięcia używaną do dostosowania efektywnego pola elementu docelowego przyciągania, podobnie jak funkcja scroll-padding w przypadku kontenera przewijania z przyciąganiem.

Zauważ, że te 2 właściwości nie zawierają słowa „snap”. Jest to celowe, ponieważ w przypadku wszystkich odpowiednich operacji przewijania modyfikują one pole, a nie tylko przyciągają przewijanie. Na przykład Chrome uwzględnia je podczas obliczania rozmiaru strony na potrzeby operacji przewijania stron, takich jak PageDown i PageUp, a także podczas obliczania ilości przewijania na potrzeby operacji Element.scrollIntoView().

Interakcja z innymi interfejsami API przewijania

DOM Scrolling API

Przyciąganie przewijania następuje po wszystkich operacjach przewijania, w tym tych zainicjowanych przez skrypt. Gdy używasz interfejsów API takich jak Element.scrollTo, przeglądarka oblicza zamierzoną pozycję przewijania operacji, a następnie stosuje odpowiednią logikę przyciągania, aby znaleźć ostateczną przyciągniętą lokalizację. Dlatego skrypt użytkownika nie musi wykonywać żadnych ręcznych obliczeń na potrzeby przyciągania.

Płynne przewijanie

Płynne przewijanie kontroluje zachowanie operacji przewijania programowego, a przyciąganie przewijania określa jego miejsce docelowe. Ponieważ kontrolują one ortogonalne aspekty przewijania, można ich używać razem i się uzupełniają.

Działanie overscroll

Interfejs Overscroll behavior API określa, jak przewijanie jest połączone w wielu elementach, i nie ma na niego wpływu przyciąganie przewijania.

Ostrzeżenia i sprawdzone metody

Unikaj używania obowiązkowego przyciągania, gdy elementy docelowe są od siebie znacznie oddalone. Może to spowodować, że treści między pozycjami przyciągania staną się niedostępne.

W wielu przypadkach przyciąganie przewijania można dodać jako ulepszenie bez konieczności wykrywania funkcji. W razie potrzeby użyj @supports lub CSS.supports, aby wykryć obsługę przyciągania przewijania CSS. Unikaj używania scroll-snap-type, który występuje też w wycofanej specyfikacji.

Wykrywanie funkcji w CSS

@supports (scroll-snap-align: start) {
  article {
    scroll-snap-type: y proximity;
    scroll-padding-top: 15vh;
    overflow-y: scroll;
  }
}

Wykrywanie funkcji w JavaScript

if (CSS.supports('scroll-snap-align: start')) {
  // use css scroll snap
} else {
  // use fallback
}

Nie zakładaj, że interfejsy API do programowego przewijania, takie jak Element.scrollTo, zawsze kończą się na żądanym przesunięciu przewijania. Przyciąganie przewijania może dostosować przesunięcie przewijania po zakończeniu przewijania programowego. Pamiętaj, że nawet przed wprowadzeniem przyciągania przewijania nie było to dobre założenie, ponieważ przewijanie mogło zostać przerwane z innych powodów, ale w przypadku przyciągania przewijania jest to szczególnie ważne.

Przyszłe prace

Przewijanie było tematem niedawnej ankiety przeprowadzonej przez zespół Chrome. Wyniki ankiety wskazały kilka obszarów, które wymagają dodatkowych działań, aby zmniejszyć różnicę między bibliotekami wtyczek a kodem CSS. Najbliższe prace będą dotyczyć scroll-snap, w tym:

  1. Dostępność i zgodność interfejsu API w różnych przeglądarkach.
  2. Pracuj nad nowymi interfejsami CSS API, takimi jak scroll-start.
  3. Pracuj nad nowymi zdarzeniami JS, takimi jak snapChanged().