www.pixy.cz


Zarovnávání prvků pomocí CSS

Zarovnávání bloků, často prováděné pomocí konstrukcí typu tabulka v tabulce, je často zmiňováno jako jedna z hlavních potíží formátování s CSS. Trápí mnoho z těch, kteří chtějí předělat své stránky do čisté struktury pouze s CSS. Je ale nutno podotknout, že CSS jsou velmi mohutný nástroj a mnoho funkcí je v nich ukryto bez povšimnutí. S kaskádovými styly lze docílit lecčeho, jediným omezením může být pouze nedostatečná či dokonce špatná implementace CSS v prohlížečích.

Zarovnávat musíme vždy něco vůči něčemu - potřebujeme tedy alespoň dva prvky, abychom o nějakém vzájemném zarovnávání mohli mluvit. Obecně si můžeme rozdělit zarovnání na dvě skupiny: dva sousedící prvky a jeden prvek uvnitř druhého.


1. Dva sousedící prvky

Dva prvky pod sebou - vodorovné zarovnávání

Vodorovné zarovnání řádkových prvků

Všechny řádky v bloku budou zarovnány podle hodnoty jeho vlastnosti text-align. Možnými hodnotami jsou left (zarovnání levých hran), right (zarovnání pravých hran), center (zarovnání středů řádek na osu bloku) a justify (zarovnání levých i pravých hran, obsah je roztažen, aby vyplnil celý řádek).

Vodorovné zarovnání blokových prvků

Hrany bloků se zarovnávají podle hodnot margin-left a margin-right. Pokud je jejich hodnotou auto, okraj (margin) se dopočítává tak, aby blok vyplnil celou danou šířku. Pokud mají hodnotu auto oba dva okraje, musí být stejné (blok tedy bude vystředěn na ose).

Chceme-li zarovnat levé hrany dvou následujících bloků, musíme jim nastavit stejný levý okraj (třeba nulový) a oběma shodně dát margin-right:auto. Budou-li mít naopak margin-left:auto, budou zarovnány jejich pravé hrany. A konečně, budou-li oba mít margin-left:auto i margin-right:auto, budou oba bloky zarovnány na osu.

Korektní výpočet okrajů z hodnoty auto nepodporují některé starší prohlížeče (např. MSIE do verze 5.5). Ty však zase chybně zarovnají pomocí text-align nejen text, ale i bloky. Můžeme tedy obě metody zkombinovat - mateřskému prvku nastavíme potřebnou hodnotu text-align, např. right. Starší prohlížeče zarovnají vnitřní bloky doprava. Pro novější prohlížeče všem vnitřním blokům dáme margin-right:auto a margin-right všem nastavíme na stejnou hodnotu.

Dva prvky vedle sebe - svislé zarovnávání

Za normálních okolností vedle sebe mohou ležet pouze řádkové prvky. Pro jejich zarovnání má CSS poměrně mohutný nástroj - vlastnost vertical-align. Má množství možných hodnot, které prvky zarovnají na účaří textu, horní či dolní hranu jejich rámu, na střed atd.

V CSS2.1 sice existuje typ prvku inline-block, jehož obsah se formátuje jako blok, ale prvek samotný jako řádkový - bohužel zatím je podporován jen sporadicky (pokud vím, tak pouze v MSIE5/Mac). Až bude všeobecně rozšířen, bude to opravdu silný nástroj na svislé zarovnávání bloků.

Existují ještě dva specifické případy, kdy se prvky mohou nacházet vedle sebe. Prvním jsou plovoucí prvky, zde však pro zarovnávání platí zcela jiná pravidla, navíc je obtékaný prvek vklíněn do prvku obtékajícího - o vzájemném svislém zarovnání nemá smysl hovořit. A v případě absolutně pozicovaných prvků jejich pozici určujeme exaktně, poloha jednoho je naprosto nezávislá na poloze druhého. Jejich vzájemné zarovnání můžeme sami vypočítat a použít pro jejich pozici; pokud jejich vzájemnou polohu potřebujeme ošetřit až podle vykreslení na stránce, použijeme dynamické pozicování (např. Javascriptem). Při určitých specifických konstelacích lze použít i metodu obdobnou níže uvedenému zarovnání vnořených bloků.


2. Dva vnořené prvky

Z podstaty CSS i HTML plyne, že jsou možné dvě alternativy. Vnější prvek je blokový a vnitřní řádkový, nebo jsou oba blokové (blok uvnitř bloku).

Vodorovné zarovnávání

Platí zde stejná pravidla jako pro sousedící prvky. Vhodnou hodnotou vlastnosti text-align vnějšího bloku horizontálně zarovnáme všechen jeho řádkový obsah. Hodnoty auto levých a pravých okrajů zase zajistí zarovnání bloků uvnitř vnějšího prvku.

Svislé zarovnání

Protože výška bloku se obvykle přizpůsobuje výšce jeho obsahu (blok jej pevně obalí), můžeme hovořit pouze o vzdálenosti obsahu bloku od jeho rámečku. To ovlivňujeme hodnotami padding. Je-li padding-top nulový, obsah bude umístěn k hornímu okraji, je-li nulový padding-bottom, bude obsah u dolního okraje bloku. Budou-li horní i dolní padding stejné, obsah bude uprostřed rámečku.

Pouze ve specifickém případě, kdy je výška vnějšího bloku explicitně určena hodnotou vlastnosti height, se může pod obsahem vyskytnout prázdné místo. Tehdy můžeme chtít, aby byl vnitřní prvek umístěn v tomto prázdném prostoru jinde než u jeho horní hrany.

Řádkové prvky uvnitř bloku dané výšky

Z podstaty formátování řádkového obsahu nelze s celými řádky příliš vertikálně manipulovat. Řádkový obsah se dynymicky distribuuje do řádek, které jsou vykreslovány pod sebou - svisle se zarovnává jen jejich obsah. Pokud chceme řádky svisle zarovnávat v prostoru uvnitř bloku, je nejlepší uzavřít je do neutrálního bloku (např. <div>) a zarovnat blok v bloku.

Blokový prvek uvnitř bloku dané výšky

Pokud má i vnitřní blok danou výšku, zbývající prostor spočítáme a vhodně nastavíme horní a dolní padding vnějšího bloku. Pokud je ale tato výška automatická a pokud víme, že vnější prvek je dostatečně vysoký, můžeme vnitřní prvek ve volném prostoru umístit relativním pozicováním.

Relativní pozicování se používá k odsunutí prvku z jeho normální pozice (je vlastně zformátován normálně a teprve následně je podle velikostí top/bottom a right/left posunut na nové místo). Využijeme toho, že tyto vlastnosti mohou mít procentní hodnotu, která se vztahuje k rozměrům vnějšího prvku (tedy k rozměrům onoho prázdného prostoru, v němž se chceme pohybovat). Např. bude-li mít vnitřní prvek position:relative a top:50%, jeho horní hrana bude posunuta přesně do poloviny výšky vnějšího prvku.

Protože vnitřní blok je neznámé výšky, nemůžeme svislý posun sami spočítat. Jeho hodnota top se odkazuje na výšku vnějšího prvku. Pokud ale vnitřní prvek ještě uzavřeme do neutrálního bloku (např. <div>) s výškou auto, těsně obalí tento vnitřní prvek a bude mít tedy výšku jako on (musí mít ovšem nulový margin, padding i border). Procentní hodnota top vnitřního prvku se už bude odkazovat na výšku tohoto obalu (tedy vlastně na svoji vlastní výšku, protože jsou stejné). Pokud mu dáme position:relative a top:-50%, posune se o polovinu své výšky nahoru. Jeho střed se dostane na střed vnějšího prvku.

Příklad - vystředění bloku v bloku:
<div style="height:300px; overflow:hidden">
	<div style="width:100%; position:relative; top:50%">
		<p style="position:relative; top:-50%">
		Obsah prvku obsah prvku obsah prvku obsah prvku
		obsah prvku obsah prvku obsah prvku obsah prvku
		obsah prvku obsah prvku obsah prvku obsah prvku...
		</p>
	</div>
</div>

Bohužel již tradičně některé prohlížeče nepodporují některé funkce CSS korektně. V tomto případě Mozilla a MSIE5/Mac z jakéhosi důvodu nepoužijí druhé (vnořené) relativní pozicování pomocí procent. MSIE ve Windows to však zobrazí správně, ale prostřední blok musí mít zadanou šířku (pokud má width:auto, procenta v top jeho potomků se budou chybně vztahovat zase na rozměr vnějšího prvku. Podivné, ale je to tak...). Chybu v Mozille a podobných lze někdy obejít tak, že známe-li aspoň přibližně počet řádek vnitřního bloku, můžeme jej místo top:-50% posunout např. o top:-3em, což už bude fungovat.

Příklad - zarovnání vnitřního bloku na spodek vnějšího bloku:
<div style="height:300px; overflow:hidden">
	<div style="width:100%; position:relative; top:100%">
		<p style="position:relative; top:-100%">
		Obsah prvku obsah prvku obsah prvku obsah prvku
		obsah prvku obsah prvku obsah prvku obsah prvku
		obsah prvku obsah prvku obsah prvku obsah prvku...
		</p>
	</div>
</div>

Anglická verze a příklady (english version and examples).


Doufám, že zde byly pokryty všechny případy možného zarovnávání prvků - pokud jsem něco opomněl, dejte mi vědět.

Petr Staníček (pixy), 11. 9. 2002