CSS využívá při vykreslování dokumentu algoritmus, na jehož základě vytváří vizuální prezentaci dokumentu. Ten se skládá z tzv. bloků. Blok je čtyřhranný objekt, jenž se skládá z několika částí a který hraje důležitou úlohu při vykreslení elementu na stránku. Tento blok popisuje množství místa, které element na stránce zabere.

Základ rozložení obsahu na webu je zakořeněn v box modelu. Ten popisuje obdélníková pole, která jsou generována pro všechny prvky ve stromu dokumentu (DOM). Tento jev má na starost vykreslující modul prohlížeče.

Můžeme vlastně brát jako fakt, že každý HTML element v dokumentu je obdélník – tedy box. Jak je vidět na obrázku, obsah (content) je obalen třemi oblastmi, které mají dané pořadí a jejichž vlastnosti je možné měnit s pomocí CSS: padding, border a margin.

Tyto oblasti jsou vždy součástí každého prvku v dokumentu, i když nejsou ve stylopisu definovány. V tu chvíli mají nulové, respektive žádné hodnoty.

Každé z těchto vlastností včetně obsahu (content) můžeme nastavit rozměr, typ, pozicování, vztah k jiným elementům nebo přidat externí informaci.

Jednotlivé oblasti

Jednotlivé oblasti lze stručně popsat.

Content

Uvnitř ohraničení této oblasti se nachází vlastní obsah prvku. Může to být text, obrázek, video nebo jakýkoliv jiný element v dokumentu. Jak šířku, tak výšku udává velikost obsahu. S obsahem lze manipulovat pouze v případě pseudo elementů.

Content

Padding

Vnitřní okraj prvku (padding) vyhrazuje prostor okolo obsahové oblasti (content) až po oblast ohraničení (border). Padding je tedy odsazení uvnitř prvku samotného.

Padding

Border

Jedná se o ohraničení prvku (border), které se nachází mezi oblastí vnitřního okraje (padding) a vnějšího okraje (margin). Používá se k dekoraci ohraničení a je možné tuto oblast vizuálně upravovat a nastavovat její podobu.

Border

Margin

Tato oblast vnějšího okraje (margin) rozšiřuje prostor okolo prvku, počínaje prostorem od ohraničení (borderu). Jedná se o prázdný prostor, který se používá k oddělení jednoho prvku od druhého.

Margin

Jak rozlišit a používat jednotlivé oblasti

U oblasti content nebo border dojde málokdy k záměně. V prvním případě jde o obsah prvku a v druhém o jeho ohraničení. Často ale vzniká nepochopení v použití vnitřního a vnějšího odsazení.

Obě vlastnosti (paddingi margin) slouží k vytváření prázdného prostoru kolem obsahu prvků a může být proto snadné je zaměnit nebo nebrat jejich rozdílné chování v potaz. Rozdíl je v metodě, jakou se mezery vytváří a k jakému použití slouží.

Padding

Padding neboli vnitřní odsazení nám definuje, jakou vzdálenost si má prvek vymezit mezi obsahem (content) a ohraničením (border). Využívá se pro odsazení prvků v kontejnerech, pro vnitřní odsazení textu u prvků s nastaveným pozadím nebo pro zvětšení prvku samotného – např. u tlačítek.

p {
  padding: 10px;
}
Padding

Margin

Margin neboli vnější odsazení je osobní prostor prvku. Margin se využívá v případech, kdy chceme mít kolem prvku prázdný prostor – požadujeme, aby se prvek odsadil od těch okolních. Využití může také najít pro zarovnání uvnitř elementu ve vertikálním a horizontálním směru (hodnota auto). A na rozdíl od všech předchozím vlastností, margin nemá efekt na rozměry box modelu.

p {
  margin: 10px;
}
Margin

Margin má navíc i další specifické chování: jeho vertikální hodnoty se v určitých případech slučují. Tomuto chování se říká margin collapsing.

Margin collapsing

Margin neboli vnější okraj má oproti vnitřnímu okraji (paddingu) jedno specifické chování. Pro toto chování existuje v angličtině spojení margin collapsing. Do češtiny bychom to mohli přeložit jako slučování okrajů.

Kdy ke slučování dochází

Definujme si, kdy k tomuto chování dochází. Sloučení vnějších okrajů dvou elementů nastane v případě, že jsou splněny tyto podmínky:

  • jedná se o blokové elementy,
  • jedná se o horní nebo dolní okraje (na horizontální okraje se sloučení neaplikuje),
  • elementy se ve struktuře nachází ve stejné úrovni struktury DOM a neleží mezi nimi žádný oddělující obsah, nebo jsou elementy ve vztahu rodič – potomek a mají definováno vnitřní odsazení nebo ohraničení,
  • na prvek není aplikována vlastnost float,
  • prvky nemají nastavené absolutní pozicování.

Na stránce MDN najdete ještě podrobnější popis případů, kdy ke slučování dochází.

Proč ke slučování dochází

Slučování je navrženo tak, aby bylo snadné definovat vertikální okraje pro více elementů jdoucích v obsahu za sebou.

Toto chování se hodí například při návrhu blogového článku, kde jsou umístěny různé prvky, u kterých chceme mít sjednocené odsazení. Obrázky, tabulky, nadpisy, odstavce a další elementy tak mohou mít stejné vnější odsazení bez ohledu na to, v jakém pořadí jdou za sebou. Díky tomu nemusíme definovat odsazení pro jednotlivé kombinace.

