CSS triky – jak obtékat i bez “clearování”
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 Kout z WEBface 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:

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.

Vše z Blog Root.cz
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.
Hezke, mozna bych u prvniho reseni zkusil misto tecky nedelitelnou mezeru.
Hned si to jdu vyzkouset. Diky.
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 ;)
Pardon, este vychytat veci pre IE :), no viem, ze som to pouzival uz podobnym sposobom. Najdem maly hack pre IE
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 :)
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;
[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á.
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ů.
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"
[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.
[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...
[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
[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.
Znovu vynalézáte kolo, pánové. Cožpak vy neznáte clearfix?
http://www.positioniseverything.net/easyclearing.html
[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
"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?
[16] Martin, vieš si predstaviť HTTP request alebo využitie úpravy DOM, jQuery selektorov bez zapnutého javascriptu v prehliadači ? :)
[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).
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.
[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
[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 ;)
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).
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.
Omlouvam se za hloupou otazku (nezivim se delanim stranek), ale nemusi byt u floatovaneho elementu nastavena sirka (li snad neni nahrazovany)?
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
[24]
Nemusi, sirka je dynamicka vzhladom na dlzku textu.
[25]
To sme poteseni :)
[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).
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í.
[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.
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é.