Na pewno nie raz gdy tworzyliście jakąś stronę internetową stawaliście przed starym jak świat problemem – stopka, która „wisi” w powietrzu kiedy na danej podstronie jest zbyt mało treści by zwyczajnie zepchnąć ją w dół. Stopka prezentująca się w taki sposób tak na prawdę nie prezentuje się w ogóle. Optymalnie powinna się ona znajdować na samym dole i być tam nawet jeśli ilość treści nie pozwala na to by jej położenie znalazło się w pożądanym miejscu.
Jak to osiągnąć? Na szczęście nie musimy tutaj wymyślać koła od nowa. W internecie jest kilka popularnych rozwiązań a gdyby ktoś miał czas i ochotę żeby przeszukać fora tematyczne to zapewne znalazł by ich jeszcze więcej. Na szczęście dzięki webroad.pl nie musicie nawet szukać. Przedstawimy Wam kilka popularnych rozwiązań wraz z opisem działania.
Ryan Fait – Sticky Footer
Jednym z nadal najbardziej popularnych sposobów na osiągnięcie efektu sticky footer („klejąca się stopka”) jest rozwiązanie zaproponowane przez Ryan’a Fait. Na stronie internetowej tego pana znajdziemy krótki tutorial i wyjaśnienie działania jego rozwiązania. Zacznijmy od kodu CSS:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | * { margin: 0; } html, body { height: 100%; } .wrapper { min-height: 100%; height: auto !important; height: 100%; margin: 0 auto -142px; /* dolny margines = minusowa wartość wysokości stopki wliczając w to ewentualny padding stopki */ } .footer, .push { height: 142px; /*klasa .push musi mieć tę samą wysokość co klasa .footer */ } |
Myślę, że szeroki komentarz nie jest raczej wymagany. Tak na prawdę mamy tutaj dość prosty (ale całkiem sprytnie skonstruowany) kod, który przy zaaplikowaniu odpowiedniej struktury html zapewni osiągnięcie pożądanego efektu. Kod html powinien wyglądać następująco:
1 2 3 4 5 6 7 8 9 | <body> <div class="wrapper"> <p>Treść strony www</p> <div class="push"></div> </div> <div class="footer"> <p>Stopka zawsze na dole strony</p> </div> </body> |
Zdefiniowane powyżej klasy działają tak żeby treść naszej strony zawsze ładnie ułożyła się wraz ze stopką w całość, która zajmie całą stronę i nie będziemy mieć problemów z „wiszącą” stopką. Jeśli stosujemy wielokolumnowy layout powinniśmy do klasy .push dodać następujący kod:
1 | clear: both; |
Aby to rozwiązanie działało musimy pamiętać o kilku warunkach:
- Żaden element strony nie może znajdować się poza klasami footer i wrapper, chyba że ma ustawione „position:absolute” i jego położenie ustalane jest na tej zasadzie
- Nie możemy stosować górnych i dolnych marginesów ponieważ modyfikują one kalkulacje związane z wysokością elementów
- Klasa push musi mieć tę samą wysokość co stopka
- Minusowy margines dla klasy wrapper musi mieć tę samą wartość co wysokość stopki
Wadą tego rozwiązania jest konieczność stosowania klasy .push, która nie może zawierać w sobie żadnej treści (sensem jej istnienia jest tylko to, że ma pewną określoną wysokość i dopełnia kalkulacje wysokości). Jest to tzw. niesemantyczny kod. Kolejna istotną wadą jest brak możliwości stosowania górnych i dolnych marginesów. Ich stosowanie ingerowało by w sposób działania kodu przedstawionego wyżej i nasz sticky footer by po prostu nie działał. Autor sugeruje stosowanie marginesów wewnętrznych (padding), ale one nie zawsze są w stanie zastąpić funkcjonalność zwykłych marginesów.
Plusem rozwiązania są prostota i kompatybilność międzyprzeglądarkowa.
Steve Hatcher – New CSS Sticky Footer
Tym razem mamy do czynienia z rozwiązaniem nie wymagającym stosowania sztucznych elementów jak klasa .push z poprzedniego przykładu. Zastosowana metoda opiera się na czystym CSS’ie aplikowanym do pewnej struktury kodu html.
1 2 3 4 5 6 7 8 9 10 | <div id="wrap"> /*w tej klasie zamieszczamy całość treści, pomijając oczywiście te, które trafią do stopki*/ <div id="main"> /*w tej klasie zamieścimy największą część treści i całego layoutu*/ </div> </div> <div id="footer"> /*a tutaj nasza stopka :)*/ </div> |
#wrap jest tutaj kontenerem owijającym praktycznie całą stronę oprócz stopki. #main to element, który kod css podda odpowiedniemu rozciągnięciu. Dlatego właśnie najprawdopodobniej tam będziecie umieszczać większość treści i najwięcej elementów layoutu strony. Arkusz stylów powinien zostać uzupełniony następująco:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | * {margin: 0; padding: 0;} /*zerujemy wszystkie marginesy - niestety tutaj również będziemy musieli zadowolić się górnym i dolnym paddingiem */ html, body {height: 100%;} #wrap {min-height: 100%;} #main {overflow:auto; padding-bottom: 180px;} /* ta sama wartość co wysokość stopki */ #footer {position: relative; margin-top: -180px; /* wysokość stopki z minusem :) */ height: 180px; clear:both;} /*Opera Fix*/ body:before {/* thanks to Maleika (Kohoutec)*/ content:""; height:100%; float:left; width:0; margin-top:-32767px;/* thank you Erik J - negate effect of float*/ } |
Oprócz powyższego między tagami <head> musimy dodać warunkowy styl dla IE
1 2 3 4 5 | <!--[if !IE 7]> <style type="text/css"> #wrap {display: table; height: 100%} </style> <![endif]--> |
Nasz arkusz stylów wygląda na ciut bardziej skomplikowany niż poprzednio, ale zasada działania jest podobna jak w rozwiązaniu Rayan’a Fait. W gruncie rzeczy chodzi o wysokości i wymuszenie na elementach blokowych rozciąganie się tak aby zająć całość możliwego miejsca nawet jeśli owe div’y nie mają w sobie wystarczająco dużo treści by to zrobić. Niestety ze względu na właściwości elementów blokowych wymuszenie na nich takiego zachowania nie jest łatwe.
Wady powyższego rozwiązania to przede wszystkim ban na górne i dolne marginesy, problemy mogące pojawiać się przy relatywnym określeniu wielkości czcionek, należy pamiętać o tym. że #main posiada dolny padding, który odpycha go od dołu dając miejsce stopce z kolei stopka zawiera w sobie negatywny margines górny, który poniekąd „wyciąga” ją na dół okna przeglądarki.
Zalety – rzeczywiście działa i działa bez zbędnego kodu html.
1 | #stopka {position: absolute;} |
W sumie nie ma chyba prostszego rozwiązania (jeśli jest inaczej to proszę o informacje w komentarzach). To co musimy w tym układzie zrobić to zwyczajnie pozycjonować stopkę absolutnie. Poniżej przykładowy html:
1 2 3 4 5 6 | <body> <div id="stronka"> </div> <div id="stopka"> </div> </body> |
Teraz css:
1 2 3 4 5 6 | #stopka { position:absolute; bottom:0; left:50%; margin-left:-200px; width:400px;} |
Pozycjonowanie absolutnie działa w odniesieniu do pierwszego rodzica, który nie ma domyślnej pozycji „static” a w przypadku braku takiego rodzica do bloku html. Dlatego nadając stopce właściwość i wartość „bottom:0;” ustawiliśmy ją na samym dole okna przeglądarki. Dodatkowo przesunęliśmy jej pozycję o 50% i nadaliśmy negatywny lewy margines o wartości równej połowie długości stopki. Dzięki temu możemy wyśrodkować element pozycjonowany absolutnie. Jeśli tło body było by takie samo jak tło elementu o nazwie „stronka” – problem mamy z głowy. Dzięki drobnej iluzji związanej z pokrywającym się tłem o raz absolutnym pozycjonowaniem stopki osiągamy swój cel ponieważ stopka jest zawsze na dole.
Oczywiście można zastosować też bardziej wyrafinowane metody. Przykładowo element „stopka” mógłby być opisany w css’ie następująco:
1 2 3 | #stronka { position:relative; } |
Dzięki temu prostemu zabiegowi moglibyśmy umieścić stopkę wewnątrz owego element i pozycjonować ją absolutnie względem niego, zaś samo nadanie id stronka „position:relative” nie odgrywa dla nas żadnej innej roli. Jednak nadal nie mielibyśmy stopki na dole strony… a gdyby potraktować element „stronka” podobnie jak w tym artykule? klik
Temat absolutnego pozycjonowania stopki zachęcam rozwinąć w komentarzach :)
Podsumowując warto stwierdzić, że dwa pierwsze rozwiązania są chyba zdecydowania najlepszymi obecnie znanymi i pewnie nie pozostaje to bez związku z ich popularnością. Absolutne pozycjonowanie jest pewną alternatywą i jeśli ktoś chciałby rozwinąć temat to ponownie zachęcam do komentowania.
Na koniec dodam jeszcze, że nie wspomniałem nic o zastosowaniu jquery. Otóż uważam, że skoro mamy rozwiązania oparte na css i html to myślę, że nie ma sensu sięgać do (jakże przydatnej) biblioteki jquery.
a może by tak zrobić stopkę bez stałej wysokości? Display table-cell height: 100% dla contentu i height: 1 dla stopki z tym samym displayem ?
Pewnie można – będę musiał kiedyś spróbować ;)
A nie można po prostu nadać blokowi content wartości dla min-height, która nas zadowala ?
Można i jest to zresztą całkiem proste i skuteczne rozwiązanie, ale…
jest to w sumie „obejście” problemu a nie jego rozwiązanie. Poza tym o
ile dobrze pamiętam to min-height nie działa w starszych operach.
Ja osobiście uważam , że najlepsze rozwiązanie to takie, które jest zgodne z brzytwą Ockhama.
PS. Dlaczego obejście a nie rozwiązanie ? I kto się bawi w optymalizację pod starą Operę :-) tylko masochiści….
Z brzytwą ockhama się zgadzam
natomiast z operą to jest tak, że chyba dopiero najnowsza wersja zaczęła
dobrze obsługiwać min-height więc mówiąc o „starszych” operach nie mam
na myśli przeglądarek po prostu przestarzałych – z drugiej strony nie
dam sobie ręki za to uciąć ;)