Kurs HTML

7.6. Właściwość position: sticky

Wprowadzenie: Pozycjonowanie "przyklejone"

Wartość position: sticky; to stosunkowo nowa i bardzo przydatna metoda pozycjonowania w CSS. Łączy ona w sobie cechy pozycjonowania relatywnego (relative) i stałego (fixed).

Element z position: sticky; zachowuje się jak element z position: relative; do momentu, aż podczas przewijania strony jego pozycja względem viewportu osiągnie określoną wartość progową (zdefiniowaną przez top, right, bottom lub left). W tym momencie element "przykleja się" do krawędzi viewportu i zaczyna zachowywać się jak element z position: fixed;, pozostając w tym miejscu podczas dalszego przewijania w obrębie swojego kontenera nadrzędnego.

position: sticky; jest idealne do tworzenia elementów, które mają być normalnie w przepływie, ale mają "podążać" za użytkownikiem podczas przewijania pewnego obszaru, np. nagłówki sekcji, paski boczne w długich artykułach, czy nagłówki tabel.

Jak działa position: sticky;?

  • Wymaga progu przesunięcia: Aby position: sticky; zadziałało, musisz określić co najmniej jedną właściwość przesunięcia (top, right, bottom lub left) inną niż auto. Ta wartość definiuje próg, przy którym element ma się "przykleić". Na przykład top: 0; oznacza, że element przyklei się do górnej krawędzi viewportu, gdy jego normalna pozycja osiągnie tę krawędź podczas przewijania.
  • Zachowanie początkowe (jak relative): Dopóki próg nie zostanie osiągnięty, element zachowuje się jakby miał position: relative; - pozostaje w normalnym przepływie dokumentu i zajmuje swoje miejsce.
  • Zachowanie po osiągnięciu progu (jak fixed): Gdy podczas przewijania element osiągnie zdefiniowany próg (np. top: 0;), zmienia swoje zachowanie na podobne do position: fixed; względem swojego **najbliższego przodka z mechanizmem przewijania (scrolling ancestor)** lub viewportu. Pozostaje "przyklejony" w tym miejscu.
  • Ograniczenie do kontenera: Co ważne, element "przyklejony" za pomocą sticky pozostaje w tym stanie tylko tak długo, jak długo jego **kontener nadrzędny** jest widoczny w viewporcie. Gdy kontener nadrzędny zostanie przewinięty poza ekran, element sticky również zniknie razem z nim (w przeciwieństwie do fixed, które zawsze pozostaje względem viewportu).
  • Tworzy nowy kontekst stosu: Podobnie jak fixed, tworzy nowy kontekst stosu.
<div class="container">
  <h2 class="sticky-header">Przyklejony nagłówek sekcji</h2>
  <p>Dużo treści w tej sekcji...</p>
  <!-- ...więcej treści... -->
</div>
<div class="another-section">
  <p>Kolejna sekcja strony...</p>
</div>
.container {
  height: 800px; /* Kontener musi być wystarczająco wysoki */
  overflow: auto; /* Lub przewijanie na body/html */
  border: 1px solid gray;
  margin-bottom: 20px;
}

.sticky-header {
  position: sticky;
  top: 0; /* Przyklei się do góry, gdy osiągnie tę pozycję */
  background-color: lightblue;
  padding: 10px;
  margin: 0; /* Usuń domyślne marginesy nagłówka */
  z-index: 10; /* Opcjonalnie, aby był na wierzchu */
}

.another-section {
    height: 500px;
    background: lightyellow;
}

/* Dodajmy trochę stylów dla treści */
.container p {
    padding: 0 10px;
    line-height: 1.6;
}
.container p:first-of-type {
    margin-top: 20px; /* Odstęp od nagłówka */
}

W powyższym przykładzie, .sticky-header będzie normalnie na początku .container. Gdy użytkownik zacznie przewijać .container (lub całą stronę, jeśli .container jest wystarczająco duży), nagłówek przesunie się w górę. Kiedy górna krawędź nagłówka dotknie górnej krawędzi viewportu (top: 0;), nagłówek "przyklei się" i pozostanie na górze, podczas gdy reszta treści .container będzie się pod nim przewijać. Gdy cały .container zostanie przewinięty poza ekran, nagłówek również zniknie.

