CSS2 – pozicování elementů

22. ledna 2003

Jedním z hlavních nedostatků původního HTML a CSS byl fakt, že autoři stránek měli pouze minimální možnost ovlivnit přesné umístění určitého elementu. Proto byly postupně v prohlížečích implementovány nové vlastnosti, které umožňovaly přesné pozicování. Pro množinu těchto vlastností se vžilo označení CSS-P (CSS-Positioning).

Konzorcium W3C na tuto situaci reagovalo, standardizovalo tyto vlastnosti a

V CSS2 si můžeme vybrat ze tří schémat pozicování (position scheme). Může to být normální tok (normal flow), absolutní pozicování (absolute positioning) a plovoucí boxy (floats). Konkrétní schéma se určuje pomocí vlastností position a float.

Definice pojmů

Před dalším výkladem si musíme vysvětlit dva důležité pojmy, „obsahující blok“ (containing block) a „viewport“ (vie wport).

„obsahující blok“

Mluvíme-li o „obsahujícím bloku“ daného elementu, obecně tím myslíme nejbližší rodičovský blok (blokový element), ve kterém je umístěn. Existují však přesná pravidla volby obsahujícího bloku. Pro popis absolutního pozicování je nutno pochopit následující:

  • Pokud není daný element absolutně pozicovaný (tj. nemá hodnotu vlastnosti position nastavenou na jednu z absolute, fixed), jeho obsahující blok je tvořen nejbližším rodičovským blokovým elementem.
  • Obsahující blok kořenového elementu jazyka (v XHTML element body) vytváří přímo prohlížeč. V následujícím textu jej budu nazývat základní obsahující blok (initial containing block).
  • Pokud je element pozicován absolutně, stává se jeho obsahujícím blokem nejbližší rodičovský element, který má vlastnost position nastavenou na jakoukoli jinou hodnotu než static. Pokud tento požadavek žádný rodičovský element nesplňuje, stává se jeho obsahujícím blokem základní obsahující blok.

V normě jsou tato pravidla ještě o něco komplikovanější, tento výčet však bohatě stačí pro použití pozicování v praxi. Na příkladě následujícího fragmentu XHTML kódu se pokusím ilustrovat, jak je určován obsahující blok různých elementů:

<body>
  <div>
    <p><strong>Toto je text <em>odstavce</em>.</strong></p>
  </div>
</body>

V tabulce je výčet všech použitých elementů společně s jejich obsahujícími bloky:

obsahujícího bloku

element jeho obsahující blok
body základní obsahující blok
div body
p div
strong
p
em p

Obsah předchozí tabulky se přesně řídí uvedenými pravidly. Element body je kořenovým elementem dokumentu a jako takovému je přidělen základní obsahující blok přímo prohlížečem. Obsahujícím blokem elementu div je nejbližší rodičovský blokový element, v tomto případě body. Stejným pravidlem jsou určeny i bloky ostatních elementů.

Nyní však chtějme absolutně pozicovat tyto elementy: div, em: {position: absolute;}. Tabulka obsahujících bloků se změní následovně:

element jeho obsahující blok
body základní obsahující blok
div základní obsahující blok
p div
strong p
em div

I tentokrát malé vysvětlení. Element div je pozicován absolutně. Protože nemá žádného absolutně pozicovaného rodiče, jeho obsahující blok vytváří přímo prohlížeč. Obsahující blok absolutně pozicovaného elementu em tvoří nebližší pozicovaný rodič, v tomto případě právě element div.

viewport

Tento výraz ponechám v jeho anglické verzi. Jednoduše se jedná o část obrazovky, na které je dokument zobrazován. Podíváme-li se na klasický prohlížeč, tak celé okno se skládá z menu, tlačítek, adresové řádky a právě viewportu, ve kterém se vykresluje požadovaný obsah.

Normální tok

Schéma normálního toku je prohlížeči nejpřirozenější. Jednoduše zobrazuje obsahy jednotlivých elementů, jak jdou za sebou (blokové elementy pod sebe, řádkové vedle sebe). To tedy znamená, že autor nemá žádnou možnost ovlivnit, kde přesně se daný element zobrazí. Toto schéma je pro prohlížeč výchozí, pokud chceme jeho použití zdůraznit, provedeme to zápisem position: static.

I přes tuto zdánlivou triviálnost existují „kouzla“, která můžeme s elementem v normálním toku provádět. Této magii se říká relativní pozicování (relative positioning). Elementu jej nastavíme hodnotou position: relative. Umístění takového elementu se nastavuje vzhledem k jeho pozici v normálním toku. K tomu slouží čtyři vlastnosti top, bottom, left, right.

Obecně řečeno, tyto 4 vlastnosti vždy představují vzdálenost od něčeho. Od čeho konkrétně závisí na zvoleném typu pozicování (jak jsme si již řekli, v případě relativního pozicování je to vůči umístění v normálním toku). Vlastnost top specifikuje, o jakou vzdálenost je horní hrana elementu pod nějakou jinou horní hranou. Zcela obdobně bottom představuje vzdálenost dolní hrany nad nějakou jinou dolní hranou. Vlastnost left je vzdálenost levé hrany vpravo od nějaké jiné levé hrany a konečně right reprezentuje vzdálenost pravé hrany elementu vlevo od jiné pravé hrany.

Nyní konkrétně pro relativní pozicování. Souřadnice left, top značí vzdálenost od levého horního rohu. Chceme-li nějaký element posunout vůči původnímu umístění jeho levého horního rohu o 7 px doprava a 10 px dolů, použijeme zápis left: 7px; top: 10px; Samozřejmě lze použít i záporné hodnoty, které posunou levý horní roh v opačném směru.

Zcela obdobně souřadnice right, bottom představuje vzdálenost od pravého dolního rohu. Tedy chceme-li posunout element o 4 px doleva a 8 px nahoru vůči původnímu umístění pravého dolního rohu, nastavíme right: 4px; bottom: 8px;.

Pro souřadnicové vlastnosti lze použít i procentuální hodnoty, které se vztahují k výšce a šířce obsahujícího bloku. Platí však pravidlo, že výška tohoto obsahujícího bloku musí být přesně zadána pomocí vlastnosti height, jinak se k ní vztahující procentuální hodnota bere jako dopočítávaná hodnota auto.

Představme si toto pozicování následujícím způsobem. Prohlížeč nejdříve vykreslí všechny elementy jako při normálním toku. Poté posune relativně pozicované elementy vůči jejich původním pozicím. Ostatní elementy zůstanou na svých místech, takže může dojít k jejich překrytí. Zároveň je však relativně pozicovaný element součástí normálního toku, takže na místě, kde byl původně, zůstane volná plocha.

  IE6 Opera 6.05 Mozilla 1.1
position: relative x x x

Absolutní pozicování

Při absolutním pozicování je element vyjmut z normálního toku, takže se na jeho místo může posunout obsah dalšího elementu. Pokud hovoříme o absolutně pozicovaném elementu, znamená to, že jeho vlastnost position má jednu z hodnot absolute, fixed. Na základě těchto hodnot prohlížeč rozlišuje, vůči čemu je daný element pozicován. V následujících odstavcích si vysvětlíme obojí chování.

Pozice vůči obsahujícímu bloku

Pokud chceme element umístit vůči jeho obsahujícímu bloku, nastavíme mu position: absolute. Přesnou pozici opět nastavíme vlastnostmi top, bottom, left, right, které se tentokrát vážou na příslušné strany obsahujícího bloku.

Souřadnice left, top v tomto případě znamená, o kolik vpravo a dolů se levý horní roh elementu zobrazí oproti levému hornímu rohu obsahujícího bloku. Například left: 5px; top: 10px; znamená umístění o 5 px vpravo a 10 px dolů vůči rohu obsahujícího bloku.

Zcela analogicky souřadnice right, bottom představuje vzdálenost pravého dolního rohu ve směru vlevo nahoru od pravého dolního rohu obsahujícího bloku. Styl right: 7px; top: 4px; značí vzdálenost o 7 px vlevo a 4 px nahoře od rohu obsahujícího bloku.

Pozice vůči viewportu

Chceme-li element umístit vůči viewportu, přiřadíme mu styl position: fixed (v dalším textu budu toto pozicování označovat jako fixní). Přesné umístění mají opět na starost čtyři snad už důvěrně známé vlastnosti top, bottom, left, right. Důležité je chování fixně pozicovaného elementu při scrollování. Zůstává totiž neustále na obrazovce na stejném místě vůči viewportu. Toto je velmi důležitý poznatek. Představte si například layout pomocí CSS. Element představující menu může být umístěn fixně, takže i při scrollování zůstane menu pořád na svém místě. Bez javascriptu. Zajímavé je i chování takového elementu na stránkových médiích (tiskárna). Měl by být vytištěn na každé stránce vždy v neměnné pozici.

Porovnání a malý příklad

Ačkoli se to na první pohled možná nezdá, má pozicování vůči obsahujícímu bloku a viewportu mnoho společného. Při obou je daný element kompletně vyjmut z normálního toku a vůči něčemu někam umístěn.

Při absolutním pozicování position: absolute budete nejčastěji pozicovat vůči základnímu obsahujícímu bloku. Málokdy se vám asi povede, abyste měli absolutně pozicovaný element uvnitř nějakého jiného pozicovaného elementu (který by se tak stal obsahujícím blokem). Uvědomme si ale, co to vlastně ten základní obsahující blok je. Jde o nějaký obdélník, který poskytuje sám prohlížeč. Nepřipomíná vám to náhodou něco? Samozřejmě, něco podobného je i viewport. Nějaký obdélník, ve kterém se dokument zobrazuje. Co se týče implementace v prohlížečích, viewport i základní obsahující blok jsou totéž.

Co z toho tedy vyplývá? Ať už pozicujete vůči základnímu obsahujícímu bloku nebo vůči viewportu, ve skutečnosti umisťujete objekt v obou případech vůči jednomu a tomu samému obdélníku, ve kterém je v prohlížeči dokument zobrazen. U fixního umístění máte však tu výhodu, že element stále zůstává na tom samém místě i pří scrollování.

Nyní spíše z cvičných důvodů uvedu malý příklad CSS layoutu pomocí absolutního pozicování. Pro kritiky předem zdůrazňuji, že jde skutečně pouze o cvičný příklad bez nároku na jakoukoli optimalizaci.

Naše stránka se skládá z jednoduchého menu vlevo a samotného obsahu vpravo. Na menu navíc kladu požadavek, aby bylo neustále na obrazovce. Menu bude představováno elementem div#menu a obsah div#obsah. Stylesheet bude vypadat následovně:

#menu
{position: fixed;
left: 10px;
top: 10px;
width: 200px;}
#obsah
{position: absolute;
left: 215px;
top: 10px;}

Samotný XHTML dokument bude prostý:


<body>
  <div id=“menu“>…menu…</div>
  <div id=“obsah“>…obsah dokumentu…</div>
</body>

Věřím, že další popis již není potřeba. Ukázka bude bezchybně chodit v Opeře 6.05 a Mozille 1.1, IE6 bude mít bohužel problémy díky absenci podpory fixního pozicování. Nejsou to však problémy natolik velké, aby nešly překonat a vy tak nenabídli uživatelům Opery a Mozilly malý nadstandard.

  IE6 Opera 6.05 Mozilla 1.1
position: absolute x x x
position: fixed x x

Pokud IE6 narazí na zápis position: fixed, čte jej jako position: static, tedy jako umístění v normálním toku. Pokud tedy vytváříte CSS layout i pomocí fixního umístění, vždy se musíte ujistit, kde se nakonec daný element zobrazí v Exploreru.

Plovoucí boxy

Nyní je čas se podívat na třetí zbývající schéma pozicování, na plovoucí boxy. Pro identifikaci tohoto schématu se používá na začátku zmíněná vlastnost float.

Obecně je plovoucí box blokový element, který je posunut úplně vlevo (respektive úplně vpravo) až k samotnému okraji obsahujícího bloku. Pokud před dosažením levého (pravého) okraje narazí plovoucí box na jiný plovoucí box, zastaví se a nepřekryje ho. Plovoucí box je sice vyjmut z normální toku, ale obsah samotného obsahujícího bloku jím není překryt, obtéká ho. O tom, jestli je plovoucí box umístěn vlevo nebo vpravo v obsahujícím bloku, rozhoduje vlastnost float, která může nabývat hodnot left, right. Pokud vlastnosti float nějakého elementu přiřadíte jednu z těchto dvou hodnot, je automaticky považován za plovoucí box. Naopak implicitní hodnota none znamená, že element je klasickou součástí normálního toku.

Pro plovoucí boxy platí také určitá pravidla. Automaticky se stávají blokovými elementy a dle normy musí mít explicitně stanovenou šířku (ve skutečnosti toto prohlížeče nevyžadují).

Jak jsem řekl, plovoucí box je obsahem stránky obtékán. Tomuto obsahu můžeme vlastností clear zakázat obtékání plovoucích boxů z určité strany. Hodnoty mohou být následující:

  • left – zakáže obtékání boxů umístěných vlevo
  • right – zakáže obtékání boxů umístěných vpravo
  • both – zakáže obtékání
  • none – povolí obtékání

Je-li vlastnost clear aplikována na element tvořící obsahující blok nějakého plovoucího boxu, nemá žádný efekt. Jinak řečeno, plovoucí box je vždy obtékán alespoň svým obsahujícím blokem. O tom, jestli může být obtékán i dalšími elementy, rozhoduje hodnota vlastnosti clear.

Nyní uvádím příklad stylesheetu dokumentující všechny výše uvedené vlastnosti a pravidla týkající se plovoucích boxů:

p {clear: left;}
span
{float: left;
width: 150px;
border: 1px solid red;}

Po aplikaci tohoto stylu by vzhled fiktivního dokumentu vypadal takto:

Podívejme se na toto formátování. První odstavec v sobě obsahuje plovoucí box (s červeným okrajem). Plovoucí box je umístěn doleva, takže je posunut až k levému okraji svého obsahujícího bloku. Zároveň však obsah plovoucího boxu zasahuje do následujícího odstavce, který je posunut až pod něj, protože má zakázáno obtékat vlevo umístěné plovoucí boxy vlastností clear. Tato vlastnost ovšem nemá žádný vliv na obsahující blok plovoucího boxu, a proto první odstavec normálně plovoucí blok obtéká.

Třetí rozměr dokumentu a vztahy mezi vlastnostmi

Nyní již jen ve zkratce. Při pozicování se může stát, že obsah jednoho elementu překryje obsah jiného. Viditelný je logicky ten, který je v dokumentu uveden později. Toto chování můžeme ovlivnit vlastností z-index, která nabývá hodnoty větší nebo rovné nule, přičemž platí, že element s vyšší hodnotou z-index překryje elementy s nižší hodnotou. Pokud se setkají dva elementy se stejnou hodnotou, zobrazí se klasicky ten, který je v dokumentu uveden později.

Při pozicování se určitým způsobem ovlivňují vlastnosti display, position, float. Následující pravidla toto chování jasně popisují:

  • Pokud je display nastaven na none, prohlížeč musí ignorovat hodnoty vlastností position, float.
  • Pokud je element absolutně pozicovaný (position: absolute, fixed), hodnota display je automaticky nastavena na block a float na none.
  • Pokud má vlastnost float jinou hodnotu než none, vlastnost display je nastavena na block a element se považuje za plovoucí box.
  • V jiném případě je aplikována hodnota vlastnosti display.

  IE6 Opera 6.05 Mozilla 1.1
float x x x
clear x x x
z-index x x x

Příštím článkem, ve kterém zabrousíme mezi nepříliš známá zákoutí CSS2, se s touto normou rozloučíme.

Starší komentáře ke článku

Pokud máte zájem o starší komentáře k tomuto článku, naleznete je zde.

Štítky: Články

Mohlo by vás také zajímat

Nejnovější

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *