Artykuł ten jest tłumaczeniem artykułu CSS Positioning 101 autorstwa Noah Stokes, zamieszczonego na A List Apart. Noah Stokes wyraził zgodę na przetłumaczenie i opublikowanie jego artykułu na moim blogu, za co serdecznie mu dziękuję. Zaznaczam, że nie jestem autorem poniższego tekstu, a jedynie autorem tłumaczenia.

CSS Positioning 101

Jeśli jesteś front-end developerem albo po prostu lubisz kodować, layouty oparte na CSS z pewnością stanowią podstawę twojej pracy. Być może zatem będzie to dla Ciebie tylko przypomnienie, a może coś zupełnie nowego – niezależnie od tego przyjrzyjmy się razem właściwość CSS position i sprawdźmy, jakie zastosowanie może ona mieć przy tworzeniu zgodnych ze standardami, beztabelkowych layoutów.

W pozycji jest moc

Pozycjonowanie przy użyciu CSS często źle rozumiane. Czasem, próbując naprawić na szybko wszystkie bugi na stronie, eksperymentujemy na chybił-trafił z różnymi ustawieniami właściwości position tak długo, aż uzyskamy pożądany efekt. Ta przypadkowość nieraz przynosi pożądany efekt, jednak warto wiedzieć i rozumieć, dlaczego właściwie tak się dzieje. Mam nadzieję, że ten artykuł pozwoli ci poznać i – co ważniejsze – zrozumieć działanie właściwości position.

Specyfikacja CSS wyróżnia pięć wartości dla właściwości position: static (statyczna), relative (względna), absolute (bezwzględna), fixed (stała) oraz inherit (dziedziczona). Każda z nich ma inne zastosowanie, a ich zrozumienie ma kluczowe znaczenie przy tworzeniu layoutów opartych o CSS.

Znaj swoje miejsce

Na początek poznajmy lepiej obszar, po którym będziemy się poruszać. Zupełnie jak w realny świat, świat znaczników posiada swoje granice. W języku CSS wyznacza je domyślnie tzw. układ normalny (normal flow). W specyfikacji CSS 2.1 czytamy:

Pola znajdujące się w układzie normalnym należą do kontekstu formatowania, który może być blokowy lub śródliniowy (ale nie taki i taki jednocześnie). Pola blokowe uczestniczą w kontekście formatowania blokowego. Pola śródliniowe uczestniczą w kontekście formatowania śródliniowego.

Wyobraź sobie przez chwilę, że „pole”, o którym mowa w specyfikacji, to zwykły drewniany klocek. Teraz wyobraź sobie, że elementy w układzie normalnym zachowują się tak, jak drewniane klocki, na które działa siła grawitacji. W normalnym układzie elementy strony będą zachowywać się tak, jak klocki położone jeden na drugim – będą pojawiać się w takiej kolejności, w jakiej występują w kodzie. Być może w dzieciństwie układałeś wieże z z takich drewnianych klocków – zachowanie elementów w normalnym układzie strony nie różni się niczym od zachowania klocków, z których ją budowałeś. W wieży układałeś klocki jeden na drugim – podobnie działa układanie elementów strony w kodzie, różnica polega na tym, że bawiąc się klockami nie dało się nagiąć grawitacji. Dlatego właśnie CSS jest o wiele fajniejszy niż klocki.

Statycznie czy względnie – co za różnica

Elementy pozycjonowanie statycznie lub względnie zachowują swoje pierwotne właściwości i wyświetlają się w jak te wspomniane wcześniej klocki – jeden na drugim, zgodnie z prawem grawitacji. Warto zanotować, że domyślną wartością dla właściwości position jest static. Rzućmy okiem na układ trzech elementów pozycjonowanych statycznie:

#box_1 {
position: static;
width: 200px;
height: 200px;
background: #ee3e64;
}

#box_2 {
position: static;
width: 200px;
height: 200px;
background: #44accf;
}

#box_3 {
position: static;
width: 200px;
height: 200px;
background: #b7d84b;
}

W przykładzie A widać trzy elementy ułożone na kształt wieży z klocków. Nieźle, nie? To jest tzw. układ blokowy 101. Powinszować!

Pozycjonowanie statyczne ma zastosowanie przede wszystkim w jednokolumnowych układach stron, gdzie każdy elementy wyświetlają się jeden an drugim. Jeśli jednak chciałabyś poprzesuwać te elementy za pomocą top, right, bottom i left, to masz niestety pecha. Te właściwości nie mają zastosowania dla elementów pozycjonowanych statycznie. W zasadzie elementy pozycjonowane w ten sposób nie mogą nawet stanowić układu odniesienia dla elementów w nich zawartych. Zaraz, układu odniesienia? Wyglądasz, jakbyś nie miał pojęcia, o co chodzi – śpieszę więc z odpowiedzią. Elementy pozycjonowane względnie zachowują się zupełnie jak te pozycjonowane statycznie – współgrają z innymi elementami i nie powodują zamieszania. Trudno w to uwierzyć, co nie? Spójrz zatem na nasz kolejny przykład, w którym zastosujemy pozycjonowanie względne:

