Menu item highlighting v jQuery

JavaScript Hotová řešení Menu item highlighting v jQuery

Velmi důležitá a často používaná věc je menu item highlighting, neboli zvýrazňování aktivní položky v menu. Používá se na fixním menu, jinak bychom samozřejmě efekt neviděli, kde vám ukazuje kde se právě nacházíte. Daná položka je pak nějak zvýrazněna, třeba barvou pozadí, barvou písma atp.

Jako vždy si uděláme základní kostru v HTML a JS souboru.

JS:

$(function(){

  ... kód ...

});

HTML:

<body>
<header>
   ... text ...
</header>

<div id="menu">
   <nav>
     <ul>
         <li><a href="#alfa" class="tlacitko"><span>ALFA</span></a></li>
         <li><a href="#beta" class="tlacitko"><span>BETA</span></a></li>
         <li><a href="#gama" class="tlacitko"><span>GAMA</span></a></li>
         <li><a href="#epsilon" class="tlacitko"><span>EPSILON</span></a></li>
         <li><a href="#zeta" class="tlacitko"><span>ZÉTA</span></a></li>
         <li><a href="#eta" class="tlacitko"><span>ÉTA</span></a></li>
     </ul>
   </nav>
</div>

<div id="main">
<section>
   <article id="alfa">
      ... dlouhý text ...
   </article>
   <article id="beta">
      ... dlouhý text ...
   </article>
   <article id="gama">
      ... dlouhý text ...
   </article>
   <article id="delta">
      ... dlouhý text ...
   </article>
   <article id="epsilon">
      ... dlouhý text ...
   </article>
   <article id="zeta">
      ... dlouhý text ...
   </article>
   <article id="eta">
      ... dlouhý text ...
   </article>
</section>

<aside>
   <div class="sticky">
      <p> ... text ... </p>
      <p> ... text ... </p>
   </div>
</aside>
</div>

<footer>
   ... text ...
</footer>
</body>

K tomuto si nezapomeňte přidat i smooth scrool, který najdete v předchodím dílu, zde. Bude to pak vypadat lépe.

Takže, nejdříve bych chtěl poukázat na chyby, kterých se lidé často dopouští.

  1. Kód píší tak, že si zjistí ručně souřadnice a ty pak porovnávají s scrollTopem, tzn. pokud je scrollTop větší než třeba 479, zabarvi toto. Opravdu, takto ne, to je snad nejhorší co se dá udělat. Jednak stačí dopsat 2 odstavce textu a už vám kód nebude fungovat a za druhé je s tím i strašně práce.
  2. Zjistí si jen offset().top jednotlivých article a ty porovnávají s scrollTopem. Všechno dělají po jednom - pomocí ifů - a řeší tedy jenom horní hranici, pokud sjedete tam, kde je obsah, který nemáte v menu, zabarvení zůstává.
  3. Po kliku na menu item se rovnou zabarví. Při scrollu na stránce se to nemění. Tady asi musím říci, že je to také dost špatné, jelikož když budete scrollovat, tak se vám pochopitelně nebude zvýraznění měnit, tudíž to není použitelné. Navíc to nevypadá hezky.

A jak by se to mělo dělat správně? No, určitě by se mělo dělat vše automaticky, snažte si automatizovat vše, musí se brát nejen začátek, ale i konec. To je velmi důležité, jelikož ne všechny části webu musíte mít v menu.

Další důležitá věc je, že se vám při kliku na item v menu musí měnit menu podle stránky, ne naopak, tedy ne stránka podle menu. Pro ty, kteří se zamotali: Pokud scrollujete na stránce, menu se vám podle toho mění. Pokud kliknete do menu, stránka scrolluje, ale menu se vám také mění podle toho, kde na stránce jste.

Vytvoříme si nějakou stránku, nezapomeňte si vytvořit také třídu .active, kterou bude obsahovat element li, která nám bude měnit styly menu itemů.

Menu highlighting v jQuery

Takže, jsme připraveni a již víme jak na to.

Vytvoříme si funkci:

function activeItem()
{
   ...
}

Nyní si musíme rozmyslet, jaké proměnné vytvoříme. Do začátku si do proměnné uložíme selektor 'menu ul', vytvoříme si scroll_top a jako poslední proměnnou odchylka, ta nám bude udávat naší odchylku od začátku articlu.

Jak jistě víme, normálním kódem by se nám menu item nastyloval až po tom, co by byl scroll_top větší než offset().top. Touto odchylkou posuneme offset().top o nějakou část nahoru, tedy to bude i odpovídat tomu, kde se právě nacházíme - tedy co právě čteme.

var menu = $('nav ul');
var odchylka = 200;
var scroll_top = $(window).scrollTop();

Nyní už potřebujeme zjistit offset().top = minimum každého articlu a také jeho konečnou vzdálenost = maximum. Od toho samozřejmě odečteme naší odchylku. Přímo se nabízí použití .each(), který pro každý element, který vyhovuje selektoru, provede určitou funkci.

$("#main section article").each(function(){
   var toto = this;
   var article_top = $(toto).offset().top;
   var article_height = $(toto).innerHeight();
   var article_id = $(toto).attr('id');

   var min = article_top - odchylka;
   var max = article_top + article_height - odchylka;

this, tedy aktuální article, který právě .each() prochází, si uložíme do proměnné toto.

Důležité je, abychom pro zjišťování výšky articlu používali innerHeight(). Ten nám k normální výšce přičte i padding. Pokud bychom chtěli přičíst i margin, použijeme outerHeight().

Teď už máme vše potřebné pro podmínku.

if ( (scroll_top > min) && (scroll_top < max) )

Podmínka nám funguje, takže stačí vymyslet jak měnit aktivní item v menu. Nejjednodušší bude, když všem 'nav ul li' odebereme třídu .active, to uděláme takto. Mimochodem, toto si přidejte pod proměnnou stroll_top.

menu.find('li').removeClass('active');

Následně třídu .active dáme takovému li, které má stejný href, jako náš article_id.

if ( (scroll_top > min) && (scroll_top < max) )
{
   menu.find('li a[href="#'+article_id+'"]').parent().addClass('active');
}

Jelikož nám menu prezentuje $('menu ul'), musíme nějak označit naše 'li a'. Ovšemže menu.$('li a') fungovat NEbude. Pro tuto situaci, kdy bychom potřebovali dále hledat, zde máme .find() nebo .filter().

.find() nám prohledává další potomky, kdežto .filter() nám prohledává selektor, v našem případě 'nav ul'. My tedy použijeme .find(). Do něho jsme dali vyhledávat 'li a', a to přesněji takovéto 'a[href="#'+ar­ticle_id+'"]'. Následně najdeme rodiče - tedy li a tomu přidělíme třídu.

Naší funkci tedy ještě musíme volat i v

$(window).scroll(function(){
   activeItem();
});

, jinak by nám to samozřejmě při scrollování nefungovalo.

Pro zkoušku si odebereme třeba a#delta z menu a zkontrolujeme si, zda-li nám to funguje, tedy respektive nefunguje. Když budeme na article#delta tak se nám nesmí nic zabarvit. Také si zkuste dát footer třeba na 7000px, jestli vám tam nic nezvýrazňuje.

Menu highlighting v jQuery

Každopádně je to všechno a funguje to. :)


 

Stáhnout

Staženo 543x (8.87 kB)
Aplikace je včetně zdrojových kódů v jazyce javascript

 

  Aktivity (1)

Článek pro vás napsal Honza Bittner
Avatar
Autor je vášnivý web developer. Ptejte se mě na cokoli na https://github.com/HoBi/ama a followujte mě na Twitteru https://twitter.com/tenhobi. :-)

Jak se ti líbí článek?
Celkem (11 hlasů) :
55555


 



 

 

Komentáře

Avatar
studio.manoss:

No, mě to právě zachránilo krk ;) takže palec nahoru. Navíc jsem si prosvištěl řeckou abecedu :D

 
Odpovědět  +1 25. ledna 22:59
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 1 zpráv z 1.