CSS triky - jak obtékat i bez "clearování"

9. 7. 2008 19:54 (aktualizováno) | Martin Hassman

Dostal se ke mně zajímavý webdesignérský trik, o který se musím podělit. Jak se zachází s plovoucími („floatovanými“) prvky pomocí kaskádových stylů jistě víte. Ovšem víte i jak nejlépe jejich obtékání ukončit?

Pokud ihned vyhrknete, že přidáte značku s clear:left; clear:right nebo clear:both, tak sice máte pravdu, ale já se ptal jak nejlépe plovoucí sekci ukončit.

Pavel KoutWEBface mi totiž zaslal řešení, jak obtékání ukončit i bez přidané značky navíc. Já o něčem takovém slyšel poprvé. Nevěřil jsem. Zkoumal. Testoval. A nakonec pochopil. Skutečně, Pavlova řešení (ano, hned dvě různá řešení) tento malý zázrak umožní a fungují ve všech běžných prohlížečích.

Výsledek naší ukázky bude vypadat takto:

Obtekani - vysledka ukazka

Nadpisy panelů na obrázku jsou ve skutečnosti neuspořádaný seznam, který je tvořen plovoucími položkami. Vlastní obsah panelů je ale nesmí obtékat, nýbrž má být umístěn až pod nadpisy (na obrázku vlastně žádný obsah nemáme, jen bílý prázdný obdélník).

Napřed si připravme základní kód společný pro obě řešení.

XHTML:

<ul>
  <li><a href="#">first</a></li>
  <li class="selected"><a href="#">second</a></li>
  <li><a href="#">third</a></li>
</ul>

CSS:

ul {
  list-style: none;
  margin: .8em 0 0 0;
  padding: 0;
  border-bottom: 1px solid #DDDDDD;
}

ul li {
  position: relative; /* IE6 only */
  float: left;
  background-color: #EEEEEE;
  border: 1px solid #DDDDDD;
  padding: 5px 15px;
  margin: 0 5px -1px 0;
  list-style: none;
  display: block;
}

html>body ul li {
  position: static;
}

ul li:hover {
  background-color: white;
}

ul li.selected {
  background-color: white;
  border-bottom-color: white;
}

První řešení – použití after

V prvním řešení k ukončení obtékání použijeme pseudoelement :after, kterému nastavíme clear:both. Obejdeme tím nutnost přidávat další značku – jednoduše využijeme pseudoelement (pseudoznačku). Jednoduché a elegantní.

ul {
  height: 1%; /* IE workaround */
  overflow: visible; /* IE workaround */
}
ul:after {
  content: ".";
  display: block;
  height: 0;

  clear: both;

  visibility: hidden;
}

Důležitá jsou pravidla pro ul:after, první pravidla pro ul jsou pomůckou jen pro IE.

Omezení: pseudoelement :after může být u každé značky jen jeden. Proto pokud byste :after již využívali pro svojí potřebu, zmíněné řešení nemůžete použít.

Druhé řešení – nastavíme obecnou následující značku

V druhém řešení použijeme selektor pro následujícího sourozence a ať jím je kterýkoliv prvek, nastavíme mu clear:both. Když o té myšlence přemýšlím, připadá mi strašně triviální, nicméně samotného mě nikdy nenapadla.

ul {
  height: 1%; /* IE6 only */
  margin-bottom: -4px; /* IE6 only */
  overflow: visible;
  float: left;
  width: 100%;
}
html>body ul {
  height: auto;
  margin-bottom: 0;
}
*+html>body ul {
  margin-bottom: -4px; /* IE7 only */
}
ul + * {
  clear: both;
}

Nejdůležitější je označené univerzální pravidlo se selektorem ul + *, kterým opět obejdeme nutnost přidávat další značku pro ukončení obtékání. My totiž využijeme první značku za naším seznamem, ať je to jakákoliv značka (pokud by žádná následující sourozenecká značka neexistovala, museli bychom selektor upravit).

Obě řešení spolu s dalšími pokusy najdete na adrese http://client.webface.cz/temp/clear-float-tabs.html

Zmíněná řešení jsou k nezaplacení zejména pokud:

  • chcete mít (X)HTML kód co nejjednodušší (nechceme ho mít plný značek jen pro clearování)
  • nemůžeme do stávajícího (X)HTML kódu zasahovat (např. když tvoříme uživatelské styly)

Věřím, že předvedená řešení řada z vás někdy využije. Já za ně Pavlu Koutovi děkuji. Pavel potvrzuje, že stále patří mezi přední osoby českého webdesignu.

  • 30. 6. 2008 11:52

    veena (neregistrovaný)

    A co obyčejné overflow nadřazenému prvku (zde ul)?
    Pozor na hasLayout u IE6 (width:100% nebo zoom:1)

    Viz http://www.quirksmode.org/css/clearing.html

    Takové vychytávky bych také rád uvedl na WebExpo.

  • 30. 6. 2008 11:57

    Martin Kopta (neregistrovaný)

    Hezke, mozna bych u prvniho reseni zkusil misto tecky nedelitelnou mezeru.

    Hned si to jdu vyzkouset. Diky.

  • 30. 6. 2008 12:08

    Radovan (Uzivatel) (neregistrovaný)

    Načo riešiť veci jednoducho keď to ide zložito :)

    Moje riešenie bez floatovania

    ul li {
    /* mozilla haven't inline-block */
    display: -moz-inline-block;
    display: -moz-inline-box;
    display: inline-block;

    a inline-block podporuju všetky prehliadače len mozilla nie, no na to tam je specialny atribut ;)

  • 30. 6. 2008 12:11

    Radovan (Uzivatel) (neregistrovaný)

    Pardon, este vychytat veci pre IE :), no viem, ze som to pouzival uz podobnym sposobom. Najdem maly hack pre IE

  • 30. 6. 2008 12:19

    Radovan (Uzivatel) (neregistrovaný)

    Tak som hladal, ja som podobne riesenie vyuzil pri odkaze v riadku, aby som mal z neho blok.
    Na blogu quirksmode je napisane:

    "IE 6/7 accepts the value only on elements with a natural display: inline."

    Takze jedine oddelenym CSS alebo pomocou javascriptu IE7/8. Kazdopadne je to podla mojeho nazoru cistejsie riesenie ako tu spominane. Podobne riesenia na "dve strany" pre obycajnu prkotinu mi obcas vedia len privodit nazor, ze musi to ist aj lepsie :)

  • 30. 6. 2008 12:29

    Radovan (Uzivatel) (neregistrovaný)

    Som ja ale slepy. Nerozmyslam nad tym co pisem :)

    ul li {
    display: inline

    ul li a
    /* mozilla haven't inline-block */
    display: -moz-inline-block;
    display: -moz-inline-box;
    display: inline-block;

  • 30. 6. 2008 12:32

    Pavel Kout (neregistrovaný)

    [2] Ano, Martine. Ono tohle je tohle vyčištění vlastně známé už déle (z pravěku, kdy jsme si říkávali "tohle bych chtěl jednou používat"), ale problém je IE. Tak mě napadlo zkombinovat to s validními filtry pro IE, které znám, aby to bylo skutečně použitelné už aspoň dnes.

    Teď mě zrovna čeká kódování layoutu s hromadou záložek (cestovka) a potřeboval jsem najít elegantnější řešení než klasika: zapouzdřující blok, a v něm seznam (nejlépe obtékaný kvůli pozadí) a ještě "čistič" navíc. Pokud se navíc podíváš pozorněji, všimneš si ještě další odlišnosti oproti stávajícím řešením: není tam použit *žádný* obrázek (obvykle jako background-image toho nečíslovaného seznamu) — to je další goal.

    A ještě pro zajímavost: testoval jsem to i v v betě IE8 a tady je screenshot chybného zobrazení řešení 1 a 2 — http://client.webface.cz/temp/clear-float-tabs-ie8b1.png — z čehož vyplývá, že výhledově nejsou použitelná.

  • 30. 6. 2008 13:04

    Tachyon (neregistrovaný)

    A nebylo by lepší mít klidně ty floatěné ale na to mít nastavený jako
    ul {overflow: hidden;}
    není u něho nastavená žádná výška, tudíž se to natáhne krásně dle floatěných prvků.

  • 30. 6. 2008 13:08

    Radovan (Uzivatel) (neregistrovaný)

    Jejda, dúfam, že tento komentár už nebude braný ako spam, no urobím zhrnutie a vysvetlenie a deklarujem si autorske pravo na napad :-D (ironia)

    Takže zmena oproti stávajúcemu riešeniu a iným dostupných na weboch je rozdielna v tom, že nepoužíva žiadne všeobecné a krkolomné hacky, ale len jemne upravuje nekompatibilitu CSS v IE6/7 a prehliadačoch na jadre Gecko 1.8 (Firefox 2)

    ul
    {
    list-style: none;
    border-bottom: 1px solid #DDDDDD;
    }

    ul li
    {
    display: inline;
    }

    ul li a
    {
    /* mozilla haven't inline-block */
    display: -moz-inline-block;
    display: -moz-inline-box;
    display: inline-block;
    background-color: #EEEEEE;
    border: 1px solid #DDDDDD;
    padding: 5px 15px;
    margin: 0 5px -1px 0;
    list-style: none;
    }

    ul li a:hover
    {
    background-color: white;
    }

    ul li.selected a
    {
    background-color: white;
    border-bottom-color: white;
    }

    Princíp je v tom, že využijeme atribút z CSS 2.1 "display: inline-block" kedy objekt sa sprava ako blok, ale je zarovnaný ako riadkový element. Jediný použitie "hacku" je to, že prinútime Firefox nižši ako verzia 3 využit svoje riešenie tohoto atribútu, pre ostatné prehliadače (tým aj nový Firefox 3) sa využije štadardný zápis.
    Malá zmena sa týkala aj IE6/7, kedy "inline-block" je možné použiť len pre značky s prirodzeným atribútom display: inline, čo práve LI nebolo. Tým teda stačí definovať odkaz ako "inline-block" a položku zoznamu zmenit na "inline"

  • 30. 6. 2008 13:47

    Pavel Kout (neregistrovaný)

    [9] Když já se zoufale bráním používat proprietární elementy, atributy, vlastnosti a hodnoty. Používám pouze obecně platné a podporované (z důvodu dopředné kompatibility) a jsem ochoten pouze ošetřit staré "shity" (aktuálně IE6/7) za podmínky, že to nebude dělat paseku v budoucnosti (= budou ignorovány). Já vím, že jsem příliš konzervativní, ale tento přístup se mi za ta léta vyplatil.

  • 30. 6. 2008 13:57

    karf (neregistrovaný)

    [9][10] - mno, ona je otázka, co je dopředně kompatibilnější - inline-block nebo :after? Podle mě to vyjde nastejno. Jinak tyhle metody jsou známy už delší dobu, ale každá má své "ale". Já se po různých experimentech vrátil k normálnímu clearovacímu elementu, zas tolik mi tam nevadí. Mimochodem mě ale celkem zarazilo používání old-school hacků typu html>body ul. Ale proti gustu...

  • 30. 6. 2008 13:59

    Radovan (Uzivatel) (neregistrovaný)

    [10] Pavel:

    Ja to chápem, ale príde mi (osobne) veľmi zvláštne používať "škaredé" techniky na úkor použiteľnosti, prehlľadnosti a hlavne pokrokovosti. Ja som taký liberálnejši typ a mám rad pokrok.

    A tieto rozšírenia sú plne s definíciou CSS, ktorá práve na to odkazuje

    http://www.w3.org/TR/CSS21/syndata.html#vendor-keywords

  • 30. 6. 2008 14:03

    Radovan (Uzivatel) (neregistrovaný)

    [11] Karf, no ono to je dost na uvážnie, ale keď si zoberieš, že CSS 2.1 tu je dosť dlho na to, aby väčšina vecí bola implementovaná (a ked nie je tak aspoň niečo), tak ju treba využiť.

    http://www.quirksmode.org/css/display.html

    Jediné problémy boli s týmito dvoma "hekmi". No že nie sú validné (iba v prípade Firefoxu 2 a nižšie) ? To mi nijako nevadí keď priamo norma o týchto vychytávkach spomína.

  • 30. 6. 2008 14:08

    Rixo (neregistrovaný)

    Znovu vynalézáte kolo, pánové. Cožpak vy neznáte clearfix?

    http://www.positioniseverything.net/easyclearing.html

  • 30. 6. 2008 14:27

    Radovan (Uzivatel) (neregistrovaný)

    [14] Rixio, nič proti gustu, ale aspoň u mňa skončila éra hnusných hackov, ak niečo nejde už nijak jednoducho, tak použijem Dean Edvardsov javascript IE7/8.
    Získam:
    - pokojnejší spánok
    - viac voľného času
    - zdokonalím sa v novších technikách
    - posuniem web trochu dopredu

    Ja som osoba "lenivá" a po relatívne dlhom čase v oblasti web developerstva osoba pokroková.
    Vždy si treba zvážiť pre koho to robím a čo použijem. Je mi jasné, že keď budem používať hojne jQuery a Ajax prkotinky, tak vyladovať niečo pre staršie prehliadače je:
    1. strata času
    2. javascript musí byť povolený.

    No po tom druhom bode ma dúfam nebudete haniť, ale 98% ľudí ho má zapnutý a zbytok sú vačšinou ludia, čo sa boja nebezpečenstva čo nie je a milovníci príkazovej riadky

  • 30. 6. 2008 14:33

    Martin Hassman (neregistrovaný)

    "javascript musí byť povolený"

    Radovan: Zajímavé je to hlavně proto, že jQuery a obecně tyhle unobstrusive JavaScriptové knihovny byly navrženy s ohledem na to, aby výsledná webová stránka NEBYLA bezpodmínečně závislá na JavaScriptu. Tak kde děláš chybu?

  • 30. 6. 2008 14:40

    Radovan (Uzivatel) (neregistrovaný)

    [16] Martin, vieš si predstaviť HTTP request alebo využitie úpravy DOM, jQuery selektorov bez zapnutého javascriptu v prehliadači ? :)

  • 30. 6. 2008 14:51

    Pavel Kout (neregistrovaný)

    [11] "zarazilo používání old-school hacků typu html>body ul" — tady bych si dovolil upozornit, že se nejedná o hack (tj. potenciální pandořinu skříňku), nýbrž o workaround pro elegantní odliftrování té nejhloupější současné potvory (IE6) a relativně normálního zbytku (relativně kvůli IE7, což je jen o něco lepší IE6; v praxi je ovšem důsledek kolikrát spíš horší).

    [14] Ano, to je ono profláknuté řešení, které bylo zdokumentováno ještě přes původním release toho příspěvku na PositionEverything. Zaklínadlo však opět zní "IE".

    Ale dovolím si ještě jednou zopakovat to, o co mi primárně šlo — abych mohl vytvořit záložky ze kteréhokoliv nečíslovaného seznamu bez toho, abych ho uzavíral do zapouzdřujícího prvku, ošetřoval obtékání mimo tento seznam (když kód implementuje někdo další, může na to zapomenout) a abych se vyhnul použití obrázku. To samé platí třeba i pro fotogalerie (resp. thumbnaily) — opět jen UL/LIs. Proto jsem si říkal, že by to mohlo pár lidem pomoci a ukázal jsem to Martinovi.

    Nezapomeňte prosím, že si povídáme o stylování v době, kdy stále cca třetina používá IE6, který nezvládne ani např. H1 + P ( margin-top: 0; }. Lze vymyslet soustu parádních formátování, ovšem IE6 záhy obvykle srazí vaši radost z nich do záporných hodnot (ani IE7 na tom není zase o tolik lépe).

  • 30. 6. 2008 15:02

    Martin Hassman (neregistrovaný)

    Radovane a dovedeš si představit deset trpaslíků skákajících kolem tebe a šťouchajících do tebe ze všech stran každý jednou vidličkou, jak při tom na tebe volají: "NEVTÍRAVÝ JAVASCRIPT"? A když bys špatně rozuměl, oni ti to zopakují, kolikrát budeš chtít.

  • 30. 6. 2008 15:23

    Radovan (Uzivatel) (neregistrovaný)

    [19] :-D :-D

    Ja nehovorím o vtieravom javascripte, ale o tom čo uľahčuje veci. Len neviem či máš predstavu o tvorbe portálov, nie len obyčajných web stránok. Ak máš, tak sám vieš, ze bez pokročilejších techník sa nezaobídeš, pokiaľ nechceš tvoriť web ala 90te roky.
    Pokročilejšie vyhľadávanie (bez nutnosti reloadovat stránku), komplexnejšie formuláre (neviem si predstaviť 5 select boxov a pri každej zmene znova robiť reload). Bez niečoho podobného sa nezaobídeš, a keď už je javascript nuntosť, tak prečo si robiť nervy s problémami prehliadačov a riešiť veci komplikovano keď máme dostupné riešenia ?
    Dokonca v Youtube si bez javascriptiu môzeš akurát tak čítať texty, aj to len na prvej stránke, lebo ďalej neprekliknes :-D

    Javascript nie je hrozba. A preto sa k nej aj tak chovám.

    BTW: ešte teraz sa smejem :-D

  • 30. 6. 2008 16:14

    karf (neregistrovaný)

    [18] no jenže právě tohle se ukázalo být pandořinou skříňkou při příchodu IE7, proto můj podiv. Jinak já pragmaticky používám podtržítkový hack a nestydím se za to ;)

  • 30. 6. 2008 16:26

    Yuhů (neregistrovaný)

    Martine, nedokázal bys z toho řešení vyházet všechny věci, které tam nemusejí být? Myslím ty různé marginy a barvy. Už to čtu podruhé a stále nechápu, proč by to jako mělo fungovat v Exploreru (zejména v šestce).

  • 30. 6. 2008 16:28

    Yuhů (neregistrovaný)

    Aha, třetí čtení zabralo, omlouvám se.
    Hm, akorát si nemyslím, že to jsou dobrá řešení. Nastavování výšky na jedno procento je zadělávání si na nějaký průšvih.

  • 1. 7. 2008 7:46

    Jezz (neregistrovaný)

    Omlouvam se za hloupou otazku (nezivim se delanim stranek), ale nemusi byt u floatovaneho elementu nastavena sirka (li snad neni nahrazovany)?

  • 1. 7. 2008 9:03

    LS_999 (neregistrovaný)

    Sice se nezabyvam tvorbou webu, ale tento zapis musim pochvalit. Neco jsem se dozvedel ze zapisu, neco i v diskuzi... vice takovychto uzitecnych zapisu namisto vecneho buseni slamy

  • 1. 7. 2008 11:27

    Radovan (Uzivatel) (neregistrovaný)

    [24]

    Nemusi, sirka je dynamicka vzhladom na dlzku textu.

    [25]

    To sme poteseni :)

  • 1. 7. 2008 17:59

    Jezz (neregistrovaný)

    [26]
    Vychazim z knihy "CSS Kaskadove styly - Kompletni pruvodce" od Pixyho:
    Plovouci prvky musi mit definovanou sirku (vnitrni rozmery u nahrazovanych prvku nebo vlastnosti width).

  • 1. 7. 2008 18:16

    Martin Hassman (neregistrovaný)

    Jezz: A tak je to také řečeno ve specifikaci http://www.w3.org/TR/CSS2/visuren.html#floats Ono u plovoucích prvků používaných pro ten účel, pro který byl float skutečně vytvořen, to platilo (např. když někdo nechal plovat obrázek / tabulku s popiskem, bylo nutné explicitně říct, jak se má ten popisek zalomit).

    Ale dnes, když je float používán (chtěl bych říct i zneužíván, ovšem to už lze těžko říct, když ho tak používáme de facto každý) k tvorbě vlastního designu, to není tak jednoduché a pro řešení zmiňované v článku nepraktické až nepoužitelné - s každou změnou obsahu (popisky) by bylo nutné nastavoval i šířky a měnit design (to je ve sporu i s oddělením vzhledu a obsahu).

    Dalo by se říct, že CSS2 specifikace je nekompatibilní z praktickým používáním floatu. A do příchodu CSS3, který přinese nové designovací možnosti, se to nezmění.

  • 2. 7. 2008 0:13

    Radovan (Uzivatel) (neregistrovaný)

    [27] Jezz, kazdy prvom obsiahnuty nejaky text, alebo nedelitelnu medzeru uz ma nejaku sirku, zada sa automaticky podla dlzky obsahu a je obmedzene na velkost vonkajsieho prvku.

  • 3. 7. 2008 8:35

    karf (neregistrovaný)

    Jezz: podle CSS 1 a 2 opravdu musely mít floaty zadanou šířku, v CSS 2.1 toto pravidlo bylo vypuštěno - většina implementací se ustálila na stejném algoritmu, který je ve specifikaci popsaný, takže dnes už je to široce podporované.

Přidávat nové názory je zakázáno.

Vitalia.cz: Vakcína Cervarix je oficiálně i pro chlapce

Vakcína Cervarix je oficiálně i pro chlapce

Měšec.cz: Platíme NFC mobilem. Konečně to funguje!

Platíme NFC mobilem. Konečně to funguje!

Měšec.cz: 10 změn novely zákoníku práce

10 změn novely zákoníku práce

Měšec.cz: Test: Výběry z bankomatů v cizině a kurzy

Test: Výběry z bankomatů v cizině a kurzy

Podnikatel.cz: Česká pošta vycouvala ze služby ČP Cloud

Česká pošta vycouvala ze služby ČP Cloud

Vitalia.cz: „Sjíždět“ porno není bez rizika

„Sjíždět“ porno není bez rizika

120na80.cz: Lepší poporodní sexuální život? Žádný problém

Lepší poporodní sexuální život? Žádný problém

Root.cz: Xiaomi má vlastní notebook podobný Macu

Xiaomi má vlastní notebook podobný Macu

Lupa.cz: Elektronika tajemství zbavená. Jak s ní začít?

Elektronika tajemství zbavená. Jak s ní začít?

Měšec.cz: Na návštěvě na exekutorském úřadě

Na návštěvě na exekutorském úřadě

Podnikatel.cz: Pozor na vykuky, imitují služby České pošty

Pozor na vykuky, imitují služby České pošty

DigiZone.cz: Pevnost Boyard v září a česká

Pevnost Boyard v září a česká

Měšec.cz: Do ostravské MHD bez jízdenky. Stačí karta

Do ostravské MHD bez jízdenky. Stačí karta

Vitalia.cz: Musí moudrák opravdu ven?

Musí moudrák opravdu ven?

120na80.cz: Víte, co je svobodná menstruace?

Víte, co je svobodná menstruace?

Podnikatel.cz: Chce dodávat chlebíčky. Jaká živnost je třeba?

Chce dodávat chlebíčky. Jaká živnost je třeba?

Lupa.cz: Co najdete uvnitř kosmické sondy?

Co najdete uvnitř kosmické sondy?

Vitalia.cz: Je bílý kokos fakt tak úžasný? Ano, je!

Je bílý kokos fakt tak úžasný? Ano, je!

Vitalia.cz: Ženy, které milují příliš, jsou neštěstí

Ženy, které milují příliš, jsou neštěstí

Lupa.cz: Nechcete datacentrum? Jsou na prodej

Nechcete datacentrum? Jsou na prodej