101 porad na temat używania elementów pływających w CSS

05 czerwca 2012
1 gwiadka2 gwiazdki3 gwiazdki4 gwiazdki5 gwiazdek

Własność float CSS jest cennym i niezbędnym narzędziem w zestawie każdego użytkownika języków HTML i CSS. Jeśli jednak nie rozumiesz dokładnie sposobu jej działania, to może Cię czekać wiele rozczarowań i utrata nerwów. Ponadto kiedyś własność tę kojarzono z wyjątkowo paskudnymi błędami niektórych wyszukiwarek. Nic więc dziwnego, że niektórzy mają przed nią opory. W tym artykule spróbuję Cię uspokoić i pomóc Ci pozbyć się problemów związanych z własnością float. Wyjaśnię jak dokładnie własność ta działa na elementy i jak bardzo jest przydatna, gdy się ją dobrze opanuje.

Pływające elementy spotykamy na co dzień, np. gdy weźmiemy do ręki gazetę codzienną, to znajdziemy w niej obrazki otoczone tekstem. W świecie HTML-a i CSS-a, aby tekst zawijał się wokół obrazu, tak jak w gazecie, obraz trzeba zamienić w element pływający. Obrazy to tylko jedno z wielu zastosowań własności float: jej innym popularnym zastosowaniem jest tworzenie układów kolumnowych. W zasadzie każdy element HTML można zamienić w pływaka. Gdy opanujesz podstawowe wiadomości z zakresu używania własności float i position, to bez problemu utworzysz każdy układ, jaki sobie wymarzysz.

Definicja float CSS

Zaczniemy od zdefiniowania elementu pływającego. Oto, co na ten temat piszą w W3C:

Pole pływające to pole dosunięte do lewej lub prawej krawędzi linii. Najciekawszą cechą pól pływających jest to, że obok nich może znajdować się jakaś treść (chyba że zostanie to zabronione za pomocą własności clear). Pola spływające do lewej krawędzi pozwalają na występowanie treści po prawej stronie, a pola spływające do prawej — po lewej stronie.

Własność float przyjmuje jedną z czterech wartości: left, right, inherit oraz none. Zastosowanie każdej z nich jest raczej oczywiste. Na przykład, deklaracja float: left powoduje, że element, do którego została zastosowana zostanie ustawiony przy lewej krawędzi swojego rodzica. To samo dotyczy ustawienia float: right;. W tym przypadku element zostałby ustawiony przy prawej krawędzi swojego rodzica. Wartość inherit powoduje przejęcie ustawienia własności float po elemencie-rodzicu. Natomiast wartość none jest domyślnym ustawieniem i oznacza, że element nie jest pływający.

Oto prosty przykład podobny do opisanego powyżej, przykład A, i odpowiadający mu kod:


img { 
  float: right;
  margin: 10px;
}

Jak zachowują się elementy pływające

Nic trudnego a na dodatek ile radości, prawda? Bułka z masłem chciałoby się powiedzieć. Zanim przejdziemy do zagadnień, w których elementy pływające zachowują się jak mięsożerne jednorożce, najpierw powtórzymy sobie podstawowe wiadomości. W dokumentach HTML mają zastosowanie pewne prawa, z których jednym są zasady tzw. układu normalnego. W układzie normalnym elementy blokowe (div, p, h1 itd.) układają się jeden pod drugim na pionowej osi widocznego obszaru okna przeglądarki. Elementy pływające są najpierw rozmieszczane zgodnie z układem normalnym, a następnie wyjmowane z tego układu i przenoszone w kierunku lewej lub prawej (w zależności od zastosowanych do nich ustawień) krawędzi ich elementu-rodzica. Innymi słowy zmieniają swoje rozmieszczenie i zamiast ustawiać się na osi pionowej, układają się poziomo obok siebie, jeżeli jest wystarczająco dużo miejsca. Jest to kluczowa informacja, o której należy pamiętać podczas budowy stron internetowych.

Spójrzmy na kilka innych przykładów. W przykładzie B są trzy bloki, nie mające przypisanej własności float:


.block { 
  width: 200px;
  height: 200px;
}

Widzisz, jak układają się jeden nad drugim? Na tym właśnie polega rozmieszczenie elementów w układzie normalnym. A teraz ten sam kod HTML, ale z zastosowaniem własności float (przykład C):

.block { 
  float: left;
  width: 200px;
  height: 200px;
}

Teraz bloki ustawiają się obok siebie. Świetnie, to już mamy ustalone. Ale o co dokładnie chodziło mi w wypowiedzi „ jeżeli jest wystarczająco dużo miejsca”? Miałem nadzieję, że nie spytasz. Weźmy poprzedni przykład i pięciokrotnie zwiększmy liczbę pól blokowych. Elementem-rodzicem w tym przypadku jest element body. Zauważ, że jeśli zmniejszysz rozmiar okna przeglądarki (a więc też i elementu body) część bloków zostaje przeniesiona do nowego wiersza, ponieważ nie ma dla nich miejsca w pierwszym rzędzie. Gdy zwiększysz rozmiar okna przeglądarki, zauważysz że elementy same odpowiednio zmienią swoje położenie. Sprawdź to w przykładzie D.

Własność clear

Własność float ma nieodłączną towarzyszkę o nazwie clear. Te dwie własności uzupełniają się wzajemnie i żadna z nich bez drugiej nie dałaby Ci pełni szczęścia. Jak zapewne pamiętasz, elementy pływające są najpierw rozmieszczane zgodnie z zasadami układu normalnego, a dopiero potem z niego wyjmowane. Oznacza to, że każdy element znajdujący się za pływakiem będzie zachowywał się niezgodnie z Twoimi oczekiwaniami. I tu mogą rozpoczynać się kłopoty. Spójrzmy na jeszcze jeden przykład z użyciem bloków. W przykładzie E dwa bloki (różowy i niebieski) są pływakami, a dwa inne, znajdujące się bezpośrednio za nimi (zielony i pomarańczowy) — nie. Oto kod HTML i CSS przykładu E:

