As a child my family’s menu consisted of two choices: take it or leave it.
Buddy Hackett

Rejtett menü


Kedves Látogató! Bizonyára Te is kerültél már abba a helyzetbe, hogy olyan menüre volt szükséged, ami ugyan állandóan rendelkezésre áll, ám mégsem takar el semmit, és nem foglalja el a képernyő adott felületét. Van olyan menü, mint amilyet a hálóhelyemen látsz. Ennek az a hibája, hogy csak az oldal tetején érhető el. Nyilván találkoztál olyan menüvel is, amelyik a weboldal valamelyik szélén helyezkedik el; vagy együtt gördül a tartalommal, vagy az ablak egy pontjához rögzített. Mindkét megoldásnak a hátránya, hogy többnyire teljes hosszban leköti az oldal egy részét, ahogy itt jobbra a Google AdSense-hirdetések számára fenntartott sáv teszi.

Milyen a jó menü?

Hogyan küszöbölhetők ki e negatívumok? Elsősorban olyan menüre van szükség, amelyik az ablak rögzített pontján helyezkedik el, hogy az oldal görgetésekor is folyamatosan kezünk ügyében legyen. Másodsorban – hogy a menü ne foglaljon el folyamatosan helyet és ne takarjon le egyfolytában semmit – el kell rejteni, hogy csak akkor bújjon elő, amikor éppen szükség van rá.

Fix menü

Helyhez rögzített menü után kutatva a világhálón, egy kisebb gyűjtemény révén találtam is egy csinos, célszerűnek látszó oldalt. Vizsgálgatva a kódját, kiderült, hogy a menüt egyszerű HTML-lista elemeiként tartalmazza (ugyanez elképzelhető volna táblázatos formában vagy div-ek halmazával; sőt, akár szóközzel tagolva is egymás mellé rakhatók az elemek). Tiszteletem jeléül megtartva a szerkezetet, a kódrészlet így néz ki:

<div id="fix-div" onmouseover="showMenu()" onmouseout="hideMenu()">
   <div id="hidden-menu">
      <ul>
         <li><a href="#teteje" id="menu-teteje" onclick="clicked('menu-teteje')" class="menu-item">Az oldal tetejére</a></li>
         <li><a href="#jo-menu" id="menu-jo-menu" onclick="clicked('menu-jo-menu')" class="menu-item">Milyen a jó menü?</a></li>
         <li><a href="#fix-menu" id="menu-fix" onclick="clicked('menu-fix')" class="menu-item">Fix menü</a></li>
         <li><a href="#stiluslap" id="menu-stiluslap" onclick="clicked('menu-stiluslap')" class="menu-item">A stíluslap</a></li>
         <li><a href="#mutat-rejt" id="menu-mutat-rejt" onclick="clicked('menu-mutat-rejt')" class="menu-item">Mutatás/elrejtés</a></li>
         <li><a href="#hab" id="menu-hab" onclick="clicked('menu-hab')" class="menu-item">Hab a tortán</a></li>
         <li><a href="#plusz"id="menu-plusz" onclick="clicked('menu-plusz')" class="menu-item">Egy kis plusz</a></li>
         <li><a href="#osszegzes" id="menu-osszegzes" onclick="clicked('menu-osszegzes')" class="menu-item">Összegzés</a></li>
      </ul>
   </div>
</div>

Az állandóan aktív, de alapértelmezésben átlátszó "fix-div" azonosítójú külső blokk folyamatosan érzékeli, hogy az egér mutatója fölötte van-e vagy sem (ettől függ, hogy láthatóvá váljon-e a menünk). Ebbe a blokkba ágyazódik a tényleges, alapállapotban rejtett menüblokk.

A trükk járulékos hozama, hogy a menü tetszőleges helyre tehető a HTML-kódban. A fix pozicionálás révén nem ott jelenik meg, ahová beágyaztuk. Elhelyezhetjük a body elejére, végére vagy akár szöveg közé is – bárhová. A fenti kód közvetlenül ez alá a bekezdés alá került.

A stíluslap

A stíluslapon a menükezelés szempontjából érintett blokkokra vonatkozó tulajdonságok az alábbi értékeket tartalmazzák:

