Praktické výhody nestandardního box-modelu

…aneb nevěřte evangelistům!
19. 12. 2006

Předpokládám, že většina z vás používá standardní box-model a případně nestandardní pouze v Internet Exploreru. Málokdy vidím, že by někdo používal pouze nestandardní box-model a to pro všechny prohlížeče. Respektive si vzpomenu pouze na jeden web, který by to v praxi používal. Přitom mi přijde nanejvýš logické použít právě ten nestandardní box-model. Jednak – pokud chcete mít web optimalizovaný i pro starší verze IE, stejně se nestandardnímu box-modelu nevyhnete. A proč tedy zbytečně používat dva box-modely, když mohu snadno použít pouze jeden?

Zajímají-li vás historické souvislosti, koukněte opět na webylon nebo na pohled z druhé strany. Pokud neznáte rozdíly, přečtěte si prosím článek u Yuhůa nebo od Jozoba. A aby bylo úplně jasno, tak „standardním“ box-modelem mám na mysli ten, který běží v IE ve standardním režimu a „nestandardní“ je pak ten, který běží v quirku. Aby mě někdo pak nějak netahal za slovíčka.

A nyní již přejděme k výhodám nestandardního box-modelu. Osobně ho považuji za mnohem logičtější než za ten standardní, protože pokud nějakému bloku nastavím nějakou šířku, mohu si být jistý, že tento blok opravdu zůstane takto široký, dokud nepoužiji margin. Ve standardním box-modelu se mi konečná šířka bloku mění v závislosti na paddingu, borderu a i marginu, což mi nevyhovuje. Málokdy skládám stránky z nějakého hotového návrhu, kde bych měl přesně dané rozměry, takže neustále tyto tři hodnoty měním a zkouším, jak to bude nejlépe vypadat. Ve standardním box-modelu jsem odsouzen k neustálému přepisování šířky při jakékoliv změně paddingu (obzvláště při floatování je to o nervy) nebo musím zanořit bloky do dalších bloků (což je ovšem nehezké řešení a navíc). Tohle je ovšem příliš obecné, přejděme tedy k praktické části.

Představte si následující situaci: chcete mít stránku roztaženou na 100% šířky prohlížeče, tudíž šířky bloků jste nuceni zadávat v procentech. Jeden blok chcete mít široký 30%, druhý 70%. Zatím je všechno v pohodě, tohle uděláte jednoduše v obou box-modelech. Následující kód tedy platí pro oba box-modely (jen u standardního pochopitelně vynecháte vlastnosti -moz-box-sizing a box-sizing):

*{
margin:0;
padding:0;
-moz-box-sizing: border-box;
box-sizing: border-box

}
#levy{
width:30%;
float:left;
background:green;
}
#pravy{
width:70%;
float:right;
background:red;

}

Zatím žádný rozdíl. Problémy nastanou až teď. Ve chvíli, kdy se totiž rozhodnu, že chci mít v těch boxech padding jiný než v procentech, jsem ve standardním boxmodelu bez šance. Abych se totiž vešel do sta procent, musel by se součet šířek a součet paddingů rovnat sto procent, což už logicky nelze dosáhnout jinak, než že budu mít všechny rozměry (včetně paddingů) v procentech. To není takový problém, dokud ovšem nutně nepotřebuji udat nějaký padding v pixelech. Například pokud bych chtěl mít oba bloky odděleny nějakým okrasným obrázkem o šířce 20 pixelů a chtěl tak dát tomu pravému bloku padding-left:20px, už bych se stoprocentní šířky v životě nedopočítal. Jednodušší příklad se dá vymyslet s okrajem. Chtěl bych-li dát jednomu z těch bloků border, klidně i jeden pixel, jsem bez šance, protože celková šířka bloku bude v tu chvíli 100% + 1px. Naproti tomu v nestandardním box-modelu si mohu s různými jednotkami hrát jak chci:

*{
margin:0;
padding:0;
-moz-box-sizing: border-box;
box-sizing: border-box

}
#levy{
width:30%;
float:left;
background:green;
padding:0 20px;
border-right:2px solid black;

}
#pravy{
width:70%;
float:right;
background:red;
padding:0 1em;
border-left:2px solid blue;

}

Můžete si též prohlédnout příklad. Ve standardním box-modelu jsem nucen do dvou bloků levy a pravy zanořit další blok, abych docílil stejného efektu. Výsledné CSS by tedy ve standardním box-modelu muselo vypadat takto:

*{
margin:0;
padding:0;

}
#levy{
width:30%;
float:left;
background:green;
}
#pravy{
width:70%;
float:right;
background:red;

}
#levy-vnoreny{
padding:0 20px;
border-right:2px solid black;
}
#pravy-vnoreny{
padding:0 1em;
border-left:2px solid blue;
}

Opět si můžete příklad prohlédnout naživo. Do HTML kódu jsem byl nucen přidat dva další zbytečné bloky, které bych při použití nestandardního box-modelu použít nemusel. Ovšem s tímto souvisí i jistá zajímavost. Všimněte si, jak se v druhém případě počítá padding. Standardně se počítá tak, že se přičítá k šířce. Ovšem ve chvíli, kdy je blok roztáhnutý na 100% šířky (což jsou právě ty dva vnořené bloky levy-vnoreny a pravy-vnoreny, které mají 100% šířku rodičovského prvku), se již padding nepřičítá k šířce, protože by se tam nevlezl, ale snižuje šířku prvku, na který je aplikován. V tuto chvíli se tedy standardní box-model chová prakticky úplně stejně jako nestandardní box-model. Neroztáhne okraj mimo blok, ale naopak sníží velikost bloku (i když zmenší zároveň jeho šířku, což se u nestandarního neděje – výsledek je ovšem totožný). Tedy stručně řečeno, pokud chci nějakému bloku dát padding, který je určen jinými jednotkami, než šířka elementu, musím ve standardním box-modelu zanořit další blok a nastavit padding až zde – tento padding potom sníží šířku bloku, čímž vlastně pouze záměrně simuluji nestandardní box-model (padding a width v podstatě jedno jest).

Příkladů na kolize, pokud nepoužívám stejné jednotky by se daly vymyslet spousty, ale všechny by byly prakticky stejné. Zkrátka v nestandardním box-modelu nejsem nucen používat stejné jednotky a mohu si zvolit jaké chci bez toho aniž bych musel používat nějaké pomocné vnořené elementy. Schválně si někdy zkuste použít nestandardní box-model, neříkám, že musí každému sednout (mně sedl), ale alespoň to zkuste. Říkat, že vám standardní box-model vyhovuje, když jste nezkusili ten opačný není zrovna košer :-). Kompatibilita je zaručena, neboť všem současným prohlížečům lze box-model přenout: -moz-box-sizing: border-box pro Firefox a box-sizing: border-box pro Operu. llook ještě zmiňoval -khtml-box-sizing:border-box pro prohlížeče založené na KHTML. Navíc v návrhu CSS3 již vlastnost box-sizing je, takže lze očekávat, že i budoucí prohlížeče budou tento box-model znát.