<div class="block pink float"></div>
<div class="block blue float"></div>
<div class="block green"></div>
<div class="block orange"></div>
.block {
  width: 200px;
  height: 200px;
}
.float { float: left; }
.pink { background: #ee3e64; }
.blue { background: #44accf; }
.green { background: #b7d84b; }
.orange { background: #E2A741; }

Podoba Ci się ten zielony prostokąt? A gdzie on jest? Znajdziesz go pod różowym blokiem. Bloki różowy i niebieski są pływakami i zachowują się zgodnie z naszymi oczekiwaniami, tzn. ustawiły się obok siebie. Ponieważ jednak zostały one wyjęte z normalnego układu, bloki zielony i pomarańczowy zachowują się tak, jakby tych pływających elementów w ogóle nie było. To właśnie dlatego nasz zielony blok ukrył się pod różowym prostokątem. Jak sprawić, aby zielony blok stał się widoczny? Należy użyć własności clear.

Własność clear przyjmuje pięć wartości: left, right, both, inherit oraz none. Wartość left oznacza, że górna krawędź elementu musi znajdować się pod jakimkolwiek elementem mającym zdefiniowane ustawienie float: left. To samo dotyczy wartości right — element musi znajdować się pod jakimkolwiek elementem mającym przypisane ustawienie float: right. Wartość both sprawia, że element jest przenoszony pod wszystkie elementy pływające — zarówno w lewo jak i prawo. Wartość inherit sprawia, że przejęta zostaje ustawienie własności clear od elementu-rodzica, natomiast none — tak, jak się domyślasz. Uzbrojeni w tę nową wiedzę spójrzmy na przykład E2. Tym razem zielonemu blokowi przypisaliśmy własność clear. Oto zmodyfikowana wersja kodu:

<div class="block pink float"></div>
<div class="block blue float"></div>
<div class="block green clear"></div>
<div class="block orange"></div>
.block {
  width: 200px;
  height: 200px;
}

.float { float: left; }
.clear { clear: left; }
.pink { background: #ee3e64; }
.blue { background: #44accf; }
.green { background: #b7d84b; }
.orange { background: #E2A741; }

Dzięki przypisaniu deklaracji clear: left zielonemu blokowi, zmusiliśmy go, aby traktował różowy blok jak element układu normalnego, mimo że ten w nim nie jest, i ustawienia się pod nim. Własność clear jest niezwykle przydatna. Za jej pomocą możemy przywrócić elementy niepływające do normalnego układu, czyli sprawić aby zachowywały się zgodnie z naszymi oczekiwaniami. Umiejętność posługiwania się własnościami float i clear otwiera przed nami całkiem nowe możliwości tworzenia przy użyciu języków HTML i CSS.

Tworzenie układów stron przy użyciu własności float

W tej części artykułu zajmiemy się technikami tworzenia układów stron. Jest to jedna z najważniejszych dziedzin zastosowania własności float. Typowy układ dwóch kolumn można utworzyć na wiele sposobów. W większości z nich używany jest przynajmniej jeden element pływający. Spójrzmy na prosty przykład: dwukolumnową stronę z treścią po lewej stronie, nawigacją po prawej oraz stopką i nagłówkiem. Ponieważ jest to artykuł o używaniu elementów pływających, będę pokazywał tylko kod dotyczący tych elementów. Oto przykład F:

#container {
  width: 960px;
  margin: 0 auto;
}

#content {
  float: left;
  width: 660px;
  background: #fff;
}

#navigation {
  float: right;
  width: 300px;
  background: #eee;
}

#footer {
  clear: both;
  background: #aaa;
  padding: 10px;
}

Przenalizujemy go. Element pełniący rolę kontenera ma identyfikator #container. Obejmuje on nasze elementy pływające i utrzymuje je na miejscu. Gdyby nie on, pływaki rozeszłyby się do lewej i prawej krawędzi obszaru roboczego (okna przeglądarki). Dalej znajdują się reguły dla elementów #content i #navigation. To są nasze pływaki. Element #content wysyłamy pod lewą krawędź a #navigation — pod prawą i w ten sposób uzyskujemy układ dwukolumnowy. Szerokość każdego z nich ustawiłem w taki sposób, aby w całości wypełniały kontener. Na końcu znajduje się reguła elementu #footer, któremu przypisaliśmy własność clear. Jak pamiętasz, własność ta sprawia, że element, któremu została przypisana jest przenoszony z powrotem do układu normalnego, jeśli znalazł się w sąsiedztwie elementu pływającego. W tym przypadku elementowi #footer przypisaliśmy wartość both, dzięki czemu element ten zostaje przeniesiony zarówno pod element #content jak i #navigation.

Co by się stało, gdybyśmy zapomnieli przypisać elementowi stopki własności clear? Spójrz na przykład G.

Stopka przesunęła się pod element #navigation. Stało się tak dlatego, ponieważ pod elementem #navigation było wystarczająco miejsca, aby zmieścił się tam element #footer, a ponieważ pracujemy w układzie normalnym, element ten zachował się jak najbardziej prawidłowo. Tyle że nie o to nam chodziło, prawda? Zapewne zaczynasz już rozumieć, jak oddziałują między sobą własności float i clear i jak się wzajemnie uzupełniają.

Jeśli jesteś maniakiem dokładności, tak jak ja, to zapewne zauważyłeś w przykładzie F, że kolumny #content i #navigation mają różne wysokości. Jest kilka sposobów na rozwiązanie tego problemu, ale ich opis wykracza poza temat tego artykułu. Znakomite wyjaśnienie rozwiązania kwestii wysokości kolumn niezależnie od ilości zawartej w nich treści znajduje się w artykule Faux Columns (Fałszywe kolumny) Dana Cederholma.

Elementy pływające przodem

Przedstawione dotychczas przykłady były bardzo proste i raczej nikomu nie mogłyby sprawić problemów. Mimo to istnieją pewne pułapki, w które można wpaść podczas pracy z własnością float. Co ciekawe, jedna z największych pułapek nie dotyczy samych arkuszy stylów, a HTML-a. Położenie elementu pływającego w kodzie źródłowym HTML ma wpływ na to, jaki wynik zobaczymy na ekranie. Spójrz na przykład H.

Mamy tu niewielkie pole. Przy jego prawej krawędzi znajduje się pływający obraz, po lewej stronie którego znajduje się tekst. Oto kod CSS tego przykładu:

#container {
  width: 280px;
  margin: 0 auto;
  padding: 10px;
  background: #aaa;
  border: 1px solid #999;
}

img {
  float: right;
}

Element-rodzic, #container, ma niewielką szerokość, a element img znajduje się w jego wnętrzu. Kod HTML wygląda następująco:

<div id="container">
  <img src="image.gif" />
  <p>To jest tekst, który znajduje się w 
niewielkim bloku. Wykorzystuję go jako przykład
pokazujący, że miejsce umieszczenia elementów pływających w 
dokumencie HTML ma wpływ na układ wynikowy. Na 
przykład, spójrz na ten wspaniały obraz 
zastępczy, który powinien znajdować się po prawej stronie.</p>
</div>

Teraz efekt jest taki, jakiego się spodziewaliśmy, ale co się stanie, gdy nieco zmienimy kolejność elementów HTML? W przykładzie I element img przeniesiemy za akapit:

<div id="container">
  <p>To jest tekst, który znajduje się w
niewielkim bloku. Wykorzystuję go jako przykład
pokazujący, że miejsce umieszczenia elementów pływających w 
dokumencie HTML ma wpływ na układ wynikowy. Na 
przykład, spójrz na ten wspaniały obraz 
zastępczy, który powinien znajdować się po prawej stronie.</p>
  <img src="image.gif" />
</div>

Teraz już wynik nie jest zgodny z oczekiwaniami. Obraz nadal spływa do prawej krawędzi rodzica, ale już nie znajduje się w górnym rogu, tak jakbyśmy chcieli, tylko pod akapitem. Co gorsza na dodatek wystaje poza dolną krawędź elementu #container, w którym się znajduje. O co chodzi? Przede wszystkim jedną z najważniejszych zasad, jakie sformułowałem tworząc układy stron jest elementy pływające przodem. To znaczy, w kodzie HTML elementy pływające prawie zawsze umieszczam na początku, przed elementami niepływającymi, z którymi będą one wchodzić w interakcje, tak jak w przypadku powyższego akapitu. W większości przypadków to wystarczy, aby otrzymać żądany efekt. Jeśli natomiast chodzi o wystawanie obrazu poza dolną krawędź nadrzędnego elementu #container, to żeby zrozumieć dlaczego tak jest, musisz poznać pojęcie kurczenia się elementów. Zobaczmy zatem na czym polega kurczenie się elementów i co z tym zrobić.

Kurczenie się elementów

Kurczenie się elementów występuje wtedy, gdy element zawiera elementy pływające. Wówczas element taki nie rozciąga się, aby je wszystkie objąć. Inaczej jest w przypadku elementów niepływających — wtedy element nadrzędny rozciąga się tak, aby je wszystkie objąć. W przykładzie I element nadrzędny #container skurczył się tak, jakby elementu img w ogóle nie było. Nie jest to wynik błędu przeglądarki, ale poprawny i spodziewany sposób działania. Ponieważ elementy pływające są najpierw umieszczane w układzie normalnym, a następnie z niego wyjmowane, element #container nie traktuje znajdującego się w nim elementu img, jako swojej zawartości i zachowuje się tak, jakby go tam w ogóle nie było. Na marginesie, Eric Meyer napisał znakomity artykuł na ten temat pt. Containing Floats, w którym szczegółowo opisał to zagadnienie. Polecam. Na szczęście istnieje wiele sposobów na rozwiązanie tego problemu. Jeśli myślisz, że potrzebna do tego jest własność clear, to jesteś na dobrym tropie.

Jednym z najczęściej stosowanych rozwiązań problemu kurczenia się elementu nadrzędnego zawierającego element pływający jest umieszczenie elementu ze zdefiniowaną własnością clear za tym elementem pływającym. To powoduje, że element nadrzędny przywraca normalny układ za elementem pływającym. Najłatwiej jest to wyjaśnić na przykładzie. Spójrz na kod HTML przykładu J, który jest bardzo podobny do poprzedniego, tylko zawiera jeden dodatek:

<div id="container">
  <p>To jest tekst, który znajduje się w 
niewielkim bloku. Wykorzystuję go jako przykład
pokazujący, że miejsce umieszczenia elementów pływających w
dokumencie HTML ma wpływ na układ wynikowy. Na 
przykład, spójrz na ten wspaniały obraz 
zastępczy, który powinien znajdować się po prawej stronie.</p>
  <img src="image.gif" />
  <div style="clear: right;"></div>
</div>

Umieszczając w kodzie element div ze śródliniowo przypisaną deklaracją clear: right sprawiliśmy, że element #container musiał obliczyć swoją wysokość z uwzględnieniem elementu pływającego, ponieważ pod tym elementem znalazł się element należący do układu normalnego. Mimo iż rozwiązanie to pozwala uzyskać właściwy efekt, to jednak nie jest eleganckie, ponieważ wymaga wstawienia dodatkowego elementu HTML. O wiele lepiej byłoby, gdybyśmy użyli tylko kodu CSS. Jest kilka metod tego rodzaju. Przyjrzymy się jednej z nich.

Spójrz na poniższy przykład, w którym mamy element nadrzędny zawierający trzy pływające obrazy. Kod HTML wygląda następująco:

<div id="container">
  <img src="image.gif" />
  <img src="image.gif" />
  <img src="image.gif" />
</div>

Kod CSS:

#container {
  width: 260px;
  margin: 0 auto;
  padding: 10px 0 10px 10px;
  background: #aaa;
  border: 1px solid #999;
}

img {
  float: left;
  margin: 0 5px 0 0;
}

Gdy wyświetlisz stronę z tym kodem w przeglądarce, to odkryjesz, że element nadrzędny nie obejmuje znajdujących się w nim pływających obrazów. Tego oczywiście należało się spodziewać, ponieważ elementy pływające są wyjmowane z układu normalnego, przez co nasz element nadrzędny #container jest „pusty”. Zobacz to w przykładzie K.

Teraz rozwiążemy problem przy użyciu kodu CSS zamiast dodawać elementy HTML do dokumentu. Istnieje sposób na zmuszenie elementu nadrzędnego do objęcia znajdujących się w nim pływaków. Polega on na użyciu własności overflow z wartością hidden. Należy zaznaczyć, że własność overflow nie została stworzona z myślą o takim zastosowaniu, przez co użycie tej techniki może mieć efekty uboczne w postaci niechcianego ukrywania treści albo wyświetlania niechcianych pasków przewijania. Więcej na ten temat możesz poczytać tutaj i tutaj. W naszym przykładzie zastosujemy ustawienie overflow: hidden do elementu nadrzędnego #container:

#container {
  overflow: hidden;
  width: 260px;
  margin: 0 auto;
  padding: 10px 0 10px 10px;
  background: #aaa;
  border: 1px solid #999;
}

Wynik jest przedstawiony w przykładzie L. Nieźle, prawda? Inna metoda, która daje podobny efekt, a ma mniej wad polega na użyciu pseudoelementu :after. Kod HTML pozostaje bez zmian, a kod CSS wygląda następująco:

#container:after {
  content: ".";
  display: block;
  height: 0;
  clear: both;
  visibility: hidden;
}

