The Horizontal version of this menu is built with the headings <h2>'s
showing across the top, activating a first level drop drown when
hovered over, leading to further pop-outs, on hover, where necessary.
CSS Menus - Fluid and Accessible - Horizontal Tutorial
Horizontal CSS Dropdown and PopOut Menu
References:
- Technical Notes
- Grab the HTML
- Download the whatever:hover filefrom Peter Nederlof's site.
- Forget about Internet Explorer, IE, until I tell you to Remember
- Please view the interim samples in a CSS compliant browser (Firefox or Opera), not IE again until I say so ;)
To The CSS
The Horizontal version of this menu is built with the headings <h2>'s
showing across the top, activating a first level drop drown when
hovered over, leading to further pop-outs, on hover, where necessary.
Firstly this time the #menu div is still our
"container" only this time we want it to be 100% wide, so we could
leave it as it is because it would default to this. However to properly
contain the floated child lists if we also float the #menu div is will stretch to contain its floated children.
We then need to set the required dropdown width but this time it goes directly onto the <ul>
elements themselves, and the need to be floated in order to appear side
by side. We also still need to remove all the default padding, margins
and bullets from the <ul>s the same as before.
#menu {
width: 100%;
background: #eee;
float: left;
}
#menu ul {
list-style: none;
margin: 0;
padding: 0;
width: 12em;
float: left;
}
Showing the three lists in horizontal alignment because they're
floated, the background color is only for demo to show the container
actually stretching, it can be removed later.
Then we apply the required formatting to the <h2> headings and the <a> anchors, again I'm using the same formatting as the vertical menu
#menu a, #menu h2 {
font: bold 11px/16px arial, helvetica, sans-serif;
display: block;
border-width: 1px;
border-style: solid;
border-color: #ccc #888 #555 #bbb;
margin: 0;
padding: 2px 3px;
}
#menu h2 {
color: #fff;
background: #000;
text-transform: uppercase;
}
#menu a {
color: #000;
background: #efefef;
text-decoration: none;
}
#menu a:hover {
color: #a00;
background: #fff;
}
Which now shows the three,top level choices neatly in a line with all their vertical lists below them. - If it didn't did you forget I told you not to view in IE until the end!, try again in a non-IE Browser please..
Positioning the Pop-out Drops
The First level Drop Down Menus are already in the correct place, so
we don't need to position then, but we need to position the children,
nested lists, of these choices absolutely again, so just like the
vertical version we need to make the parent <li> elements into containing blocks for these absolutely positioned children, which is doing by placing position: relative; onto the parent <li>'s and again because we are not using offset co-ordinates to actually move these <li> elements we can apply it globally.
Then we need to select all <ul> elements that have at least TWO parent <ul>'s
again in order to move them over into their pop out position. This time
we do not need to set the width here as we already set the width on all
<ul> elements to 12em so this will take that width too by order of the cascade.
#menu li {position: relative;}
#menu ul ul ul {
position: absolute;
top: 0;
left: 100%;
}
Now the lists are all in position, in a non-IE Browser for results.
However now, which is not apparent yet in these simple demo pages,
we have a problem if there is text underneath this navigation bar,
which there would most likely be in a real page.
Because we have left the first child list "in the flow" of the
document rather than position it for pop-out purposes it is actually
pushing any following text down below it. Normally in these drop down
scenarios we would want it to drop down over the top of on any existing text.
We can do this by pulling it out of the flow using absolute
positioning again, only this time we don't want to give it any offset
co-ordinates, because we're actually happy with where it is, and just
in case we'll give it a high z-index to ensure it and it's children
actually do appear over the top of any positioned text that may follow.
#menu ul ul {
position: absolute;
z-index: 500;
}
Hiding and Revealing using :hover
First let's hide all those "drop and pop" menus using the display property.
A "Remember IE" Moment
This is where we have to get more specific with the CSS than we
should have to be because of IE. We cannot use Child Selectors so we
will do it longhand, it's OK, this way will still work for other
browsers too.
Also due to working with an older csshover.htc file
while developing these menus we became aware that IE5.x required a more
specific element selector or the menus just didn't work in those
browsers. The behavior file has now been updated to address this issue,
so using this fix is no longer required.
Although a point to note: In our testing/development of these menus
we found that leaving the CSS workaround in place improved IE's
performance on larger menus. The choice is yours, I'll leave it in this
demo CSS.
This time we actually do want to hide the second level menu (top choice) as we only want the <h2>
heading to remain visible offering the top level choices as a dropdown,
and then any further choices as popouts, so we need to target all <ul>'s that have at least ONE parent <ul> which will leaving out the heading list because it doesn't have a parent.
div#menu ul ul {
display: none;
}
Again that was the easy bit, so let's get to revealing them again.
Again the convoluted CSS to keep IE happy, this time when we hover over the first <li> which is in fact the heading too we want the child lists to appear
div#menu ul li:hover ul
{display: block;}
In this demo we require 3 levels of hover to activate child menus so we have three levels to counteract also.
div#menu ul ul,
div#menu ul li:hover ul ul,
div#menu ul ul li:hover ul ul
{display: none;}
div#menu ul li:hover ul,
div#menu ul ul li:hover ul,
div#menu ul ul ul li:hover ul
{display: block;}
the display: block; rules show the three levels being activated with the display: none; rules being entered afterwards to more specifically hide the unwanted (deeper nested) lists (counteract them).
Now It's IE's Time again!
This time if that last sample is viewed in IE it doesn't look so bad
except for the unnecessary whitespace between the nav bar and the text,
however we know the hovers are not activating so let's call the Majic Ingredient again, the csshover.htc file
body {
behavior: url(csshover.htc);
}
Now when you look at in IE, the hovers are working, but there are still a few other things still wrong with it
- whitespace between the list items
- the anchor hover background change only works of the link text itself is hovered over, it should happen on the whole block
- You cannot increase or decrease the size of the text
- The first hover is moving the list down even though we absolutely positioned it to take it out of the flow
A lot of that list is exactly the same as the problems in the vertical list,
namely the font-sizing issue, the whitespace problem and the anchor
block problem. So let's deal with them first in exactly the same way we
did there ~ Same problems = Same Solutions.
The complete conditional CSS is the same as the vertical menu's code and looks like this:
<!--[if IE]>
<style type="text/css" media="screen">
body {
behavior: url(csshover.htc);
font-size: 100%;
}
#menu ul li {float: left; width: 100%;}
#menu ul li a {height: 1%;}
#menu a, #menu h2 {
font: bold 0.7em/1.4em arial, helvetica, sans-serif;
}
</style>
<![endif]-->
One problem that we didn't apparently deal with is the first list is
now respecting the position absolute, you'll have to take my word for
it until you view the link below, but
we dealt with it! The dimension (1%) on the <li>
element took care of that too, IE is a strange creature at times, but
once you realise that a lot of its problems are inter-related it's
easier to understand that one fix often suits all.
Summary
So that's it there has been some nuances left out like background
images etc.. but the basics of hover, positioning and getting it to be
compatible with IE/Windows 5+, were the major requirements here.
What we have here is the bare bones of any particular style of
dropdown you would like to create, background images can be used to
spice it up, but most of all the HTML has remained clean throughout
meaning it's very accessible to all UA's and Search Engine spiders.
The other main thing I would say is that please always develop in a
non-IE environment as IE workarounds are unfortunately as necessary as
CSS hacks were a couple of years ago. I hope you see that CSS driven
menus are firmly within our grasp because we can work around IE quite
easily and it's foibles can usually always be fixed especially when
sticking to CSS2 properties.
|