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,bottomlubleft) 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ą
stickypozostaje 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, elementstickyró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
stickyprzykleja 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 elementustickynie 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 elementustickyma 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.