#fix-div {
   position: fixed;               /* helyhez kötött */
   bottom: 0px;                   /* az ablak alján (0-nál nagyobb érték esetén feljebb kerül) */
   height: 26px;
   margin-left: -36px;
   border: 1px solid transparent; /* átlátszó kerettel */
   background-color: transparent; /* átlátszó háttérrel */
   background-image: url(../images/misc/spacer.gif);
}

#hidden-menu {
   margin: 0 auto;
   padding-top: 4px;
   line-height: 16px;
   display: none;                 /* elrejtve */
}

#hidden-menu  ul {
   margin: 0;
   list-style-type: none;
}

#hidden-menu  ul li {
   float: left;
   padding: 0 2px;
}

Ahogy az elvárható, alapállapotban az összes elem a stílusbeállításoknak megfelelően nem látszik. A fix-div első két tulajdonságának értéke határozza meg, hogy a menü az ablak aljára kerüljön, az utolsó pedig egy 1 × 1 pixeles megsokszorozódó, átlátszó „kép”, aminek egyetlen célja, hogy az Explorer ne bizonytalankodjon a menü érzékelésében. Általánosságban elmondható, hogy az átlátszó elemek ugyan jelen vannak, csak nem látszanak. A hidden-menu stílusbeállításai pedig egymás mellé sorakoztatják a menü – amúgy szokásosan egymás alá kerülő – listaelemeit. A menüelemek látványt generáló stílusbeállításai sem igazán bonyolultak:

A hover és az active pszeudoosztály outline tulajdonsága révén a szöveg a háttérrel megegyező színű keretet kap. Ezzel a vonalvastagság által megadott mértékben kiterjeszthető a háttérszín, amit az Explorernek csak a 8-as változata ért. Sajnos a 7-es elég ramaty képet mutat. (Ez e hálóhely legtöbb hiperhivatkozására is áll.)

A copyright-excluder tulajdonságai között megadott width érték adja a lap legalján a fix-div érzékelő blokk elől elzárt terület szélességét (ez később, az összegzésben remélhetőleg világosabbá válik)…

Mutatás/elrejtés

Az oldalon működő JavaScripttel két-két feladatot kell elvégezni. Egyrészt az aktuális eseményhez kell igazítani az állandóan aktív (fix-div) blokk háttér- és keretszínét, másrészt – ezzel egyidejűleg – az egér helyzetétől függően meg kell jeleníteni vagy el kell rejteni a menüt. A függvények futtatásával módosulnak a stíluslapon eredetileg megadott értékek.

function showMenu() {
   document.getElementById('fix-div').style.backgroundColor = '#6AD'
   document.getElementById('fix-div').style.borderTop =
   document.getElementById('fix-div').style.borderBottom = '1px solid #1A4D81'
   document.getElementById('hidden-menu').style.display = 'block' // mutasd
}

function hideMenu() {
   document.getElementById('fix-div').style.backgroundColor = 'transparent'
   document.getElementById('fix-div').style.border = '1px solid transparent'
   document.getElementById('hidden-menu').style.display = 'none'  // rejtsd el
}

Bizonyára már ki is találtad: a showMenu() függvény akkor lép életbe, ha az egér mutatója a fix-div azonosítójú blokk fölé kerül, míg a hideMenu() függvény sorai akkor hajtódnak végre, amikor a mutató elhagyja a blokkot. (Ha megmondod, hogy miért nincs semmi a showMenu() függvény második sorában az egyenlőségjel jobb oldalán, Sport csoki a jutalmad!)

A menüelemre kattintás pedig meghívja az alábbi függvényt, ami az elem szövegének aláhúzását végzi, majd alaphelyzetbe hozza az előzőleg kiválasztott menüelemet (ha van ilyen).

var previous
function clicked(item) {
	document.getElementById(item).style.textDecoration = 'underline'
	if (previous)
		document.getElementById(previous).style.textDecoration = 'none'
	previous = item
}

Hab a tortán

A Fix menü alcím alatt említett csinos, célszerűnek látszó oldalon megfogott még valami: a menüelemre kattintva tapasztalható visszafogott, diszkrét mozgás. Rövidesen nekiálltam felderíteni, hogy ezt mi eredményezi. Kiderült, hogy a szájt építője felhasznált egy MIT- vagy GPL-licenccel védett, ingyenes JavaScript-csomagot. (A két licenc közül szabadon lehet választani.) A csomag forrása a jQuery „Downloading jQuery” oldaláról tölthető le. Ahogy egyből rájöttél, nem tudtam ellenállni a kísértésnek. Anélkül, hogy különösebben vizsgálgattam volna a tartalmát, egy az egyben használatba vettem…

Mindenesetre legalábbis fura, hogy öt állományból áll. Feltételezhető, hogy jóval többet tud, mint ami itt látszik. Ha úgy adódik, feltétlenül szánok rá egy kis időt, hogy feltérképezzem. Majd beszámolok a tapasztalataimról.

Egy kis plusz

Miután elkészült, nézegettem, kóstolgattam a menüt az ablak alján. Hamarosan rá kellett jönnöm egy súlyos hiányosságára. Ha több weblapon volna rá szükség, bármilyen módosítást (menüelem törlését, átírását vagy új elem felvételét) minden egyes oldalon át kellene vezetnem. Mennyivel egyszerűbb lenne csak egyetlen állományban változtatni, ami érvényesülne minden oldalon. Nem is kell mondanom, hogy rövid álmodozás után nekifogtam a megvalósításnak. Az eredeti menü kissé átalakított változatát

<div id="fix-div2" onmouseover="showMenu2()" onmouseout="hideMenu2()">
   <div id="hidden-menu2">
      <div id="menu2-head">Rejtett menü</div>
      <span id="span-menu2-teteje"><a href="#teteje"><div id="menu2-teteje">Az oldal tetejére</div></a></span>
      <span id="span-menu2-jo-menu"><a href="#jo-menu"><div id="menu2-jo-menu">Milyen a jó menü?</div></a></span>
      <span id="span-menu2-fix"><a href="#fix-menu"><div id="menu2-fix">Fix menü</div></a></span>
      <span id="span-menu2-stiluslap"><a href="#stiluslap"><div id="menu2-stiluslap">A stíluslap</div></a></span>
      <span id="span-menu2-mutat-rejt"><a href="#mutat-rejt"><div id="menu2-mutat-rejt">Mutatás/elrejtés</div></a></span>
      <span id="span-menu2-hab"><a href="#hab"><div id="menu2-hab">Hab a tortán</div></a></span>
      <span id="span-menu2-plusz"><a href="#plusz"><div id="menu2-plusz">Egy kis plusz</div></a></span>
      <span id="span-menu2-osszegzes"><a href="#osszegzes"><div id="menu2-osszegzes">Összegzés</div></a></span>
   </div>
</div>
egy sima szöveges állományban tároltam a szerveren, ami Ajax-támogatással válik egy tetszőleges helyre – jelen esetben e bekezdés végére – biggyesztett üres span értékévé. Ettől kezdve mindig csak ennek a külön tárolt fájlnak a tartalmát kell átalakítani. Ha akarod, megnézheted a szöveges állományt. (Amennyiben a látványt élvezhetetlennek találod, a karakterkódolást érdemes átállítani UTF-8-ra. Minthogy az oldalon a menü – a tulajdonságaival együtt – magában áll, természetes, hogy ha az egeret a menüelemek fölé húzod, hibaüzenetet kapsz.) Az eljárás eredményének megtekintéséhez – itt, ezen a lapon – bátran húzd a mutatót az ablak jobb felső sarkába…

Ez a menü a másiktól tökéletesen függetlenül, önállóan működik (hogy a kód silabizálgatásakor ne nehezítse a dolgot, direkt nem hangoltam a kettőt össze), ezért felváltva kezelve mindkettőben látszik, hogy utoljára melyik elemre kattintottál. Nagy örömömre szolgál, hogy teljesült régi vágyam: ebben a menüben (a hiperhivatkozás JavaScriptben előírt törlésével) inaktívvá válik a kiválasztott menüelem. Mindezt készséggel fogadja az Flock, a Google Chrome, a Mozilla Firefox, az Opera, a Safari, a SeaMonkey és a már két éve nem támogatott, ősrégi Netscape; de még a négy évvel ezelőtt útjára bocsátott utolsó Mozilla is csak színkezelésben hibázik.

Mondanom se kell, hogy a menüelem passzivitását az Explorerben nem láthatod, mert ez a fránya, megátalkodott, öntörvényű böngésző a JavaScripttel generált kódot önhatalmúlag átalakítva tönkreteszi, amit már nem lehet végrehajtani. Emiatt – ahhoz, hogy legalább a háttérszíne és a kurzor mutassa a kiválasztott elemet – kénytelen voltam egy szánalmas, megalkuvó megoldást alkalmazni. Amit tehettem, az csak tüneti kezelés. Kész átverés… Ha Explorert futtatsz, ugye látod, hogy mi lett a következménye? Az előzőleg kiválasztott menüelem stílusa megtartja a hover pszeudoosztályt. (Ha már itt tartunk, szólnom kell arról is, hogyha az Explorer 6-os változatát használod, ne számíts semmi jóra. A program nem ismeri fel a fix pozicionálás itt alkalmazott módszerét. Mindkét menü – meglehetősen megnyirbált stílusokkal – ott jelenik meg az oldalon, ahol a kódban éppen található. Természetesen ez cseppet sem meglepő a program korát tekintve…)

Próbálgatva a munka új gyümölcsét ötlött fel bennem: nem tartható, hogy a menü mindig a jobb felső sarokban legyen. Biztosítanom kell, hogy az ízlésednek megfelelő helyre tehesd. Ebben segítségemre volt a QuirksMode. Ezentúl a menüt bárhová rakhatod az ablakban, csak kattints a fejére és húzd el. A mindenkori helyzetét itt követheted nyomon:

x =
y =
Az x és y értéke mutatja a menüblokk és az ablak bal fölső, míg a zárójelbe tett méret a jobb alsó sarkának vízszintes és függőleges távolságát.

Ha akarod, a menüt elhelyezheted koordináták megadásával (zárójelben – szürkén – a megadható legnagyobb értékeket láthatod):

x = px

y = px

vagy az alábbi kis ábra segítségével az ablak négy sarkának valamelyikébe teheted;
sőt, ha rákattintasz a menüfejen lévő kis gombra, annak lenyomott helyzetében a menüt mozgathatod a kurzorvezérlő billentyűk segítségével is. Ezalatt a menü folyamatosan látszik. A gombot a menüblokkra kattintással, az Escape vagy az m billentyű lenyomásával, továbbá a fenti pozicionálások valamelyikével oldhatod ki. Hogy a rejtettsége mellett mindig tudd, hogy hol található, ez az áttetsző gomb akkor is a képernyőn marad, amikor a menü egyébként nem látszik. (Az Explorer sajnos nem ismeri az ezt előidéző szabványos utasítást, emiatt e böngészőben a gomb letakarja a mögötte lévő tartalmat.)

Végül elmondanám, hogy az oldal frissítésével vagy ismételt betöltésével a menü visszaáll az eredeti helyére. Alapállapotban az ablak szélességének változtatásakor mindig a jobb felső sarokban található, de vigyázat, ha már elmozgattad, helyben marad. Ez az ablak szélességének csökkentésekor csaphat be igazán! Amennyiben elfelejtetted, hogy hova helyezted, az „eltűnt” menü az m billentyű lenyomásával bármikor megjeleníthető. (Ha előzőleg véletlenül az ablakon kívülre került, e műveletre a jobb felső sarokba ugrik.) Ilyenkor, numerikus és grafikus pozicionálással a menüblokk 2 másodpercre megjelenik a képernyőn.

Összegzés

Sikerült tehát elérni a kitűzött célt. Íme az ablak egy részterületén egy menü, ami bármikor rendelkezésre áll és soha sincs útban. Ugye, milyen jól hangzik? Bizony, sok olyan weboldalt láttam, amelyik tetején ott virít egy tartalomjegyzék-szerű hivatkozáscsomag. Nem is szólva az oldalak különböző pontjain elhelyezett sok-sok linkről, amikre kattintva a lap tetejére lehet ugrani. Ezeket a funkciókat sokkal kézreesőbben kínálja ez a menü (természetesen a világháló akármelyik oldala is szerepelhetne benne). Most, hogy e technikát ilyen jól felfedeztem, néhány, minden böngészőben működő trükkjét boldogan építettem be Rita blogja oldalaira, ahol úgy kellett, mint egy falat kenyér.

Van egy dolog, ami még hátravan: érdemes volna megvizsgálni, hogy hogyan lehet ezen az úton almenüt létrehozni. Ebben nagy segítséget nyújthat például az Envato szájtja.

Egy probléma azért mégiscsak akadt: a menü letakarta az oldal alján lévő copyright-hivatkozást, ezért nem lehetett rákattintani. Ennek kiküszöbölésére korlátozni kellett a menü megjelenítését úgy, hogy a mutatót a hivatkozáshoz közelítve ne bújjon elő. E célra valószínűleg használhatók lettek volna például az ablakméret és görgetésben leírtak. Minthogy a dolgokat javarészt többféleképpen is meg lehet oldani, naná, hogy egy könnyebb utat választottam: az érintett sor blokkját használtam fel.

<div id="copyright-excluder" onmouseover="onCopyright()" onmouseout="outOfCopyright()">
   <a href="../site/copyright.htm" ... stb.
</div>

A blokkhoz rendelt onCopyright() JavaScript-függvénynek nem kell mást tennie, mint a képernyőre merőleges z tengely mentén mozgatni az egér mindenkori helyzetét érzékelő fix-div blokkot – azt a lap legalján lévő copyright alá (vagy mögé) „rejtve”. A blokk letakart részterületén nem észlelheti, hogy a mutató fölé került-e. Az outOfCopyright() pedig – ha a mutató elhagyja a copyright blokkot – visszaállítja az eredeti állapotot.

function onCopyright() {
   document.getElementById('copyright-excluder').style.border = '1px dashed #aeaeae'
   document.getElementById('fix-div').style.zIndex = '-1' // küldd hátra
}

function outOfCopyright() {
   document.getElementById('copyright-excluder').style.border = '1px solid transparent'
   document.getElementById('fix-div').style.zIndex = '1'  // hozd előre
}

A megoldás eredménye: ha az oldal legalsó helyzetében a mutatót a copyright-hivatkozásra fölülről lefelé húzod, az onCopyright() függvény hatására a menü nem jelenik meg – rákattinthatsz a linkre (a fix-div blokk elől elzárt területet szaggatott vonal jelzi). Ám, ha alulról felfelé vagy az elzárt területen kívülre húzod a mutatót, a fentiek szerint megszűnik a függvény hatása, a menüelemeket az oldal legalján is elérheted.

Mindezt meg sem említettem volna, de minthogy ez a technika az oldal bármelyik elemére is alkalmazható, akármikor szükséged lehet rá. Érdemes még megjegyezni, hogy a z irányú mozgatás kizárólag pozicionált elemekre érvényes, amilyen itt a fix-div blokk.

Kedves látogató! El kell árulnom, hogy a weblapon látható kódok csak tájékoztató jellegűek, puszta kivonatai a ténylegeseknek. Pár igen fontos stílusbeállítás például JavaScripttel történik, ami itt nem is látszik. Ha kíváncsi vagy, megnézheted, sőt le is töltheted a css- és a js-állományt (a HTML-oldal forrásának megszerzését rád bízom). A fájlokból könnyen kihámozható mindaz, ami az ablak alján lévő rejtett menüvel kapcsolatos. Ha bármilyen hibába ütköznél, valamit nem értesz, kérdésed vagy hozzátenni valód van, kérlek mondd el vagy írd meg. Számítok a véleményedre…

Készült:
Utolsó módosítás:
Sütijóváhagyás:
2010. 01. 20.
2010. 03. 07.
2015. 08. 20.
Valid HTML 4.01 Transitional Valid CSS level 2