Mailform   Sitemap   About   Print view   Deutsch Français Nederlands

CMSimple_XH Plugins

Last update:
July 07, 2016, 19:40

 

Horizontal drop down menu

 
The basic menu call

The standard menu call in CMSimple_XH templates is:

<?php echo toc();?>

When we call this here on this page, the result is:

The html of it is:


<ul class="menulevel1">
<li class="docs"><a href="/en/?Welcome">Welcome</a></li>
<li class="sdocs"><a href="/en/?Tutorials">Tutorials</a>
<ul class="menulevel2">
<li class="sdoc"><span>Horizontal drop down menu</span></li>
<li class="doc"><a href="/en/?Tutorials/Search-Engine-Optimization">Search Engine Optimization</a></li>
</ul>
</li>
</ul>

So we get an unordered list where only the subpages of the actual page are listed. This is useful only for a simple vertical menu.

 
Another menu call

In a horizontal drop down menu the complete menu structure has to be always there, with the submenus normally hidden and made visible only through the css hover function. So to start we need a call in the template which gives us the complete menu. This is:

<?php echo li($hc,1);?>

The function li() returns an unordered list which is a menu for the pages of the website. It has 2 parameters, the 1st should be an array of page numbers of the pages which appear in the menu and the 2nd the menu level to start with.

As 1st parameter we take $hc, which is the array of the page numbers to be shown in the menu (i.e. counted without hidden pages) and the actual page numbers (i.e. counted with hidden pages). li($hc,1) thus gives us what we want, i.e. an unordered list, where the list items are the menu items:

The html produced looks like this:

<ul class="menulevel1">
<li class="docs"><a href="/en/?Welcome">Welcome</a>
<ul class="menulevel2">
<li class="docs"><a href="/en/?Welcome/Calendar">Calendar</a>
<ul class="menulevel3">
<li class="doc"><a href="/en/?Welcome/Calendar/Events">Events</a></li>
</ul>
</li>
<li class="doc"><a href="/en/?Welcome/Downloadcontrol">Downloadcontrol</a></li>
<li class="doc"><a href="/en/?Welcome/Expandcontract">Expandcontract</a></li>
<li class="doc"><a href="/en/?Welcome/Flexslider">Flexslider</a></li>
<li class="doc"><a href="/en/?Welcome/Memberpages">Memberpages</a></li>
<li class="doc"><a href="/en/?Welcome/Miniblog">Miniblog</a></li>
<li class="doc"><a href="/en/?Welcome/Morepagedata">Morepagedata</a></li>
<li class="doc"><a href="/en/?Welcome/Legendbox">Legendbox</a></li>
<li class="doc"><a href="/en/?Welcome/Protected-Download">Protected Download</a></li>
<li class="doc"><a href="/en/?Welcome/Quoteoftheday">Quoteoftheday</a></li>
<li class="doc"><a href="/en/?Welcome/Teaser">Teaser</a></li>
</ul>
</li>
<li class="sdocs"><a href="/en/?Tutorials">Tutorials</a>
<ul class="menulevel2">
<li class="sdoc"><span>Horizontal drop down menu</span></li>
<li class="doc"><a href="/en/?Tutorials/Search-Engine-Optimization">Search Engine Optimization</a></li>
</ul>
</li>
</ul>
 
Developing the css
Step 1

With css styling we can convert this into a horizontal drop down menu. For convenience we put it into a div with the class name "menu". We begin the css with eliminating the list styling and the padding and margins which different browsers give to lists:

.menu ul {
    list-style-type: none;
    padding: 0;
    margin: 0;
}

Now we hide the secondary levels with visibility: hidden; additionally they must be taken out of the normal flow of html elements, so that they later can reappear on top of other elements. Therefore we add position:absolute;. Later we will refine this a bit more.

.menu ul ul {
     visibility: hidden;
     position: absolute;
}

The 1st level menu items are then positioned next to each other by float:left;. A little margin between the floats has to be given. The position:relative; is given, because the second hidden level is absolute positioned, and this positioning starts from the next higher relative positioned element.

If there are long headings consisting of several words, these should not be divided at the end of a line, so white-space:nowrap; has been added.

As CMSimple_XH gives the unordered menu list automatically the class "menulevel" followed by the level nr, we use this class name:

.menu ul.menulevel1 li {
    float:left;
    margin-right: 1em;
    position:relative;
    white-space: nowrap;
}

Now we don't get much, as all secondary levels are hidden:

 
 
Step 2

The first level still needs a bit more styling. The links should not have a special color nor an underline, and if they are blocks, it is easier to reach them with the cursor. The cursor should trigger some action, starting with a color change.

.menu ul li a {
    display:block;
    color:black;
    text-decoration: none;
}
.menu ul li a:hover {
    color:blue;
}

Thus we get the following, which represents already the final look of the menu without the drop down effect:

 
 
Step 3

Now let us make the second level appear. First we refine this second hidden and absolute positioned level a bit more with width, background, z-index. Width is just for convenience, but background is important as without background the underlying elements will be visible, and z-index is necessary to put the hovering secondary level on top of other elements. This z-index works also for the following levels, putting them on top if they appear. 

On hover the hidden sub level should appear, however only one sublevel, not all, therefore ">" is used.

The list items of the second levels need a definite width, for instance the same width as the surronding ul, i.e. 150px. This width determines the positioning of the 3rd level.

Long headings consisting of several words, which may appear in sublevels, should be allowed to break into several lines, therefore the white-space: nowrap; of the 1st level has to be reset.

.menu ul ul {
    visibility: hidden;
    position: absolute;
    width:150px;
    background:white;
    z-index:1;
}
.menu li:hover > ul {
    visibility: visible;
}
.menu ul ul li {
    width:150px;
    white-space: normal;
}

Now we alredy get a nice drop down effect. However the 3rd level has not been taken care of. It now appears on top of menu elements of the 2nd level:
 
 
Step 4

The 3rd level is taken care of by positioning it left:150px;, this is the width of the 2nd level list elements. The 3rd level also needs top:0; to start at the correct height, otherwise it will be positioned one line below the hovering cursor.

.menu ul ul ul {
    left:150px;
    top:0;
}

So finally we get our complete horizontal drop down menu.

 
 
Conclusion

Of course you will want to embellish this with background, borders, margins, shadows, rounded corners, etc. Usually this means quite some experimentation.

The bare minimum css to start with is:

.menu ul {
    list-style-type: none;
    padding: 0;
    margin: 0;
}
.menu ul.menulevel1 li {
    float:left;
    margin-right: 1em;
    position:relative;
    white-space: nowrap;
}
.menu ul li a:hover {
    color:blue;
}
.menu ul ul {
    visibility: hidden;
    position: absolute;
    width:150px;
    background:white;
    z-index:1;
}
.menu li:hover > ul {
    visibility: visible;
}
.menu ul ul li {
    width:150px;
    white-space: normal;
}
.menu ul ul ul {
    left:150px;
    top:0;
}

top