Wsparcie przeglądarek i potencjalne problemy

  • Wsparcie: position: sticky; jest obecnie dobrze wspierane przez nowoczesne przeglądarki, ale starsze wersje (zwłaszcza IE11) go nie obsługują. Zawsze warto sprawdzić kompatybilność na stronach typu Can I use.
  • Wymagany przodek z przewijaniem: Element sticky przykleja się względem najbliższego przodka, który ma mechanizm przewijania (np. overflow: scroll;, overflow: auto;, overflow: hidden;) lub względem viewportu, jeśli żaden taki przodek nie istnieje. Jeśli rodzic elementu sticky nie ma wystarczającej wysokości lub nie ma ustawionego overflow, efekt przyklejenia może nie zadziałać zgodnie z oczekiwaniami.
  • Konflikty z overflow: hidden: Jeśli którykolwiek z przodków elementu sticky ma ustawione overflow: hidden;, może to uniemożliwić działanie sticky.

Zadania praktyczne

Zadanie 1 (z rozwiązaniem)

Stwórz długą listę elementów. Nadaj jej nagłówkowi (np. <h3>) position: sticky; i top: 0;, aby pozostawał widoczny podczas przewijania listy.

Rozwiązanie:

HTML:

<div class="list-container">
  <h3 class="list-header">Moja Długa Lista</h3>
  <ul>
    <li>Element 1</li>
    <li>Element 2</li>
    <!-- ... wiele elementów li ... -->
    <li>Element 50</li>
  </ul>
</div>

CSS:

.list-container {
  height: 300px; /* Ograniczona wysokość, aby wymusić przewijanie */
  overflow: auto; /* Włącz przewijanie dla kontenera */
  border: 1px solid #ccc;
}

.list-header {
  position: sticky;
  top: 0;
  background-color: white; /* Tło, aby zakryć przewijaną treść */
  padding: 8px 10px;
  margin: 0;
  border-bottom: 1px solid #ccc; /* Linia oddzielająca */
  z-index: 1;
}

ul {
  list-style: none;
  padding: 0 10px;
  margin: 0;
}

li {
  padding: 5px 0;
  border-bottom: 1px dotted #eee;
}

Efekt: Nagłówek "Moja Długa Lista" pozostanie przyklejony do górnej krawędzi kontenera .list-container podczas przewijania jego zawartości.

Zadanie 2 (do samodzielnego wykonania)

Stwórz layout z bocznym paskiem (sidebar) i główną treścią. Nadaj paskowi bocznemu position: sticky; i top: 20px; (aby zachować odstęp od góry). Upewnij się, że główna treść jest wystarczająco długa, aby strona była przewijalna. Zaobserwuj, jak pasek boczny "podąża" za przewijaniem, ale tylko w obrębie swojego kontenera nadrzędnego.

Zadanie 3 (do samodzielnego wykonania)

Spróbuj użyć position: sticky; z właściwością bottom: 0;, aby stworzyć element, który przykleja się do dolnej krawędzi swojego kontenera podczas przewijania w górę.

FAQ - Najczęściej zadawane pytania

Czy position: sticky działa bez top/right/bottom/left?

Nie, aby position: sticky; miało jakikolwiek efekt "przyklejenia", musisz zdefiniować co najmniej jedną z właściwości przesunięcia (top, right, bottom lub left) z wartością inną niż auto. Bez tego element będzie się zachowywał jakby miał position: relative;.

Jaka jest różnica między sticky a fixed?

fixed zawsze pozycjonuje element względem viewportu i pozostaje w miejscu niezależnie od przewijania całej strony. sticky początkowo zachowuje się jak relative, a "przykleja się" do krawędzi viewportu (lub przodka z przewijaniem) tylko po osiągnięciu progu i tylko w granicach swojego kontenera nadrzędnego.

Dlaczego mój element sticky się nie przykleja?

Najczęstsze przyczyny to: brak ustawionej wartości progowej (top/right/bottom/left), brak wystarczającej przestrzeni do przewijania w kontenerze nadrzędnym lub w viewporcie, lub obecność przodka z overflow: hidden; (lub clip, auto, scroll, który "obcina" element zanim zdąży się przykleić).

Czy mogę mieć wiele elementów sticky na stronie?

Tak, można mieć wiele elementów sticky. Mogą one nawet "wypychać" poprzednie elementy sticky, jeśli mają ten sam próg (np. top: 0;), tworząc efekt stosu przyklejonych nagłówków.