#box_1 {
position: relative;
width: 200px;
height: 200px;
background: #ee3e64;
}

#box_2 {
position: relative;
width: 200px;
height: 200px;
background: #44accf;
}

#box_3 {
position: relative;
width: 200px;
height: 200px;
background: #b7d84b;
}

Przykład B pokazuje, że elementy pozycjonowanie względnie zachowują się identycznie jak elementy pozycjonowane statycznie. Różnica polega wyłącznie na tym, że elementy pozycjonowane względnie to taki Clark Kent – posiadają o wiele większe moce niż elementy statyczne.

Na początek przyjrzyjmy się, w jaki sposób właściwości top, right, bottom i left wpływają na elementy pozycjonowane względnie. Wykorzystamy do tego nasz poprzedni przykład, tym razem jednak przesuwając element #box_2:

#box_2 {
position: relative;
left: 200px;
width: 200px;
height: 200px;
background: #44accf;
}

Przykład C pokazuje pozycjonowanie względne w akcji. Trzy bloki przylegają wciąż przylegają do siebie, ale tym razem przesunęliśmy niebieski blok #box_2 o 200px od lewej krawędzi dokumentu. Właśnie nagięliśmy nieco prawo grawitacji. Niebieski blok wciąż wyświetla się w ciągu elementów – bloki układają się jeden pod drugim – zauważcie jednak, że zielony blok #box_3 wciąż wyświetla się pod niebieskim, mimo że ten nie znajduje się bezpośrednio nad nim. Używając pozycjonowania względnego nie wpływamy na zachowanie pozostałych elementów. Zielony blok w dalszym ciągu zachowuje się zupełnie tak, jakby blok niebieski nie był w ogóle przesunięty. Spróbujcie to zrobić ze swoimi klockami!

Tworzenie układu odniesienia dla elementów-dzieci to kolejna supermoc pozycjonowania względnego. Układ odniesienia to inaczej układ współrzędnych, w granicach którego możemy przesuwać elementy. Wracając do przykładu C – niebieski blok #box_2 nie został zagnieżdżony w żadnym innym elemencie, dlatego układem odniesienia, względem którego przesunie się o 200px w lewo, będzie dla niego dokument. Jeśli umieścimy element #box_2 wewnątrz elementu #box_1 to element #box_1 stanie się układem odniesienia dla elementu #box_2. Otrzymamy zatem zupełnie inny rezultat, ponieważ element #box_2 przesunie się względem elementu #box_1, a nie względem dokumentu.W następnym przykładzie nie będizemy nic zmieniać w CSS, zmienimy jedynie HTML wpisując
#box_2 w element #box_1:

<div id="box_1">
   <div id="box_2"></div>
</div>

W przykładzie D widać naniesione zmiany. Ze względu na nowy układ odniesienia, niebieski blok przesunie się o 200px w lewo w stosunku do czerwonego bloku, a nie w stosunku do dokumentu. Takie użycie pozycjonowania względnego częściej stosowane jest w stosunku do elementów pozycjonowanych bezwzględnie, które z pewnością jako dziecko chciałbyś móc wykorzystać budując wieżę z klocków.

Bezwzględnie – dowolność w każdej chwili

Jeśli pozycjonowanie względne ma moce niczym Superman, to pozycjonowanie bezwzględne jest jak Incepcja – dzięki niemu możesz stworzyć swój własny świat. W przeciwieństwie do elementów pozycjonowanych statycznie i względnie, elementy pozycjonowane bezwzględnie wypadają z normalnego układu. Oznacza to, że możesz je umieścić w dowolnym miejscu na stronie bez wpływu na pozostałe elementy. Staraj się myśleć o tych elementach jak o klockach na rzepę – pojawią się dokładnie w miejscu, w którym je przyczepisz. Podobnie jak elementy pozycjonowane względnie, elementy pozycjonowane bezwzględnie można przesuwać. Jeśli zatem ustawisz takiemu elementowi właściwości top: 100px; i left: 200px;, to przesuniesz go dokładnie o 100px od górnej krawędzi dokumentu i o 200px od lewej krawędzi dokumentu. Spójrzmy na poniższy przykład z czterema elementami:

#box_1 {
position: absolute;
top: 0;
left: 0;
width: 200px;
height: 200px;
background: #ee3e64;
}
#box_2 {
position: absolute;
top: 0;
right: 0;
width: 200px;
height: 200px;
background: #44accf;
}
#box_3 {
position: absolute;
bottom: 0;
left: 0;
width: 200px;
height: 200px;
background: #b7d84b;
}
#box_4 {
position: absolute;
bottom: 0;
right: 0;
width: 200px;
height: 200px;
background: #ebde52;
}

Na przykładzie E widać cztery bloki, każdy umieszczony w innym rogu dokumentu. Pozycjonując każdy z bloków bezwzględnie, przypięliśmy je do poszczególnych rogów okna przeglądarki. Jeśli teraz zmienisz rozmiar tego okna zauważysz, że bloki wciąż pozostają przypięte do narożników. Jeśli zmniejszysz je tak, żeby bloki nachodziły na siebie zauważysz, że miedzy nimi nie zachodzą żadne zależności – to dlatego, że nie należą już do normalnego układu.

Zupełnie jak elementy pozycjonowanie względnie, elementy pozycjonowane bezwzględnie tworzą nowy układ odniesienia dla elementów-dzieci. W przykładzie F, który jest rozbudowanym przykładem E, wewnątrz każdego z bloków umieszczono pomarańczowy element. Zauważ, że ich przesunięcie następuje za każdym razem w stosunku do elementu-rodzica.

Elementom pozycjonowanym bezwzględnie można nadać bardzo fajną funkcjonalność wykorzystując w tym celu przesuwanie. Używając tylko dwóch albo wszystkich czterech właściwości przesuwnych można rozciągnąć dowolny element na całą szerokość dokumentu lub elementu-rodzica, bez konieczności określania wysokości czy szerokości elementu. Zobaczmy, jak działa to w praktyce:

#box_a {
position: absolute;
top: 10px;
right: 10px;
bottom: 10px;
left: 10px;
background: red;
}
#box_b {
position: absolute;
top: 20px;
right: 20px;
bottom: 20px;
left: 20px;
background: white;
}

W przykładzie G, za pomocą pozycjonowania absolutnego i przesunięć, stworzyliśmy ramkę o szerokości 10 pikseli, która rozciąga się wraz z dokumentem. W kolejnym przykładzie stworzymy dwukolumnowy układ, którego wysokość będzie zmieniać się wraz z dokumentem. Oto kod CSS:

#box_1 {
position: absolute;
top: 0;
right: 20%;
bottom: 0;
left: 0;
background: #ee3e64;
}

#box_2 {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 80%;
background: #b7d84b;
}

Przykład H to pełnoekranowa, dwukolumnowy układ. Mimo, że nie jest to najlepszy sposób na tworzenie tego typu struktur, to jednak pokazuje potęgę pozycjonowania bezwzględnego. Przy odrobinie kreatywności można mu znaleźć co najmniej kilka ciekawych zastosowań. Ciekawy efekt można na przykład osiągnąć używając tylko jednej własciwości przesuwnej:

#box_1 {
width: 200px;
height: 200px;
background: #ee3e64;
}
#box_2 {
position: absolute;
left: 100px;
width: 200px;
height: 200px;
background: #44accf;
}

Spójrzmy na niebieski blok #box_2 w przykładzie H2. Zauważ, że użyłem tylko jednej własciwości przesuwnej – left: 100px;. W ten sposób blok #box_2 przesunął się o 100px w prawo, ale jego górna krawędź pozostaje nieruszona. Jeśli teraz określimy właściwość top dla tego bloku, przekonamy się, że przesunie się on względem górnej krawędzi dokumentu. Widać to na przykładzie H3:

#box_2 {
position: absolute;
top: 0;
left: 100px;
width: 200px;
height: 200px;
background: #44accf;
}

Fixed – stale w miejscu

Elementy pozycjonowane stale (position:fixed;) zachowują się niemal identycznie jak elementy pozycjonowane bezwzględnie, z ta różnicą, że blok zawierający jest ustawiany przez obszar widoku lub okno urządzenia, poza jakimkolwiek elementem nadrzędnym. Oprócz tego element pozycjonowany stale nie przewija się wraz z dokumentem tylko jest… stale widoczny. Spójrzmy na przykład:

#box_2 {
position: fixed;
bottom: 0;
left: 0;
right: 0;
}

Na przykładzie przykładzie I widać stopkę tekstem o prawach autorskich wewnątrz pozycjonowaną stale. Skrolując stronę zauważysz, że stopka pozostaje nieruszona. Zauważ ponadto, że własciwości left i right mają wartość zerową. Ponieważ pozycjonowanie stałe wpływa na element podobnie jak bezwzględne, możemy rozciągnąć element na całą szerokość dokumentu, jednocześnie przypinając go do dolnej krawędzi dzięki bottom:0;. Stosując pozycjonowanie stałe należy zachować ostrożność, ponieważ właściwość ta nie ma wsparcia w starszych przeglądarkach. Przykładowo starsze wersje Internet Explorera wyświetlają elementy pozycjonowane stale tak, jakby były pozycjonowane statycznie, a jak powszechnie wiadomo, elementy pozycjonowanie statyczne zachowują się zupełnie inaczej. Jeśli jednak planujesz zastosować na swojej stronie pozycjonowanie stałe, oto kilka rozwiązań, które pomogą ci uporać się z brakiem wsparcia dla tej właściwości w starszych przeglądarkach.

Dziedziczenie – coś za nic

Jak wspomniałem na początku artykułu, istnieje pięć wartości właściwości position. Piątą wartością jest inherit (dziedziczona). Działa zupełnie tak jak się nazywa – elementy z tak ustawioną właściwością positon, dziedziczą jej wartość po elemencie-rodzicu. Właściwość position nie jest dziedziczona – domyślna jej wartością jest zawsze static. Ostatecznie można ustawić taką samą wartość jak wartość elementu-rodzica, żeby osiągnąć identyczny efekt.

Dziedziczenie w akcji

Mniej gadania, więcej działania. Zerknijmy na przykład strony wykorzystującej tę wartość.

Przykład J to typowa strona internetowa z nagłówkiem, nawigacją, treścią i stopką. Przyjrzyjmy tym elementom i omówmy sposób, w jaki są pozycjonowane, aby zrozumieć dlaczego wykorzystano tę a nie inną wartość.

Zacznijmy od elementu #container. Jest to zwykły kontener, którego użyłem do wyśrodkowania strony. element #nav jest pierwszym elementem wewnątrz elementu #container. Ponieważ nie ma on określonej właściwości position, domyślnie pozycjonowany jest statycznie i dobrze – nie będziemy go przesuwać i nie chcemy, żeby stał się nowym układem odniesienia. Nowym układem odniesienia będzie za to kolejny elementem – blok #content – dlatego ten element będziemy pozycjonować względnie.

Ponieważ nie będziemy w ogóle przesuwać bloku #content, pozycjonowanie względne nie będzie miało na niego żadnego wpływu, ale stworzy nowy układ odniesienia dla elementu #callout. Element #callout jest pozycjonowany bezwzględnie, a ponieważ znajduje się wewnątrz pozycjonowanego względnie elementu #content, przesuwanie elementu #callout będzie odbywać się względem elementu #content. Elementowi #callout nadano ujemną wartość przesunięcia w prawo po to, żeby wysunąć go na zewnątrz bloku zawierającego. Dodatkowo, wykorzystując ciekawą właściwość pozycjonowania bezwzględnego, rozciągnąłem element #callout na pełną wysokość bloku zawierającego minus 200px, ustawiając właściwości top:100px; i bottom:100px;.

Ponieważ element #callout jest pozycjonowany bezwzględnie nie ma wpływu na pozostałe elementy. Koniecznie jednak musimy ustawić właściwość padding elementu #content, w przeciwnym jego zawartość zostanie przykryta przez element #callout. Na koniec nadaliśmy stopce wartość fixed i przypięliśmy ją do dolnej krawędzi dokumentu, gdzie pozostanie również przy skrolowaniu strony. Oprócz tego, ustawiliśmy elementowi #content dolne dopełnienie (padding) na 60px z tego samego powodu, dla którego ustawiliśmy mu prawe dopełnienie – żeby stopka nie przykryła zawartej w nim treści.

W ten sposób stworzyliśmy prosty i przejrzysty układ strony z nawigacją, przykładową zawartością, panelem bocznym i stopką korzystając z pozycjonowania statycznego, względnego i bezwzględnego. Należy pamiętać również o starszych przeglądarkach i zastosować jakieś rozwiązanie, które zapewni im wsparcie dla wartości fixed.

Podsumowanie

Znając potęgę pozycjonowania, ukończysz nawet najbardziej wymagający projekt. Szczęśliwie, 80% zarówno starszych jak i nowszych przeglądarek posiada wsparcie dla wszystkich wartości właściwości position. Jedyną wartością, przy której należy zachować szczególną ostrożność jest fixed. Dogłębne zrozumienie tej własciwości pozwoli ci tworzyć skomplikowane i nietypowe układy w oparciu o język CSS. Jedynym ograniczeniem jest Twoja wyobraźnia. Mam nadzieję, że od tej pory zmiany pozycji na chybił trafił w celu naprawienia bugów na stronie to przeszłość.

———————————————————————–
Przy tłumaczeniu wykorzystano tłumaczenie specyfikacji CSS 2.1 autorstwa pana Łukasza Piwko.

Podobne wpisy: