Navigační menu pomocí CSS

Navigační menu pomocí CSS

1

Dnes si ukážeme, jak pouze pomocí CSS vytvořit navigační menu s roll-over efekty. Jedná se o oblast CSS, která je využitelná již v dnešních prohlížečích, proto byste si článek rozhodně neměli nechat ujít!

Nejprve zkonstruujeme základní menu, poté mu přidáme ještě jednu zajímavou vlastnost. První menu se nachází v prvním příkladě.

(X)HTML kód

Na stránku vložíme základní (X)HTML kód, který vytvoří jednotlivé odkazy. Tento kód poté odpovídajícím způsobem nastylujeme. Navigační menu je vlastně seznam odkazů, proto bychom měli využít elementy pro seznamy v (X)HTML:

<div id=“navigation“>
<ul>
  <li><a href=“#“>Webdesign</a></li>
  <li><a href=“#“>Vývoj aplikací</a></li>
  <li><a href=“#“>E-komerce</a></li>
  <li><a href=“#“>Nástroje</a></li>
  <li><a href=“#“>Magazín</a></li>
  <li><a href=“#“>Diskusní fórum</a></li&gt
</ul>
</div>

Celé menu uzavíráme do div(u) s názvem navigation – toho využijeme později v selektorech CSS. Na normálních stránkách by navíc měly odkazy někam vést.

Tento kód je velmi dobře srozumitelný pro jakýkoli prohlížeč podporující HTML, proto bude navigaci moci využít každý uživatel. Ti, kteří navíc používají moderní vizuální prohlížeč, uvidí efektní menu. K podpoře v prohlížečích se dostaneme později.

CSS definice

Nyní začneme přiřazovat CSS vlastnosti. Vždy si ukážeme kus definice a pak si k ní něco řekneme:

body {
  color: #000; background-color: #fff;
  font-family: „Verdana CE“, Verdana, sans-serif; line-height: 1.35;
  margin: 0; padding: 2.5em;
}

Nejprve nastavujeme vlastnosti celé stránky: barvy, okraje a druh písma. Všimněte si, že nenastavujeme velikost písma – celé menu bude mít relativní rozměry a nebude proto závislé na velikosti písma. To si můžete vyzkoušet v přiloženém příkladě tak, že změníte velikost písma v prohlížeči.

Tyto základní vlastnosti závisí pouze na vás. Vše můžete udělat podle svých konkrétních potřeb, můžete použít i pevnou velikost písma, protože menu se jí v takovém případě přizpůsobí. Pokračujeme dál:

div#navigation {
  color: #fff; background-color: #8eccfb;
  width: 13em;
  padding: 0.5em;
  voice-family: „\“}\““; voice-family: inherit;
  width: 12em;
}
div#navigation ul {
  background-color: #6caad9;
  margin: 0; padding: 0;
}

Zde již začínáme nastavovat vizuální vlastnosti menu. Není na nich nic k nepochopení, snad pouze to, že využíváme hacku špatného box-modelu v IE 5.x. Také zde musíme vynulovat okraje a vycpávky u elementu pro neuspořádaný seznam, protože ty jsou v prohlížečích poměrně živelně implicitně nastaveny.

Všechny rozměry nastavujeme pomocí relativní jednotky em. Ta se váže k velikosti písma elementu, proto může menu obsahovat jakkoli velké písmo (protože se vždy roztáhne na potřebnou velikost).

Všimněte si také, že vše nastavujeme pouze pro naše menu, a to pomocí selektorů vázaných na náš div pojmenovaný navigation. Můžeme tedy pokračovat dál:

div#navigation li {
  list-style: none;
  margin: 0; padding: 0;
}

Nyní přiřazujeme vlastnosti elementu li, který vytváří jednotlivé položky seznamu. Opět zde nulujeme okraje a vycpávky, navíc však zrušíme zobrazování seznamové odrážky pomocí vlastnosti list-style. V další definici se již věnujeme odkazům:

div#navigation a {
  color: #fff;
  font-size: 1em;
  text-decoration: none;
  display: block;
  border-left: 1em solid #6caad9; border-right: 1em solid #6caad9;
  width: 12em;
  padding: 0.35em 1em;
  voice-family: „\“}\““; voice-family: inherit;
  width: 8em;
}

Všechny odkazy předefinováváme na blokové prvky. Je to důležité kvůli tomu, abychom u nich mohli nastavit šířku (u řádkových elementů nemůžeme) a odkaz byl aktivní (tj. dalo se na něj kliknout) po celé šířce menu. Poté mu tedy nastavujeme šířku, přičemž musíme počítat s vadným box-modelem v IE 5.x.

Další vlastnosti jsou opět vizuální, chtěl bych zde zdůraznit pouze jednu, vlastnost font-size: 1em;. Asi se vám zdá, že je zde zbytečná, protože při použití pro nastavování velikosti písma se velikost jednotky em odvozuje od velikosti písma rodičovského elementu. Touto definicí totiž říkáme, že chceme stejnou velikost písma jako u rodičovského elementu. To je ale automatické, protože vlastnost font-size se dědí. Přesto je nutné ji použít, protože IE/Win do verze 6 špatně počítá skutečnou velikost jednotky em při nastavení velkých písem v prohlížeči a vykresluje jednotlivé položky kratší než by měly být. Pokud ale tuto vlastnost explicitně nastavíme, IE si vše správně „uvědomí“ a žádný problém nevznikne.

Nyní se postáráme o dynamické efekty menu:

div#navigation a:hover, div#navigation a:focus {
  background-color: #7dbbea;
  border-left: 1em solid #8eccfb; border-right: 1em solid #8eccfb;
}
div#navigation a:active {
  background-color: #ffb380;
  border-left: 1em solid #ffb380; border-right: 1em solid #ffb380;
}

Nejprve nastavujeme změnu stavu pro odkaz, nad kterým se nachází kurzor ukazovacího zařízení (většinou myši) pomocí pseudo-třídy hover. Takový efekt je ale vázaný právě na ukazovací zařízení, proto by o něj přišli uživatelé pohybující se po stránce pomocí klávesnice nebo jiným způsobem. Ty samé změny tedy nastavíme i pro pseudo-třídu focus, která se aktivuje v momentě, kdy má element tzv. fokus, např. při surfování pomocí klávesy TAB nebo při skákání z odkazu na odkaz ve hlasovém prohlížeči (ten samozřejmě nezobrazí naše vizuální efekty). V současné době podporuje pseudo-třídu focus pouze Mozilla/Netscape 6+ a IE 5/Mac, IE/Win do verze 6 aktivuje při fokusu pseudo-třídu active.

Pseudo-třídu active nastavuje druhé pravidlo, přičemž stejně jako u hover a focus dochází k barevným změnám pozadí a rámečků – u těch nemůžeme použít vlastnosti border-left-color a border-right-color, ačkoli dochází pouze k barevným změnám, protože Opera do verze 6 v takovém případě barvu rámečku nezmění.

Nyní by se mohlo zdát, že je již menu hotové. K úplné „dokonalosti“ mu ale něco chybí, a to je odlišení již navštívených odkazů. To je vcelku dost důležité, protože toto odlišení uživateli značným způsobem ulehčuje pohyb naším webem. Zvolil jsem matnější barvu textu:

div#navigation a:visited {
  color: #ddd;
}

Celé menu můžete samozřejmě nastylovat pomocí jiných vizuálních vlastností, kostra menu zůstává vždy stejná. Vizuální podobě jsem se tolik nevěnoval, šlo mi pouze o nastínění principu.

Naše menu by měl zobrazit správně každý prohlížeč s dobrou podporou CSS, bez problémů jsem ho testoval na IE 6/Win, Mozille/Netscape 6+ a Opeře 5+. IE 4/Win nemá problémy s efekty, ale menu nevypadá, tak jak má (je to hlavně kvůli zoufalému box-modelu v tomto prohlížeči), i přesto je však plně použitelné.

„Magický efekt“

Nyní se podívejte na druhý příklad. Připomínám, že se stále jedná pouze o XHTML + CSS, žádný JavaScript. Jedná o první menu, u něhož se při přejetí nad položkou zobrazí pod menu nápověda k ní.

Nápověda, která se pod menu objevuje, musí být součástí stránky. My ji umístíme do odkazů v menu, a to přímo za název položky (samozřejmě na tomto místě musí být nějaký oddělovač položky a jejího popisu pro prohlížeče bez podpory CSS). Podívejte se tedy na upravený (X)HTML kód:

<div id=“navigation-container“>
<div id=“navigation“>
<ul>
  <li><a href=“#“ title=“Webdesign&nbsp;– V této rubrice se věnujeme webdesignu.“>Webdesign<span>&nbsp;– </span><span class=“description“>V této rubrice se věnujeme webdesignu.</span></a></li>
  <li><a href=“#“ title=“Vývoj aplikací&nbsp;– V této rubrice se věnujeme vývoji aplikací.“>Vývoj aplikací<span>&nbsp;– </span><span class=“description“>V této rubrice se věnujeme vývoji aplikací.</span></a></li>
  <li><a href=“#“ title=“E-komerce&nbsp;– V této rubrice se věnujeme e-komerci.“>E-komerce<span>&nbsp;– </span><span class=“description“>V této rubrice se věnujeme e-komerci.</span></a></li>
  <li><a href=“#“ title=“Nástroje&nbsp;– V této rubrice se věnujeme nástrojům vhodným pro vytváření webů.“>Nástroje<span>&nbsp;– </span><span class=“description“>V této rubrice se věnujeme nástrojům vhodným pro vytváření webů.</span></a></li>
  <li><a href=“#“ title=“Magazín&nbsp;– V této rubrice se věnujeme ostatním tématům.“>Magazín<span>&nbsp;– </span><span class=“description“>V této rubrice se věnujeme ostatním tématům.</span></a></li>
  <li><a href=“#“ title=“Diskusní fórum&nbsp;– V této rubrice si můžete zadiskutovat.“>Diskusní fórum<span>&nbsp;– </span><span class=“description“>V této rubrice si můžete zadiskutovat.</span></a></li>
</ul>
</div>
</div>

Celý text jsme navíc umístili do atributu title u odkazů. To je důležité pro případ, kdy prohlížeč podporuje dobře CSS, ale neumí zobrazovat dynamicky nápovědu k položkám. Uživatel by v takovém případě o nápovědu přišel. Přesně takto se mj. chová Opera verze 6 a nižší, ale mohou to být i jiné, méně známé prohlížeče.

Popisné texty jsem uzavřel do elementů span. Těm uzavírajícím oddělovače jsem nepřiřadil žádnou třídu, nápovědným textům jsem přiřadil třídu description. Toho budeme opět využívat v CSS.

Celé menu jsme také uzavřeli ještě do jednoho div(u), s id="navigation-container". Jeho stylováním nyní začneme:

div#navigation-container {
  position: relative;
  width: 13em;
}

Jak vidíte, předefinováváme jeho pozici na relativní, ale nenastavujeme vlastnosti top, right, bottom ani left, což znamená, že se element neposune oproti svému normálnímu umístění, ale bude se od něj počítat absolutní pozice vnořených elementů. Toho využijeme při umísťování nápověd.

Další pravidla jsou stejná jako v prvním případě, ale nakonec přidáme tři, pomocí kterých nastylujeme nápovědné texty. První z nich je velmi jednoduché:

div#navigation a span {
  display: none;
}

Tímto zápisem zajistíme, že se skryjí oddělovače „&nbsp;– “. Toto pravidlo by ale samo o sobě skrývalo i nápovědné texty, proto u nich nastavíme display na jinou hodnotu. Přidáme ještě několik vlastností:

div#navigation a span.description {
  color: #fff; background-color: #ccc;
  font-size: 0.9em; font-style: italic;
  position: absolute; left: 0; top: 15.5em;
  display: block; visibility: hidden;
  width: 13.3em;
  border-top: 1px solid #bbb; border-bottom: 1px solid #bbb;
  padding: 0.38em 1.1em;
  voice-family: „\“}\““; voice-family: inherit;
  width: 12.2em;
}

Kromě mnoha vizuálních vlastností zde pozicujeme všechny nápovědy přesně pod menu (pozice se počítá od div(u) pojmenovaného navigation-container): každá položka má výšku 2.05 em (výška řádkového boxu = velikost písma 1 em × výška řádku 1.35 = 1.35 em, padding nahoře a dole 0.7 em) a je jich 6; padding u div#navigation nahoře a dole 1 em; zmenšujeme písmo na 0.9 em, a proto musíme hodnotu adekvátně přepočítat; něco přidáme na oddělení menu a nápověd a vyjde nám 15.5 em.

Po přepočítání nám také vyjde šířka 13.3 em, která by měla být stejná jako šířka menu a vycpávky po stranách 1.1 em, které by nám měly zajistit stejné odsazení textu jako u menu.

Dále uděláme pomocí vlastnosti display z implicitně řádkového elementu span blokový element (a zároveň tím zrušíme jeho skrytí), celý element navíc skryjeme pomocí vlastnosti visibility. Při přejetí myší nad položkou nebo při předání fokusu položce změníme hodnotu této vlastnosti na visible, čímž menu odkryjeme. Tato myšlenka je realizována pomocí následujícího zápisu:

div#navigation a:hover span.description, div#navigation a:focus span.description {
  visibility: visible;
}

Tímto zápisem doslova říkáme, že jakémukoli elementu span s třídou description nacházejícímu se uvnitř elementu a ve stavu hover/focus, který se nachází uvnitř div(u) se jménem navigation, se má změnit hodnota vlastnosti visibility na visible, tedy viditelný.

Tuto variantu menu podporují prohlížeče stejně jako v prvním případě, pouze Opera verze 6 a nižší skryje a již nezobrazí nápovědy, jak jsem již zmínil.

Na konec jenom poznamenám, že by bylo lepší použít pro skrývání nápověd vlastnost display, protože prvek skrytý pomocí visibility může reagovat na události (i když tomu zde tak není). IE/Win verze 6 a nižší má ale s display problémy, proto musíme použít visibility.

Dnes jsme si tedy ukázali, že i přes stále vcelku živelnou podporu náročnějších věcí z CSS, se již dají využít leckteré pokročilejší konstrukce. Ty nám mohou pomoci zefektivnit stránku (kratší a čistší kód) a zvýšit její přístupnost i použitelnost (nemusíme využívat obrázky ani JavaScript).

Doplněno a upraveno!

Po zveřejnění článku jsem objevil na popisovaných menu tři nedostatky, a to i díky čtenářům – těm za tuto podporu velmi děkuji.

Prvním z problémů je špatné zobrazení v IE 5/Win. To je způsobeno CSS box-model hackem (voice-family: "\"}\""; voice-family: inherit;), který v IE 5/Win zaviní ignorování pravidla následujícího za tím, kde je hack použit. Proto musíme dvě pravidla, která za hackem následují, zduplikovat – tzn. vložit dvakrát za sebou:


div#navigation ul {
 background-color: #6caad9;
 margin: 0; padding: 0;
}
div#navigation ul {
 background-color: #6caad9;
 margin: 0; padding: 0;
}

div#navigation a:visited {
 color: #ddd;
}
div#navigation a:visited {
 color: #ddd;
}

Při tomto zápisu již není problém v zobrazení prvního menu v IE 5/Win, IE 5.5/Win, IE 6/Win ani Mozille/NS6+ a Opeře 5+ (ve všech testováno).

Upravený příklad si můžete stáhnout.

Druhý problém nalezneme v druhém příkladě, a sice ve špatné pozici nápovědy pod menu. Tu pozicujeme pomocí jednotek em, které ale nemohou umístit nápovědu vždy pod menu, protože u ní nastavujeme menší písmo – při menších velikostech písma se potom nápověda zobrazí přes menu.

Řešením problému je vložit nápovědu do dvou spanů, přičemž prvnímu necháme stejnou velikost písma jako u menu a pozicujeme ho; u druhého potom písmo zmenšíme. Upravený příklad.

Poslední třetí problém je opět s IE 5/Win. Ten vůbec nezobrazuje nápovědy k menu v druhém příkladu. Řešením je přiřadit všechny vlastnosti span.description až když je odkaz ve stavu hover, navíc nesmíme u odkazů použít vlastnosti width ani height. Také musíme nápovědu skrývat pomocí vlastnosti display. Vzhledem k nemožnosti použít width a height je menu aktivní pouze při kurzoru myši nastaveném nad textem, ne nad celou položkou. Abychom tedy dosáhli správného zobrazení v IE 5/Win, musíme omezit zobrazení v ostatních prohlížečích, které podporují CSS lépe než IE 5/Win. Pokud tak chcete učinit, zde je upravený příklad.

Jak tedy vidíte, chyby jdou na vrub především špatnému zobrazování v IE 5/Win, na kterém jsem v době psaní článku menu netestoval. Na všech ostatních prohlížečích uvedených v článku a na IE 5.5/Win je zobrazení správné i u původních dvou příkladů – tedy až na nepřesné pozicování nápovědy, které zde zmiňuji.

Pozn. red.: Pokud vás problematika tvorby menu zaujala, doporučujeme vám seriál Dynamická menu v DHTML, také od autora tohoto článku.

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

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

1 Příspěvěk v diskuzi

  1. Začátek článku „Dnes si ukážeme, jak pouze pomocí CSS“ a já jásal, že to jde. No a hned potom čtu „(X)HTML kód“ – a já blbec myslel že jen pomocí css.

    Takže mám dotaz: Lze to jen pomocí css (tj. bez (X)HTML, javascript, php, …, ap.)? Nebo to nelze? Předem díky za odpověď.

Odpovědět