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
lubleft
) inną niżauto
. Ta wartość definiuje próg, przy którym element ma się "przykleić". Na przykładtop: 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 doposition: 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, elementsticky
również zniknie razem z nim (w przeciwieństwie dofixed
, 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 elementusticky
nie ma wystarczającej wysokości lub nie ma ustawionegooverflow
, efekt przyklejenia może nie zadziałać zgodnie z oczekiwaniami. - Konflikty z
overflow: hidden
: Jeśli którykolwiek z przodków elementusticky
ma ustawioneoverflow: hidden;
, może to uniemożliwić działaniesticky
.
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.