spájame
slovenskú
IT komunitu
pridaj sa
Registrácia · Login

Matúš Koprda 20.5.2011
Hodnoť článok:
1 0

Margin collapsing

Určite ste sa s týmto podivným javom stretli. Správanie marginov je špecifikáciou CSS definované tak, že navonok vyzerá ako by mali všetky browsery nejaký zlý bug. Prečo vám kvôli nemu vznikajú diery v designe sa dozviete v tomto článku.

Predstavte si, že chcete dať do bočného stĺpca na stránke nejaký ten "chlievik" ako je na obrázku, kde má byť hlavička pekne spojená s obsahom. Ak by ste použili len marginy, dopadli by ste takto biedne ako ja na druhom obrázku.

Vychádzame z nasledovného kódu (CSS je v komentároch), ktorý by úplne fungoval, keby žijeme vo svete s logickejšou špecifikáciou CSS. ;)

<div class="box_heading">Hlavička</div> <!-- padding:8px -->
<div class="box_content"> <!-- margin-left:8px -->
	<h3>Podnadpis</h3> <!-- margin:8px -->
	<p>Blabla<br>Kecy</p> <!-- margin:8px -->
</div>

Prečo je teda medzi sivým a zeleným obdĺžnikom medzera, keď ani jeden z nich nemá takéto správanie definované v CSS? Ako by sa dalo čakať v článku o collapsing marginoch, môžu za to collapsing marginy.

To je koncept, ktorý pôvodne vznikol s dobrým úmyslom a dopadol tak, že akurát domýlil kopec ľudí namiesto toho aby im pomohol. Nápad bol taký, že keď máte pod sebou odstavce, ich marginy by sa mali prekrývať:

Nadpis

Dríst

Dríst

Dríst

Dríst

Každý odstavec v ukážke má margin 10 pixelov zhora aj zdola a nadpis až 20 pixelov. Nastáva "kolaps" marginov a spájajú sa do jedného spoločného, ktorý ma veľkosť väčšieho marginu. Autori CSS totiž predpokladali, že autori stránok budú predpokladať, že keď zadajú margin 10 pixelov, tak chcú proste medzeru o veľkosti 10 pixelov. V prípade blokov textu dáva takéto správanie ešte celkom zmysel.

Horšie je, že ku kolapsu dochádza nielen pri susediacich elementoch ale aj pri vnorených. A na to už nemám žiadne vysvetlenie. Netuším čo mohlo behať hlavami tvorcov keď vymysleli takúto hovadinu. :) V nasledujúcej ukážke vidíte ako vyzejú do seba vnorené elementy s marginami:

hovno z toho, že tu je margin

Všimnite si, že horizontálny margin sa chová normálne a iba vertikálny má nejaké nekalé úmysly. Všetky vertikálne marginy sa spojili do jedného 10-pixelového, ktorý pretŕča cez najvyšší element. To nie je bug, to je feature.

Z tejto ošemetnej™ situácie sa vieme dostať viacerými spôsobmi. Prvým a najspoľahlivejším je vloženie niečoho medzi marginy. Tým niečím môže byť buď padding alebo rámik (border). S paddingom 1px zhora aj zdola by už vyzerali obdĺžniky normálne (samozrejme s miernym rozšírením o 2 pixely):

padding fuck yeah
/* predtym */
div.obdlznik { margin: 5px; }

/* potom */
div.obdlznik { margin: 5px; padding: 1px 0px; }

Druhým riešením je nastavenie floatu postihnutému elementu a jeho následné "clearnutie". Floaty totiž z nejakého dôvodu nepodliehajú collapsingu. Toto riešenie nie je až také dobré z hľadiska, že vyžaduje viac písania a clear element navyše, ale zíde sa, ak sa ocitnete v situácii, kedy proste nemôžete použiť paddingy alebo rámiky, lebo sa zrúti svet.

Hlavička

Podnadpis

Bez akýchkoľvek úprav, čiže s dierami

Hlavička

Podnadpis

Podnadpis je floatovaný a pod ním je div s clearom (^prudko slovenská veta;)

Hlavička

Podnadpis

Riešenie s paddingom na šedom rámiku

/* original */
div.hlavicka { background: #75ac00; padding: 8px; color: #fff; }
div.obsah { background: #e0e0e0; margin-left: 8px; }
div.obsah h3 { margin: 8px; }

/* riesenie s floatom */
div.obsah h3 { margin: 8px; float: left; }
div.clear { clear: left; } /* tento element musi nasledovat za podnadpisom */

/* riesenie s paddingom */
div.obsah { background: #e0e0e0; margin-left: 8px; padding: 1px 0; }

Nebol by to Internet Explorer, keby situáciu trocha nezamotal. IE6 a 7 ignorujú collapsing ak má element "layout". Layout je Microsoftovský výmysel, ktorý element získa napríklad keď má nastavené pevné rozmery alebo s magickým príkazom zoom:1. Pro tip na záver: ak náhodou nepoznáte zoom:1, je to magický liek pre IE6 (a 7), čo sám o sebe viac menej nič nerobí, iba "ruší" niektoré bugy.

Matúš Koprda Matúš Koprda

Momentálne robím internety a keď budem veľký, snáď sa dostanem aj k hrám alebo niečomu zmysluplnému. :) Mám rád minimalizmus, obskúrnu hudbu, všetko geeky a rýpanie sa v detailoch. Ďalšie kecy odo mňa nájdeš na brm.sk a na Twitteri @blade_sk.


Hodnoť článok:
1 0

22 komentárov k článku:

Komentovať môžu iba prihlásení

Zaregistruj sa cez bezplatnú registráciu alebo použi login cez Facebook (FB Connect)

Prihlás sa tu, ak už máš profil na Zajtra.sk:


Zabudol som heslo

0 0 Maroš Masarovič 9.1.2012 23:14:04
@Matúš :D no musim ti podakovat znova : vdaka tej poznamke ze padding ide som sa pozrel na stranku vdaka ktorej som kedysi davno zacal spoznavat html a css a z ktorej som si pamatal: "Internet Explorer poněkud chybně interpretuje vlastnost šířky objektu width, když do ní zahrnuje i padding a border. " :D no a ona tam je dalej napisane ze: "Správně to dělá až Internet Explorer 6... " tkaze som sa padingu stranil zbytocne :) njn to je tak ked sa clovek do dacoho pusta po sto rokoch :) ale tak som sa aspon dobre na sebe zasmial
0 0 Matúš Koprda 20.10.2011 00:46:24
@Maroš Super, teším sa, že sa (po 5 mesiacoch :D) konečne našiel niekto, čo chápe, že popisovaný jav naozaj existuje. :)
IE by nemal mať problém s paddingami. Teda no, IE má problém so všetkým, ale v zásade tam paddingy idú.
0 0 Maroš Masarovič 18.10.2011 02:18:51
Matus dakujem za clanok. Pomohol mi. Robim zlozitejsi layout a pouzitie marginu sa zdalo byt prehladnym riesenim.(kvoli ie som pading nezvazoval). Stravil som hodnu chvilku hladanim problemu a pomaly mi stupal tlak s mojou biednou anglictinou sa mi do specifikacie nechcelo. Este raz dik. PS: stale zasnem kolko narusenych ludi chodi po svete. Myslia si ze su mudrost sama a je ich povinostou dokazovat to a hlavne v diskusiach pod niecim hodnotnym.
0 0 Matúš Koprda (fb) 24.5.2011 00:00:00
@viktor <br> sa celym menom vola "forced line break", co dobre vystihuje aj jeho ucel. Napriklad ak by si v html chcel naformatovat basen, strofy by mali byt obalene v <p> a verse oddelene <br>.
0 0 Viktor Čech (fb) 23.5.2011 00:00:00
tu nejde o to, ci je to validne, ale semanticke, ci logicke..
0 0 Matúš Koprda (fb) 23.5.2011 00:00:00
Nejde o to, ze ten primitivny ilustracny priklad da riesit inac, pointa je, ze EXISTUJU nejake collapsing margins, ako sa prejavuju a co s nimi. To bola snaha tohoto clanku.. zjavne nevysla na 100% :)

@jak Vid predchadzajuce 2 vety + priklad som ti poslal.. sice ti netaci, ale tak co uz :)

@viktor Drbnutym stylom budem pisat aj nadalej, lebo som znudeny z toho ako sa vsetky clanky snazia zniet rovnako nemastne neslano a neosobne. Okrem toho, margin collapsing nastava bezohladu na to, ci davas <br> dovnutra <p> (co je mimochodom uplne validne) alebo nie. Ak ti nestacilo moje vysvetlenie, skus si pogooglit co su collapsing margins.. alebo rovno pozri W3C specku http://www.w3.org/TR/CSS21/box.html#collapsing-margins
0 0 Viktor Čech (fb) 23.5.2011 00:00:00
uz tie vyrazy ako "padding fuck yeah" robia z tohto clanku drbnuty clanok.. nemam rad taketo supermoderne vyjadrovanie.. autor chce byt akoze IN, ale.. je to smiesne :)
k problemu: chyba nie je v prehliadaci.. ten len reaguje na zly kod.. br br sa do Pcka nedava.. :/ taketo veci sa riesia resetom css..
0 0 Ján Bokor (fb) 23.5.2011 00:00:00
Áno... margin vnoreného prvku 'odtláča' aj ten vonkajší. Ale stačí tomu vonkajšiemu pridať rovnako veľký padding a je po probléme.
0 0 Jak Divoký (fb) 22.5.2011 00:00:00
@Miro no ten clanek bych rozhodne studentum necitoval, neb je docela zmatecny a tady Matus neni schopen uvest relevantni priklad uziti toho jeho nesmyslu... smutne
0 0 Miroslav Sopko (fb) 21.5.2011 00:00:00
Mňa pri tomto inak zaujímavom článku mrzí len to, že ho vďaka niektorým výrazom a následným komentárom asi nebudem odporúčať svojim žiakom na krúžku tvorba webových stránok (aj keď nemám pochybnosti, že mnohí z nich bežne používajú ešte "šťavnatejšie" výrazy).
0 0 Jak Divoký (fb) 21.5.2011 00:00:00
@Koprda: hod sem cely kod toho obrazku + CSS (staci sem do komentu) je to par radku, pak se da o tom polemizovat .)
0 0 Matúš Koprda (fb) 21.5.2011 00:00:00
@Jak Pozri: http://i.imgur.com/TsDRr.png (rozmazane, kvoli NDA)
Neviem ci to mam aj nejak obsirne vysvetlovat, ale proste ten content box mohol (aj nemusel) mat hore obrazok. Teoreticky by mohol mat content box padding a obrazok negativne marginy, ale to mi je proti srsti :)
0 0 Jak Divoký (fb) 20.5.2011 00:00:00
@Matúš No kdyby Te ten pripad nahodou napadl, tak to sem prosimte hod, to by mohlo byt zajimave, priznam se, ze ted z hlavy mne to moc nenapada hehe...

btw. tomu lolkovi, ani neodpovidej, kdyby nam aspon konkretne napsal co se mu nelibi a argumentoval, vykriky po slepu na ceste jsou ale nejlepsi, pravda heh .-D
0 0 Matúš Koprda (fb) 20.5.2011 00:00:00
@Jan Je to príklad ilustrujúci čo je margin collapsing, jasné, že by sa to dalo riešiť ináč. Na druhej strane, kľudne sa môžeš dostať do situácie, kedy by si sa tomu nevyhol..

@Miroslav Haha, mám blog, dokonca je to napísané aj v obdĺžniku o autorovi :)
A ďakujem za nesmierne hodnotný komentár, ľudia ako ty robia svet krajším ;)))
0 0 Jak Divoký (fb) 20.5.2011 00:00:00
@Miroslav | ehm, Ty byses mohl naucit zase slusnemu chovani. Proc tu neco komentujes, kdyz hodnata Tve vypovedi jest rovna absolutni nule. Matúš se na to dival proste z jineho pohledu, nez se na to divas ty treba...
0 0 Miroslav Čirka (fb) 20.5.2011 00:00:00
chlapce prestan pisat clanky o odboroch, ktorym hovno rozumies... nie je to ani poucne a dokonca ani vtipne (ako sa mylne domnievas)... ked chces pisat pičoviny, tak si zaloz blog
0 0 Jak Divoký (fb) 20.5.2011 00:00:00
div, h3, p {margin:0; padding:0;}
.box_heading {padding:8px; background: #75ac00; color: #fff;}
.box_content {margin-left:8px;background: #e0e0e0;}
.box_content h3 {padding:8px;}
.box_content p {margin: 8px;}

a nic neresim, proste nebudu rvat margin tam kam nepatri, kdyz se neumi chovat hehehe .-D
0 0 Matúš Koprda (fb) 20.5.2011 00:00:00
CSS reset by nemal žiadny efekt, lebo akonáhle začnete používať marginy, budú sa správať ako je ukázané v článku.

S position:absolute by sa zase "rodičovský" element zmenšil ako keby tam ten vnorený "absolute" element ani nebol.

Ale všetci asi narážate na ten nadpis "ako zničiť marginy". Nadpis vymyslel Tomáš (don't blame me :D) a je trocha zavádzajúci ak si neprečítate aj to pod ním - ktoré sú **tam kde nemajú byť**. Takže reč je o odstránení collapsingu, nie od úplom odstránení marginov. Na to by stačilo dať, ako ste spomenuli, jednoduché * {margin:0}
0 0 Jak Divoký (fb) 20.5.2011 00:00:00
presne tak reset to resi, skoda toliko slov a tak nejak zbytecne...
0 0 Milan Rybovič (fb) 20.5.2011 00:00:00
Stačil by základný CSS reset a bolo by po probléme :) Ale, pekný článok :) gl
Zajtra.sk > Programovanie > CSS/HTML > Margin collapsing


Kritika

Vieš ako robiť veci lepšie? Pomôž našim odvážnejším členom a skritizuj im projekty!

Reklama

Seriály zo Zajtra.sk

Reklama