W tym przypadku za pomocą kaskadowych arkuszy stylów za elementem #container wstawiliśmy nowy element zawierający kropkę oraz nadaliśmy mu zerową wysokość i ukryliśmy go. Szczegółowy opis tej techniki znajduje się w serwisie Position is Everything.

Eric Meyer opisuje jeszcze inną metodę rozwiązania tego problemu w artykule, który był już wspominany wcześniej — Containing Floats. Zgodnie ze specyfikacją CSS 2.1:

element pływający rozszerza się, aby objąć wszystkie elementy pływające, które się w nim znajdują.

Zatem w naszym przypadku wystarczyłoby zamienić kontener w element pływający, aby objął on nasze obrazy i akapit.

Wszystkie opisane techniki dają taki sam efekt. Sprawiają, że element nadrzędny nie ignoruje rozmieszczenia znajdujących się w nim elementów pływających. Każda ma swoje zalety. Należy poznać je wszystkie i wybierać konkretną z nich zależnie od sytuacji.

Rzeczy, od których włos jeży się na głowie

Możesz nie wierzyć, ale elementy pływające mogą powodować ujawnienie się w przeglądarkach różnych błędów, takich jak błąd podwójnego marginesu czy 3px Text-Jog. Ich opis wykracza poza ramy tematyczne tego artykułu, ale nie martw się, jeśli planujesz pisać stronę dla starszych przeglądarek, to problemy te można łatwo rozwiązać.

Podsumowanie

Własność float może być bardzo przydatnym narzędziem w Twojej codziennej pracy nad układami stron. Wiedza na temat sposobu jej działania i znajomość praw rządzących zachowaniem elementów pływających pozwolą Ci efektywnie korzystać z tej własności kaskadowych arkuszy stylów.

Tłumaczenie wykonano za pozwoleniem portalu A List Apart i autora tekstu.

Autor: Noah Stokes

Źródło: http://www.alistapart.com/articles/css-floats-101/

Tłumaczenie: Łukasz Piwko

1 komentarz

  1. Osobiście CSS doprowadzał mnie zawsze do szewskiej pasji. Głównie z powodu innej interpretacji na różnych przeglądarkach. Zwłaszcza IE miał odmienne poglądy co do interpretacji kodu :/ Najgorzej chyba jak się ustawia procentowe wartości „DIVów”, ale czasami trzeba :/

    Odpowiedz

Dyskusja

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *