Gebruikerslogin

Nu online

Er zijn momenteel 1 gebruiker en 4 gasten online.

Enquête

Wat is leuker?
White hat SEO
70%
Black hat SEO
30%
Totaal aantal stemmen: 98

Suckerfish, toegankelijke dropdown menu's

Dropdown menu's zijn handig. Zeker bij grote sites is het een ideale manier om met weinig klikken toch snel op de plek van bestemming uit te komen. Maar helaas worden deze menu's maar al te vaak opgebouwd door middel van alleen JavaScript. Er wordt niet alleen JavaScript gebruikt voor de functionaliteit van het uitklappen, maar zelfs ook voor het opbouwen van de menu-items zelf. En dat is jammer, aangezien zoekmachines geen JavaScript uitvoeren en zo kun je dus de indexatie van je menu en dus waarschijnlijk zelfs hele delen van je website wel vergeten.

Gelukkig is daar een aantal jaren geleden een goede oplossing voor gevonden door de heren Patrick Griffiths en Dan Webb. Deze idee is uitgebracht onder de naam Suckerfish Dropdowns. Een jaar later kwam er een verbeterde versie uit onder de naam Son of Suckerfish en is nu een veel gebruikt menu. De kracht van het suckerfish menu is dat het een zo goed als puur CSS menu is. Er zit alleen een klein beetje JavaScript bij omdat Internet Explorer (t/m versie 6) de :hover pseudo-class niet volledig ondersteund.

Eén niveau diep

Hieronder vind je de HTML code voor een dropdown menu met één niveau.

  1.  
  2. <ul id="nav">
  3. <li><a href="#">Percoidei</a>
  4. <ul>
  5. <li><a href="#">Remoras</a></li>
  6. <li><a href="#">Tilefishes</a></li>
  7. <li><a href="#">Bluefishes</a></li>
  8. <li><a href="#">Tigerfishes</a></li>
  9. </ul>
  10. </li>
  11. <li><a href="#">Anabantoidei</a>
  12. <ul>
  13. <li><a href="#">Climbing perches</a></li>
  14. <li><a href="#">Labyrinthfishes</a></li>
  15. <li><a href="#">Kissing gouramis</a></li>
  16. <li><a href="#">Pike-heads</a></li>
  17. <li><a href="#">Giant gouramis</a></li>
  18. </ul>
  19. </li>
  20.         <!-- etc. -->
  21. </ul>
  22.  

En hier zien we dan een mooi gestructureerde lijst. Hieronder nog even wat CSS toevoegen voor het uiterlijk.

  1. #nav, #nav ul {
  2.         padding: 0;
  3.         margin: 0;
  4.         list-style: none;
  5. }
  6. #nav a {
  7.         display: block;
  8.         width: 10em;
  9. }
  10. #nav li {
  11.         float: left;
  12.         width: 10em;
  13. }

Zorg er echter wel voor dat je bij de #nav li een breedte opgeeft, anders zal het in Opera niet werken. Vergeet ook niet de (eventuele) content onder het menu te 'clearen' met clear: left;.

Nu moeten we er nog voor zorgen dat de lijsten die uitgeklapt moeten worden in eerste instantie verborgen zijn. Dit zou kunnen door middel van display: none;, maar omdat sommige screenreaders de elementen onzichtbaar maken is dit geen toegankelijke oplossing. Daarom maken we gebruik van de left eigenschap. In plaats van display: none; gebruiken we dan left: -999em; om de submenu's te verbergen en later gebruiken we left: auto; om ze weer tevoorschijn te toveren. Voor dat terugtoveren gebruiken we dan onderstaande code.

  1. #nav li ul {
  2.         position: absolute;
  3.         width: 10em;
  4.         left: -999em;
  5. }
  6. #nav li:hover ul {
  7.         left: auto;
  8. }

Omdat Internet Explorer (t/m versie 6) helaas niet de :hover pseudo-class ondersteunt op andere elementen dan het a element, zijn we helaas verplicht tot en stukje JavaScript code.

  1. sfHover = function() {
  2.         var sfEls = document.getElementById("nav").getElementsByTagName("LI");
  3.         for (var i=0; i<sfEls.length; i++) {
  4.                 sfEls[i].onmouseover=function() {
  5.                         this.className+=" sfhover";
  6.                 }
  7.                 sfEls[i].onmouseout=function() {
  8.                         this.className=this.className.replace(new RegExp(" sfhover\\b"), "");
  9.                 }
  10.         }
  11. }
  12. if (window.attachEvent) window.attachEvent("onload", sfHover);

Dit script zorgt ervoor dat bij een mouseover op het desbetreffende li element de sfhover class wordt toegevoegd en bij de mouseout weer wordt weggehaald.

Nu moeten we alleen nog even het stuk CSS toevoegen om ook de sfhover class werkende te krijgen.

  1. #nav li:hover ul, #nav li.sfhover ul {
  2.         left: auto;
  3. }

Zie daar, een werkende versie van een toegankelijk dropdown menu.

Noot: voor het gemak heb ik de CSS en het JavaScript even in de HTML file zelf geplaatst. Uiteraard is het netter om dit gescheiden te doen.

Meerdere niveaus

Het originele suckerfish artkikel werkte maar voor één niveau, maar met slechts wat kleine aanpassingen en logisch nadenkwerk kunnen we het makkelijk ombouwen naar een versie met meerdere niveaus. En, in tegenstelling tot de originele JavaScript code, is de 'sfHover' functie nu ook van toepassing op alle li elementen (ook de 'descendants' van de eerste li), zodat de meerdere niveaus in Internet Explorer ook mogelijk zijn.

Om maar weer met de HTML te beginnen hieronder het stuk code met daarin een extra niveau.

  1.  
  2. <ul id="nav">
  3. <li><a href="#">Percoidei</a>
  4. <ul>
  5. <li><a href="#">Remoras</a>
  6. <ul>
  7. <li><a href="#">Echeneis</a></li>
  8. <li><a href="#">Phtheirichthys</a></li>
  9. <li><a href="#">Remora</a></li>
  10. <li><a href="#">Remorina</a></li>
  11. <li><a href="#">Rhombochirus</a></li>
  12. </ul>
  13. </li>
  14. <li><a href="#">Tilefishes</a></li>
  15. <li><a href="#">Bluefishes</a></li>
  16. <li><a href="#">Tigerfishes</a></li>
  17. </ul>
  18. </li>
  19. <li><a href="#">Anabantoidei</a>
  20.         <!-- etc. -->
  21. </li>
  22. <!-- etc. -->
  23. </ul>
  24.  

Er zijn nog een aantal andere zaken die moeten worden toegevoegd aan de eerste versie. Het tweede niveau ('Echeneis' enz.) moet namelijk niet naar onder worden uitgeklapt, maar opzij ten hoogte van de bijbehorende 'moeder li' ('Remoras' in dit geval). Daarvoor hebben het volgende stuk CSS nodig.

  1. #nav li ul ul {
  2.         margin: -1em 0 0 10em;
  3. }

Omdat we namelijk de top van de absoluut gepositioneerde box niet kunnen definiëren , wordt deze onder de regel van de li die 'gehovered' wordt geplaatst. Daarom zetten we de margin-top op -1em zodat deze op dezelfde hoogte komt te staan. De dropdown menu's komen nu wel hoger te staan, maar omdat de meeste 'line-heights' groter dan 1em staan ingesteld voegen we daarvoor het volgende stukje CSS aan de ul's toe.

  1. #nav, #nav ul {
  2.         padding: 0;
  3.         margin: 0;
  4.         list-style: none;
  5.         line-height: 1em;
  6. }

Door het trapsgewijze (cascading) gedrag komt het tweede niveau ook automatisch tevoorschijn als je het eerste niveau uitklapt. Daarom moeten we ook het tweede niveau nog even expliciet verbergen.

  1. #nav li:hover ul ul, #nav li.sfhover ul ul {
  2.         left: -999em;
  3. }

En om het tweede niveau tevoorschijn te halen draaien we bovenstaande regel om en voegen de volgende CSS toe:

  1. #nav li:hover ul, #nav li li:hover ul, #nav li.sfhover ul, #nav li li.sfhover ul {
  2.         left: auto;
  3. }

En tadaa, een dropdown menu met twee niveaus.

Voor het geval dat je nu niveaus wilt toevoegen moet je er dus op letten dat je elke niveau expliciet verbergt en tevoorschijn haalt. Voor drie niveaus gebruik voeg je dan de volgende CSS toe:

  1. #nav li:hover ul ul, #nav li:hover ul ul ul, #nav li.sfhover ul ul, #nav li.sfhover ul ul ul {
  2.         left: -999em;
  3. }
  4. #nav li:hover ul, #nav li li:hover ul, #nav li li li:hover ul, #nav li.sfhover ul, #nav li li.sfhover ul, #nav li li li.sfhover ul {
  5.         left: auto;
  6. }

En mocht je er ooit vier nodig hebben geldt de volgende CSS code:

  1. #nav li:hover ul ul, #nav li:hover ul ul ul, #nav li:hover ul ul ul ul, #nav li.sfhover ul ul, #nav li.sfhover ul ul ul, #nav li.sfhover ul ul ul ul {
  2.         left: -999em;
  3. }
  4. #nav li:hover ul, #nav li li:hover ul, #nav li li li:hover ul, #nav li li li li:hover ul, #nav li.sfhover ul, #nav li li.sfhover ul, #nav li li li.sfhover ul, #nav li li li li.sfhover ul {
  5.         left: auto;
  6. }

Voorbeelden

Waarschijnlijk heb je al de voorbeelden bekeken van dropdown menu's van één niveau, twee niveaus en drie niveaus. Dit zijn mooie kale voorbeelden om de 'techniek' goed onder de knie te krijgen, maar je kan natuurlijk ook eens een kijkje nemen bij een wat mooier voorbeeld. Ook is het mogelijk om in plaats van een horizontaal menu een verticaal menu te maken.

Toevoeging: Roger wees me erop dat deze techniek niet goed werkt in IE7. De uitgeklapte dropdowns blijven namelijk nog wel eens hangen. Check de fix.

arjaneis
Aantal berichten: 23

Welke screenreaders ondersteunen display: none; niet? Of hoe kom je aan die info? Voor mij is dit nieuw.

emarky
Aantal berichten: 35

Onder het kopje voorbeelden linken de submenu's van één niveau, twee niveaus en drie niveaus allen naar voorbeeld1.html :) Wellicht even fixen ;)

Arjan
Avatar van Arjan
Aantal berichten: 532

Welke screenreaders ondersteunen display: none; niet?

Ik bedoel dat screenreaders deze eigenschap juist wel ondersteunen en dus de 'verborgen' ul's niet tonen/voorlezen. Dat is dan dus ook de reden dat er voor de 'left' eigenschap is gekozen en niet display:none;

(één van de) bron(nen): http://css-discuss.incutio.com/?page=ScreenreaderVisibility

@emarky: bedankt, is nu gefixed ;)

vinnietime
Avatar van vinnietime
Aantal berichten: 137

Arjan,

Fijn scriptje (-: (werkt prima)

Opmerking: als ik dit artikel selecteer in ie6 is de middenste kolom helemaal leeg en hangt dit artikel er onderaan aan.

Arjan
Avatar van Arjan
Aantal berichten: 532

Opmerking: als ik dit artikel selecteer in ie6 is de middenste kolom helemaal leeg en hangt dit artikel er onderaan aan.
Tnx voor de tip ;-) Het is inmiddels gefixed. Kwam door de breedte van de code divs

Roger
Avatar van Roger
Aantal berichten: 35

Verder kan in IE7 een rare bug optreden.. Misschien handig om die fix voor IE7 ook te vermelden?

Arjan
Avatar van Arjan
Aantal berichten: 532

Tnx Roger. Van de fix was ik al wel op de hoogte, maar was hem helemaal vergeten bij het schrijven van dit artikel. Ik heb hem erbij gezet.

visje
Aantal berichten: 1

Hallo

Ik ben geen whizzkid en heb geen kaas gegeten van bovenstaande script. Waar moet ik wat plaatsen? Tussen de head tags of body tags?
Of moet ik alles afzonderlijk onder elkaar knippen en plakken?
Ik wil dolgraag een dropdownmenu en dit lijkt me het meest geschikt. Hoop dat jullie me kunnen helpen.

Arjan
Avatar van Arjan
Aantal berichten: 532

Hoi Visje, welkom hier..

Hier even een uitleg over wat je waar moet plaatse. Hoop dat je er wat mee kunt.

Tussen de <body> tags kun je de html plaatsen. Dat is dus de code met de <ul>'s en de <li>'s.

Vervolgens heb je nog de CSS voor het uiterlijk. Hoe je dat in je site zet kun je in het artikel over CSS voor beginners lezen.

En dan tot slot moet je nog het stukje javacscript plaatsen, zodat het ook in Internet Explorer goed werkt. Dit doe je als volgt:

Je maakt een bestand aan die je bijv. menu.js noemt. Daarin plaats je de code van de javascript functie. Vervolgens plaats je dan deze code tussen je <head> tags:

<script type="text/javascript" src="menu.js"></script>

En als het goed is doet ie het nu.

Succes ermee!!

spectro
Aantal berichten: 4

Hallo allemaal,

Ik heet frank en ik ben beginneling op het gebied van websites bouwen.

Ik heb bovenstaand dropdownmenu gebruikt en het werkt prima. In firefox, opera en ie7 gaat alles goed. Maar in ie6 verdwijnt de backgroundcolor van het dropdownmenu, volgens mij de nav li:hover ul.

Misschien weet iemand een oplossing?

Arjan
Avatar van Arjan
Aantal berichten: 532

@spectro: het forum is een mooie plek om dit soort vragen te bespreken. Zou je misschien daar alsnog je vraag kunnen stellen?

Kijk dan ook meteen of je wat screenshots of, nog beter, een testversie online kunt laten zien.

Alvast bedankt!

spectro
Aantal berichten: 4

Hallo Arjan,

Had ik kunnen weten. Ik zal mijn vraag daar stellen.
Bedankt voor je reactie.