Jak slučování funguje

Stručně můžeme říct, že ke sloučení okrajů dochází, pokud se dva vertikální okraje (horní a dolní) dostanou do vzájemného kontaktu. Potom dochází ke sloučení a je aplikována pouze větší hodnota odsazení. Můžeme si to představit jako souboj dvou vnějších okrajů, kde vyhrává ten, který je větší:

Margin collapsing – různé hodnoty

Pokud jsou hodnoty odsazení u obou prvků stejné, zůstane pouze jeden, respektive se obě hodnoty sloučí do jedné:

Margin collapsing – stejné hodnoty

Převaha odsazení rodičovského prvku

Ke sloučení taky dochází u prvků, kde má jejich nadřazený element definován vnější okraj ve svislém směru stejně tak jako prvky uvnitř. V tomto případě ale záleží, jaké mají prvky uvnitř vlastnosti.

Pokud mají prvky uvnitř rodičovského elementu nastavenou vlastnost vnitřního okraje (padding) nebo ohraničení (border), vnější odsazení se nebude slučovat. Prohlédněte si příklad na CodePen, kde je u vnořených elementů nastaveno vnitřní odsazení.

Záporné hodnoty

U záporných hodnot vnějšího odsazení funguje slučování stejně. Musíme si jen dát pozor na výpočet.

Pokud je jedna hodnota vnějšího odsazení záporná, odečte se od kladné hodnoty. Pokud máme tedy nastaveno dolní odsazení (margin-bottom) na -50px a následuje prvk s horním odsazením (margin-top) 100px, výsledná hodnota odsazení bude po sloučení 50px. Tento příklad si můžete opět vyzkoušet na CodePen.

Stejný princip se použije i v případě, kdy slučujeme dvě záporná odsazení. Opět se po sloučení aplikuje vyšší (v tomto případě „zápornější“ nebo lépe absolutní) hodnota.

Box Sizing

box-sizing neboli vlastnost, která definuje způsob výpočtu šířky (width) a výšky (height) prvku, je v prohlížečích defaultně nastavena na hodnotu content-box. Existuje však ještě jedna hodnota, která mění chování výpočtu velikosti prvku: border-box. Historicky se ve specifikaci objevila také hodnota padding-box, která ale byla časem odebrána a v dnešní specifikaci již neexistuje. Ta počítala velikost boxu součtem oblastí contentpadding, tedy bez rámečku – border.

Content-Box

Výpočet šířky a výšky prvku je dán součtem oblastí content, paddingborder. Vlastnost margin nemá vliv na výslednou velikost jednotlivých prvků.

Znamená to, že pokud je nastavena šířka a výška prvku, hodnoty vlastností paddingborder nám rozšíří celkovou velikost boxu o jejich hodnoty. Toto chování odpovídá nastavení CSS vlastnosti box-sizing: content-box.

Původně definované rozměry prvku se zvětšily o hodnoty vlastností padding a border.

Border-Box

U tohoto typu modelu se definovaná šířka a výška rovná výsledné velikosti boxu, a to bez ohledu na hodnoty vlastností padding nebo border. Vlastnost margin opět nemá vliv na výslednou velikost prvku. Toto chování odpovídá nastavení CSS vlastnosti box-sizing: border-box.

Původně definované velikosti prvku zůstávají stejné, i když máme nastavený border i padding.

Nastavení box modelu

V dnešní době se ukazuje nastavení jednotného box modelu pro všechny elementy jako nejlepší možné řešení. A je pro to jednoduché vysvětlení. Se všemi prvky na webu se pracuje stejně, a tak je jejich chování napříč celým dokumentem konzistentní.

Navíc nástroje pro tvorbu webového designu pracují s jednotlivými prvky stejně, což usnadňuje spolupráci mezi designerem a kodérem. Dekorace jako rámečky neovlivňují definované rozměry prvků a stejně tak by se měly chovat i prvky na výsledném webu.

Doporučené bývá nastavení vlastnosti box-sizing na hodnotu border-box. To je přímočaré a intuitivní, ovšem toto pravidlo musíme ve stylopisu nastavit ručně, protože kvůli zpětné kompatibilitě stále zůstává výchozím nastavením hodnota content-box.

Existují však výjimky, kdy se pro vlastnost box-sizing doporučuje nastavit hodnotu content-box. Toto nastavení nám u relativního nebo absolutního pozicování zaručí, aby byly hodnoty pro nastavení pozicování relativní k obsahu, nezávislé na změnách rámečku nebo odsazení.

Do základního stylopisu se tak přidává následující pravidlo, které je dnes již běžnou praxí:

*, *::before, *::after {
  box-sizing: border-box;
}


Jon Neal přišel s jistou alternativou, která se zdá být také k zamyšlení. Namísto resetování vlastnosti box-sizing na border-box u všech prvků ji nastavuje jen kořenovému prvku dokumentu. Pro ostatní prvky využívá hodnotu inherit, která umožní vlastnost box-sizing zdědit:

html {
  box-sizing: border-box;
}

*, *::before, *::after {
  box-sizing: inherit;
}

Může se to hodit v případě, kdy navrhneme komponentu, u které předpokládáme chování výchozího nastavení box-sizing: content-box, stejně tak jako u prvků vložených uvnitř. Tím můžeme zamezit nežádoucímu rozbití vnořených komponent.

Shrnutí

Zdroje: