Menu en cascade automatique (tout CSS + javascript pour IE)

Un menu déroulant en cascade simple basé sur des CSS avec un petit script javascript supplémentaire pour IE. Sa structure en fait le menu idéal par boucles récursives.

Introduction

Le menu présenté se révèle être d’une simplicité de mise en oeuvre une fois qu’on a compris son fonctionnement. Il est basé sur les CSS (plus un script pour permettre à IE de se comporter presque comme les autres navigateurs).

Quelques mots sur le fonctionnement

Le menu fonctionne grâce aux listes imbriquées :

<ul>
  <li>Niveau 1
    <ul>
      <li>Niveau 1.1</li>
      <li>Niveau 1.2
        <ul>
          <li>Niveau 1.2.1</li>
          <li>Niveau 1.2.2</li>
        </ul>
      </li>
      <li>Niveau 1.3
        <ul>
          <li>Niveau 1.3.1</li>
        </ul>
      </li>
    </ul>
  </li>
  <li>Niveau 2
    <ul>
      <li>Niveau 2.1</li>
      <li>Niveau 2.2</li>
      <li>Niveau 2.3
        <ul>
          <li>Niveau 2.3.1</li>
          <li>Niveau 2.3.2</li>
        </ul>
      </li>
    </ul>
  </li>
</ul>

Ce qui donne sans mise en forme particulière :

  • Niveau 1
    • Niveau 1.1
    • Niveau 1.2
      • Niveau 1.2.1
      • Niveau 1.2.2
    • Niveau 1.3
      • Niveau 1.3.1
  • Niveau 2
    • Niveau 2.1
    • Niveau 2.2
    • Niveau 2.3
      • Niveau 2.3.1
      • Niveau 2.3.2

Chaque niveau de liste sera un niveau du menu déroulant.

Préparation des pages du squelette :

Vous trouverez en bas de cet article le javascript à intégrer dans les pages. Personnellement je dépose le fichier dans un dossier « script » et je l’inclus avec le code suivant :

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

Il faut également ajouter ce code au niveau du body pour que le menu fonctionne sous IE :

<body onload="setHover('menulist')">

menulist est à remplacer éventuellement par le nom de l’id que vous voulez utiliser.

Les boucles

Boucle de base

Voici la boucle « basique » permettant de générer le menu de tout le site :

<ul id="menulist">
<BOUCLE_menu(RUBRIQUES){racine}>
  <li><a href="#URL_RUBRIQUE">#TITRE</a>
    <B_sousmenu><ul>
      <BOUCLE_sousmenu(RUBRIQUES){id_parent}>
        <li><a href="#URL_RUBRIQUE">#TITRE</a>
          <BOUCLE_ssousmenu(boucle_sousmenu)></BOUCLE_ssousmenu>
        </li>
      </BOUCLE_sousmenu>
    </ul></B_sousmenu>
  </li>
</BOUCLE_menu>
</ul>

Il suffit de nommer (id=« menulist ») et ensuite de styler la liste.

Les styles en provenance de l’exemple de Jep :

ul#menulist li ul{ display:none; }
	
ul#menulist li:hover>ul{ display:block; }

ul#menulist,
ul#menulist ul{
  background:white;
  border:1px solid black;
  list-style:none;
  margin:0px;
  padding:0px;
  width:148px;
  _width:150px;
  font-size: 12px;
}

ul#menulist ul{
  position:absolute;
  top:-1px;
  left:148px;
}

ul#menulist li{
  position:relative;
  margin:0px;
  padding:0px;
  _display:inline;
}

ul#menulist a{
  display:block;
  width:100%;
  color:#000000;
}

ul#menulist a:hover{
  background: gray;
  color: white;
}

Exemple ici

Boucle détectant la présence de sous-menus

On va ajouter ici des éléments qui permettent d’identifier visuellement les rubriques en contenant d’autres en les mettant en italique et en ajoutant « >>> » derrière l’intitulé. Les styles en exemple derrière sont plus travaillés que l’exemple précédent et les boucles SPIP également (ajout de tri, suppression des numéros de titres, ...).

<ul id="menulist">
	<BOUCLE_smenuspipr(RUBRIQUES){racine}{par num titre}><li<BOUCLE_smenr(RUBRIQUES){id_parent}{0,1}> class="smenu"</BOUCLE_smenr>><a href="#URL_RUBRIQUE">[(#TITRE|supprimer_numero)]<BOUCLE_smen1r(RUBRIQUES){id_parent}{0,1}> >>></BOUCLE_smen1r></a>
		<B_smenuspip><ul>
			<BOUCLE_smenuspip(RUBRIQUES){id_parent}{par num titre}><li<BOUCLE_smen(RUBRIQUES){id_parent}{0,1}> class="smenu"</BOUCLE_smen>><a href="#URL_RUBRIQUE">[(#TITRE|supprimer_numero)]<BOUCLE_smen1(RUBRIQUES){id_parent}{0,1}> >>></BOUCLE_smen1></a>
					<BOUCLE_ssmenu(boucle_smenuspip)></BOUCLE_ssmenu>
			</li></BOUCLE_smenuspip>
		</ul></B_smenuspip>
	</li></BOUCLE_smenuspipr>
</ul>

La boucle RUBRIQUES couplée à id_parent avec une restriction de 1 permet de détecter des sous-rubriques et ici d’appliquer un style particulier à la ligne (class=« smenu ») et d’ajouter « >>> » dans l’intitulé du menu.

Des styles mettant un peu plus le menu en valeur et exploitant la détection de sous-menus :

ul#menulist li ul{ display:none; }

ul#menulist li:hover>ul{ display:block; }

ul#menulist {
  font-family: Arial, Helvetica, sans-serif;
  font-size: 11px;
  color: #0F4D2A;
  position: static;
  left: 10px;
  margin: 15px;
}

ul#menulist, ul#menulist ul {
  list-style:none;
  margin:0;
  padding:0;
  width:13em;
  border: 1px solid;
   border-top-color: #BABABA;
   border-left-color: #BABABA;
   border-bottom-color: #67B289;
   border-right-color: #67B289;
  background-color: #A7E6C4;
}

ul#menulist ul{
  position:absolute;
  top:-1px;
  left:12.7em;
}

ul#menulist li{
  position:relative;
  margin:0px;
  padding:0px;
  _display:inline;
}

ul#menulist a{
  display:block;
  width:100%;
  text-decoration: none;
  text-indent: 1em;
  width: 12.7em;
  padding: 5px 0;
}

ul#menulist li:hover, ul#menulist li a:hover {
  color: #FFFFFF;
  background-color: #67B289;
}

ul#menulist li.smenu>a {
  font-style: italic;
}

ul#menulist a {
  color: #0F4D2A;
  text-decoration: none;
}

L’exemple situé ici est inspiré de ceci, mais il est plus joli et fonctionne uniquement sur les styles (pas d’ajout de « >>> »). La mise en forme ne se voit bien que sous des navigateurs récents (bien qu’il fonctionne sous IE sans avoir toutes ses subtilités visuelles). Sous les autres navigateurs, une flèche tourne lorsqu’on survole les éléments du menu.

J’ai préféré indiquer ci-dessus un exemple fonctionnant de manière vraiment similaire sous IE et les autres navigateurs.

Je trouve que dans cet exemple, l’utilisation de ce menu prend toute son ampleur.

Menu du secteur, menu de la rubrique courante, etc.

Il est très simple d’implémenter ce menu en exploitant le contexte de la page et en n’affichant que le secteur ou la rubrique courante. Il suffit de faire une boucle affichant le secteur courant ou la rubrique courante sous forme de liste.

Les exemples donnés ci-dessous correspondent à des boucles basiques sans tri et avec les styles basiques donnés au premier exemple.

Exemple de la rubrique courante

<ul id="menulist"><BOUCLE_menuspiprub(RUBRIQUES){id_rubrique}>
	<li><b><a href="#URL_RUBRIQUE">#TITRE</a></b></li>
	<BOUCLE_smenuspiprub(RUBRIQUES){id_parent}><li><a href="#URL_RUBRIQUE">#TITRE</a>
		<B_ssmenurub><ul>
			<BOUCLE_ssmenurub(boucle_smenuspiprub)></BOUCLE_ssmenurub>
		</ul></B_ssmenurubt>
	</li></BOUCLE_smenuspiprub>
</ul>

Exemple du secteur courant fonctionnant aussi bien dans une page affichant secteur, rubrique, article, breve, ...

Ce code peut être externalisé dans un fichier qu’on inclut en passant id_rubrique.

<BOUCLE_englob(RUBRIQUES){id_rubrique}>
<B_menuspip>
	<ul id="menulist"><BOUCLE_menuspip(HIERARCHIE){id_rubrique}{0,1}>
		<li><b><a href="#URL_RUBRIQUE">#TITRE</a></b></li>
		<BOUCLE_smenuspip(RUBRIQUES){id_parent}><li><a href="#URL_RUBRIQUE">#TITRE</a>
			<B_ssmenu><ul>
				<BOUCLE_ssmenu(boucle_smenuspip)></BOUCLE_ssmenu>
			</ul></B_ssmenu>
		</li></BOUCLE_smenuspip>
	</BOUCLE_menuspip>
	</ul>
</B_menuspip>
	<ul id="menulist"><BOUCLE_menuspipsect(RUBRIQUES){id_rubrique}>
		<li><b><a href="#URL_RUBRIQUE">#TITRE</a></b></li>
		<BOUCLE_smenuspipsect(RUBRIQUES){id_parent}><li><a href="#URL_RUBRIQUE">#TITRE</a>
			<B_ssmenusect><ul>
				<BOUCLE_ssmenusect(boucle_smenuspipsect)></BOUCLE_ssmenusect>
			</ul></B_ssmenusect>
		</li></BOUCLE_smenuspipsect>
	</ul>
<//B_menuspip>
</BOUCLE_englob>

Il est possible d’inclure les articles aussi, les brèves, etc... Tout dépend après de vos envies.

Les fichiers à télécharger

Le fichier javascript :

Javascript du menu déroulant

Un ensemble de fichiers prêts à l’emploi qu’il suffit d’inclure dans les squelettes par la commande <INCLURE(spip-ex-md-menu.php3)> (ou un autre nom si vous renommez les fichiers) :

  • Un couple php3/html de type spip [1]
  • Un fichier css soit à inclure dans l’entête de vos squelettes, soit à copier/coller dans votre propre CSS.
  • Ne pas oublier le javascript et le code à préciser au niveau du body.
  • Il est présenté ici
Un exemple prêt à l’emploi

A noter que cet exemple supprime les numéros et trie par numéro.

Notes

[1note admins : à adapter pour SPIP v1.9 et suite - plus de fichier php3

Discussion

26 discussions

  • 3

    bonjour,
    je suis nouvel utilisateur de spip et je voudrais savoir comment rajouter l’affichage des articles dans ce menu. Apparrement ce n’est pas sorcier il doit falloir rajouter une boucle, mais la j’avoue que je ne vois pas bien comment faire, j’attend donc votre aide avec impatience...
    Merci.

    • Ce n’est effectivement pas très compliqué. Essayes ça :

      <ul id="menulist">
      <BOUCLE_menu(RUBRIQUES){racine}>
        <li><a href="#URL_RUBRIQUE">#TITRE</a>
          <ul><B_sousmenu>
            <BOUCLE_sousmenu(RUBRIQUES){id_parent}>
              <li><a href="#URL_RUBRIQUE">#TITRE</a>
                <ul><BOUCLE_ssousmenu(boucle_sousmenu)></BOUCLE_ssousmenu>
                <BOUCLE_articlerub(ARTICLES){id_rubrique}>
                <li><a href="#URL_ARTICLE">#TITRE</a></li>
                </BOUCLE_articlerub></ul>
              </li>
            </BOUCLE_sousmenu>
          </B_sousmenu>
          <BOUCLE_articlessect(ARTICLES){id_rubrique}>
          <li><a href="#URL_ARTICLE">#TITRE</a></li>
          </BOUCLE_articlesect></ul>
        </li>
      </BOUCLE_menu>
      </ul>

      Je n’ai pas les éléments qu’il faut pour tester en local en ce moment. Préviens-moi si ça ne fonctionne pas, mais j’ai préféré essayer de te répondre rapidement.

    • il manque une s à la fermeture de .

    • il manque une s à la fermeture de

      </BOUCLE_article{{s}}sect>.

    Répondre à ce message

  • 2

    Bonjour,

    Je suis en train de chercher à mettre en oeuvre la « pseudo classe de texte » first-letter pour modifier la première lettre de chaque ligne du menu mais je galère un peu (spip et css ont moins d’un mois pour moi !!!) et pour l’instant ça marche pas.

    J’ai essayé de mettre ça dans la feuille de style :

    /* Mod lettrine*/
    ul#menu li:first-letter
    color : green ;
    font-size : 200%

    /* Fin Mod Lettrine */

    ça marche pas peut-être parce-que :
    « En effet, petit oubli : first-letter ne s’applique qu’au contenu d’un élément de type block, list-item, table-cell, table-caption et inline-block... Mais pas aux éléments inline.
    Pour conserver l’effet de first-letter : faire flotter les éléments li plutôt que de les mettre en inline. »

    Pouvez-vous me dire si le problème est bien celui-ci et s’il est possible de le résoudre.

    Merci d’avance de votre aide.

    Fabrice Cizeron

    • Il doit y avoir un lien directement sous li non ? Et en appliquant le first-letter sur a ça fonctionne mieux ? (genre ul#menu li a:first-letter - sans l’espace entre a et : créé par spip bien sûr).

      Y’a une page où on peut le voir ?

    • Super ça marche !
      Merci Miss Popi !

      La page que tu voulais , c’est mon site ? la voilà : (en cours de modif ) http://fabrice.cizeron.free.fr/SPIPcollege/

      Merci pour ton aide

      Fabrice

    Répondre à ce message

  • Bonjour,
    Tout d’abord je trouve cette contrib super efficace, on la retrouve d’ailleurs sur beaucoup de site sous spip. et moi même je ne m’en passe plus !
    Seulement voilà, sur un de mes sites, j’ai fait un menu vertical et un autre horizontal. Ca marche super bien sur firefox, sur safari, mais pas sur IE à cause du javascript qui ne marche que sur l’un ou l’autre des deux menus.
    au moment de charger le script je dois choisir le menu à charger ( body onload=« setHover(’menu’) » ) et je voudrais ajouter menu2 par exemple. j’ai essayer de les mettre dans la même balise séparée par une virgule mais dans ce cas il n’y en a toujours qu’un seul qui charge, et c’est le premier qui apparaît dans la syntaxe.

    Je pense qu’il doit y avoir une solution à ce problème, mais je dois surement pas chercher au bon endroit.

    Si quelqu’un a la solution... ou une proposition... Si ce que j’ai expliqué n’est pas claire, je peux toujours ajouter des précisions. Ceux qui sont intéréssés par l’affichage de deux menus peuvent toujours me contacter.

    Répondre à ce message

  • 1

    Bonjour,

    Que faut-il ajouter à ce script pour exclure les rubriques avec les mots clés.
    Merci de votre réponse.

    Cordialement

    MARC MEBTOUCHE

    • Le mieux est d’utiliser les doublons ou les doublons nommés en fonction de votre besoin (si vous utilisez déjà des doublons dans votre page, il faut utiliser les doublons nommés pour éviter le catapultage) !

      Vous faites une première boucle qui recherche les rubriques ayant ce mot-clé en lui ajoutant l’attribut {doublons} (ou un doublons nommé) et vous rajoutez le critère {doublons} (ou un doublons nommé) dans les boucles rubriques de cette contribution.

      Bon courage.

    Répondre à ce message

  • 2

    Bonjour,

    Avec l’exemple que tu donnes tu écris ceci :

    « Attention ce menu ne s’affiche pas à l’identique sous IE et Firefox (par exemple, tout navigateur respectant les standards), mais fonctionne parfaitement sous IE ! »

    Pas tout à fait. Avec IE, dès que l’on quitte un menu pour explorer sa descendance, celui-ci revient à sa couleur de base, ce qui fait perdre l’information du chemin d’accès. Sur Firefox et Safari par contre, ton exemple fonctionne parfaitement.

    • Il fonctionne sous IE. Il se déplie ! Les mots ont été soigneusement choisis.

      Je ne peux ni ne veux pas pallier aux faiblesses d’IE.

    • Je l’adopte quand même pour mon squelette (qui fonctionnait jusqu’à présent en Javascript avec coolmenus) car ce menu résoud bien des problèmes.

      Merci pour ta contribution, je ne manquerais pas de la mentionner.

      Marc

    Répondre à ce message

  • Bonjour,
    super le menu mais ...
    j’ai un problème pour l’integration des articles.
    Ils apparaissent simplement au 2e niveau , mais pas au 1er ni au 3e niveau ?
    Merci de votre aide .
    c’est visible sous 2 versions :
    http://antares-sellier.com/spip-ex-md-menuvertical.php3
    http://antares-sellier.com/spip-ex-md-menu.php3

    Répondre à ce message

  • 5

    Bonjour,

    J’ai utilisé votre script (depuis Spip-Contrib.net) pour le « Menu en cascade automatique (tout CSS + javascript pour IE) » et qui est tiré de votre site.

    Tout fonctionne très bien SAUF avec IE ... j’ai beau avoir rajouté la « fameuse » ligne dans le tag

    , soit <body onload="setHover('menulist')"> ... rien à faire, IE refuse systématiquement d’afficher les sous-rubriques et fait une faute sur la page (ligne:18 - celle où se trouve le tag body, Car:1, Erreur:Objet attendu, Code:0, URL:url du site)... j’en perds mon latin, mon grec et (presque) ma patience ...

    Note importante : je ne suis pas développeur professionnel ni amateur ... juste un bidouilleur du web comme beaucoup ;-)
    Si vous pouviez m’aider à résoudre ce petit bug, cela me ferait le plus grand plaisir.
    L’adresse (de test) du site est : http://www.pionnair-ge.com/spip1

    J’aurais après une deuxième question : comment « allonger » la largeur de la fenêtre faisant apparaître les sous-menus (sous-rubriques) dans votre script (dans la feuille css) ... je tourne en rond aussi.

    Mille mercis pour vos lumières et excellente journée,
    Stéphane

    • Stéphane

      Trouvé ! Le problème était que le fichier js était au mauvais endroit ... que de temps perdu pour une bêtise pareille ! J’ai encore beaucoup à apprendre...

    • Bonjour.

      Je suis confronté au même problème et je ne vois pas comment corriger le problème. Tu fais allusion au fichier javascript mal placé. C’est à dire ?

    • Il faut indiquer le lien vers le fichier en javascript entre

      et

      et ensuite bien indiqué son action au niveau du body.

      Tu mets ça :
      <script type="text/javascript" src="script/menuderoulant.js"></script>

      au même endroit que tu déclares tes CSS et tu remplace le code du body par :

      <body onload="setHover('menulist')">

    • Tout est bien a sa place, comme indiqué (fichier javascript, balise body modifiée, etc.). Ca marche très bien en local avec EasyPHP mais pas sur le site distant. Toujours la même erreur javascript.

      Pour ceux qui sont encore confrontés au même problème, j’ai trouvé la solution sur le site http://www.aidejavascript.com/article151.html

      Il faut remplacer le code du fichier javascript « menuderoulant.js » par celui-ci se trouvant sur le site ci-dessus et ça marche !

    • Merci pour ces infos, je ferais une modif de la contrib !

    Répondre à ce message

  • Bonjour,

    J’ai créé un menu CSS horizontal pour mon site sous SPIP...

    Celui-ci fonctionne relativement bien, mais j’ai de gros problèmes d’affichage... Le problème est que les éléments du sous-menu sont plus grands que les éléments du menu principal, résultat, lorsque je me positionne sur un élément du menu principal, tous les autres se décalent... pas très user-friendly !! De plus, la colonne dans laquelle se trouve le menu s’agrandit avec le nombre d’éléments de sous-menu (j’ai volontairemetn mis un border=1 pour que ça se remarque) et décale tout le reste du site vers le bas, ce qui n’est pas le comportement voulu...

    J’ai essayé de passer le positionnement du sous-menu en « absolute », ce qui donne le résultat espéré sous Mozilla, mais pas du tout sous IE... Les sous-menu s’affichent alors sur la droite du menu principal, plutôt qu’en dessous...

    J’espère que vous pourrez m’aider... L’adresse du site est http://test.loyers.be

    Merci d’avance

    Répondre à ce message

  • 8
    André P

    Bonjour,
    D’abord merci pour ce superbe menu. Je l’ai (un peu) adapté sur un site en construction Objectif et cela fonctionne bien pour rubrique et sous-rubrique. Malheureusement, si j’ajoute une sous-sous-rubrique, le menu déborde sur le texte (normal !) mais il y a un problème de transparence (texte du menu et de l’article sont sur lemême plan)
    Je suppose que c’est à régler dans la feuille de style du menu mais où ?

    Merci pour une aide éventuelle

    • Il faut que tu attribues des « profondeurs » à certains de tes div, que tu indiques lequel va au-dessus de l’autre.

      J’ai essayé en mettent « z-index : 2 ; » à div#principal et un « z-index : 100 ; » à div#navigation et ça fonctionne :-)

    • André P

      Et ca, c’est dans les pages html où je veux que le menu apparaisse ? C’est une commande html « z-index : 2 » ? Jamais vu... J’essaie et merci déjà.

      Le monde spip est fabuleux...

    • Non rajoute ça dans un de tes fichiers ccs :

      div#principal z-index : 2 ;
      div#navigation z-index : 100 ;

      Oui le monde SPIP est fantastique ;-)

    • Rhâââ j’ai encore été trop vite et j’ai oublié les raccourcis SPIP

      div#principal { z-index: 2; }
      div#navigation { z-index: 100; }
    • André P

      Super, ça marche en local sur firefox et ie.
      Merci beaucoup. Ce qui est génial avec spip (et eva spip) c’est qu’on peut essayer des trucs en amateur et il y a toujours un + spécialiste que toi qui peut de donner le coup de main.
      A+

    • bonjour,

      j’arrive pas a mettre le menu au dessus des autres elements de la page web meme avec le css. La question que je me pose c’est est ce que j’ai bien fai la bonne manip. Sinon pour utiliser le css il faut bien intégrer dans l’html

    • Il faut que tu le mettes soit dans un fichier CSS, soit entre dans le head de ta page.

    • j’ai encore été trop vite... pfffffffffff

      donc soit entre <style> et </style> dans le head de ta page.

    Répondre à ce message

  • 4

    Très sympa, très utile et très simple : bravo.

    Par contre ce menu est vertical, quid d’un menu horizontal ?

    merci

    A+

    • Comme c’est une liste, tout n’est affaire que de CSS après.

      Tu peux repartir de l’exemple donné par Jep sur ce menu de type application.

    • bonjour,

      Donc si j’ai bien compris, si on veut changer ce menu vertical en menu horizontal, il ne faut que modifier le css ? Sinon aurais tu un exemple de css pour menu horizontal car je suis un gros debutant tant en spip qu’en prog.

    • Si tu regardes le code source de la page indiquée ci-dessus le code CSS y est, tu n’as plus qu’à copier/coller et sur le body tu mets :

      <body onload="setHover('menu')">

    • Et sur le ul tu mets menu et pas menulist ^^ j’oubliais...

    Répondre à ce message

Ajouter un commentaire

Avant de faire part d’un problème sur un plugin X, merci de lire ce qui suit :

  • Désactiver tous les plugins que vous ne voulez pas tester afin de vous assurer que le bug vient bien du plugin X. Cela vous évitera d’écrire sur le forum d’une contribution qui n’est finalement pas en cause.
  • Cherchez et notez les numéros de version de tout ce qui est en place au moment du test :
    • version de SPIP, en bas de la partie privée
    • version du plugin testé et des éventuels plugins nécessités
    • version de PHP (exec=info en partie privée)
    • version de MySQL / SQLite
  • Si votre problème concerne la partie publique de votre site, donnez une URL où le bug est visible, pour que les gens puissent voir par eux-mêmes.
  • En cas de page blanche, merci d’activer l’affichage des erreurs, et d’indiquer ensuite l’erreur qui apparaît.

Merci d’avance pour les personnes qui vous aideront !

Par ailleurs, n’oubliez pas que les contributeurs et contributrices ont une vie en dehors de SPIP.

Qui êtes-vous ?
[Se connecter]

Pour afficher votre trombine avec votre message, enregistrez-la d’abord sur gravatar.com (gratuit et indolore) et n’oubliez pas d’indiquer votre adresse e-mail ici.

Ajoutez votre commentaire ici

Ce champ accepte les raccourcis SPIP {{gras}} {italique} -*liste [texte->url] <quote> <code> et le code HTML <q> <del> <ins>. Pour créer des paragraphes, laissez simplement des lignes vides.

Ajouter un document

Suivre les commentaires : RSS 2.0 | Atom