Reorienting the Menus


So far, we've managed to create a good multilevel menu system in which each submenu opens up to the right of its parent. That's great if the navigation is going to be in the sidebar, but what if it isn't? What if we want the main-level navigation to be a horizontal toolbar across the top of the page? Good news: With some small style adjustments and a few extra rules, we can do exactly that with the same markup we're already using.

Reorientation

Before anything else, let's rework the styles so that the main-level links are shown as a horizontal toolbar. This will require very few changes, as it happens. The first thing to do is strip out the width declarations from the div#nav and div#nav ul rules.

 div#nav {float: left; margin: -1px 0 0  1px;   background: #FDD;} div#nav ul {margin: 0; padding: 0; background: white;   border: 1px solid #AAA;} 

Removals

graphics/note_icon.jpg

We don't see any code changes here because we've just removed stuff. Compare this code block to the same rule in Listing 6.4 if the changes aren't clear.


This will let the div and the lists within the div autosize themselves. Don't worry we'll fix that for the menus themselves in a moment. Right now, though, we can't have a horizontal toolbar unless we let the toolbar set its own width.

To place the toolbar across the top of the main content, we'll change its left margin.

 div#nav {float: left; margin: -1px 0 0 7em;   background: #FDD;} 

This will push the left edge of the toolbar over a distance equal to the width of the main content's left margin.

Because the navigation div is floated and has no explicit width, it "autosizes" itself to wrap around its content. (This is also known as "shrink-wrapping.") If we float them and we are going to float them the same will be true of the list items within the menus, including those at the top level. For some applications, this might be acceptable, but here we're going to want them all to be the same width. Why not 7em? It's worked well enough so far.

 div#nav li {position: relative; list-style: none; margin: 0;   float: left; width: 7em;   border-bottom: 1px solid #CCC;} 

Why did we float the list items? So they'd line up horizontally. If we didn't float them, we'd end up with a vertical list of links like we had before.

Now here's why we want those list items all to be the same width: The menus that drop down from the main level will need to be consistent widths. If not, the menu might be wider or narrower than the top-level link that made it appear. So we'll add a width to the lists that are second level or lower by way of the div#nav ul ul rule, and at the same time take out the top and left declarations.

 div#nav ul ul {position: absolute; width: 7em;   display: none;} 

These few small changes, taken together, give us the result shown in Figure 6.12.

Figure 6.12. Reorienting the menu system to be a horizontal toolbar.

graphics/06fig12.jpg

There are six things to note in Figure 6.12:

  • The main content is wrapping around the floated div. We'll want to make sure it's pushed below the toolbar.

  • The light red background of the navigation div is back. That's because we have an unordered list that has no normal-flow content; all its list items are floated, and all its descendant lists are positioned. Therefore, the ul has collapsed to have zero height, and the div's background becomes visible.

  • For the same reasons, the top-level ul element has no height, and the thick gray bar along the top is actually the top and bottom borders of the ul smashed up next to each other. The div stretches around the list items because it's floated, and floats stretch to contain floats that they contain.

  • The bottom border of the list items is what creates the border along the bottom edge of the toolbar.

  • The second-level menus appear exactly where we want them. This happens because they're still being positioned with respect to their containing list items. The reason they appear at the bottom edge of the list items is that they have a top of auto. (Remember, we took out the top declaration, and the default value of top is auto.). In this case, the top of the positioned element is placed where it would have been if the element weren't positioned. So the submenus show up right where they would have if there were no positioning in effect.

  • The autoplacement discussed in the preceding point is happening for the sub-submenus as well, so they end up overlapping their parent submenus. We'll need to fix that.

The Seventh

graphics/warning_icon.jpg

In IE/Win, there's a seventh thing to note: The left margin of the navigation bar has been doubled. This is due to a bug in IE/Win that causes it to double margins on floats for no discernable reason. Since the only difference between the figures and IE/Win should be in its placement of the navigation links, we're going to ignore this error for the rest of the project.


Let's address these points in order.

Starting the Fixes

The easiest thing to fix is the main content wrapping around the toolbar. Rather than use clear, which would push down the entire content div (including the left border), we'll just bump up the top padding. The list items are about 1.5em tall, so we'll go slightly larger than that.

 #main {color: #CCC; margin-left: 7em; padding: 2em 0 1px 5%;   border-left: 1px solid;} 

This will push the top of the first paragraph's content down by 3em because there's 2em of top padding on the div and 1em of top margin on the paragraph.

Now to erase the red background. We want a border to stretch around the links in the toolbar and give the whole thing a white background. Since the div itself is already stretching around the top-level links, we'll change its background and add a border (see Figure 6.13).

 div#nav {float: left; margin: -1px 0 0 7em;   background: #FFF; border: 1px solid #AAA;} 
Figure 6.13. Pushing the main content past the toolbar and adding a background and border to the navigation div.

graphics/06fig13.jpg

Notice the thick gray border still appearing along the top of the toolbar? That's the ul border still hanging around. We could just remove the border from ul elements entirely, but that would cause a problem: The submenus would have no borders.

Instead, we'll lighten up the border just a bit and remove the top and bottom borders by setting their widths to zero.

 div#nav ul {margin: 0; padding: 0; background: white;   border: 1px solid #CCC; border-width: 0 1px;} 

This will still give the submenus right and left borders, and for the top-level ul, no border will appear because the borders that have width have no height (since the element itself has no height).

Now, what about the bottom borders of the submenus? Those are handled by the bottom border of the list items. Visually speaking, there is no difference. Where the bottom border of list items might be considered a problem is along the bottom edge of the toolbar where the list item borders sit up against the bottom border of the navigation div. We can get rid of that by removing the border declaration from the div#nav li rule.

 div#nav li {position: relative; list-style: none; margin: 0;   float: left; width: 7em;} 

But this will also remove the bottom borders from the submenu list items, and we've already established that we need those. So we'll add the borders back in for submenus with this rule.

 div#nav ul ul {position: absolute; width: 7em;   display: none;} div#nav ul ul li {border-bottom: 1px solid #CCC;} div#nav ul.level1 li.submenu:hover ul.level2, div#nav ul.level2 li.submenu:hover ul.level3 {display:block;} 

There's one more thing to fix at the top level: the arrow image. Having a right-pointing arrow doesn't really make sense anymore because the menus drop down, not pop out to the right. As long as we have an image of a downward pointing arrow (called, let's say, dropmenu.gif), we only need to change a single rule (see Figure 6.14).

 div#nav li.submenu {background: url(dropmenu.gif) 95% 50% no-repeat;} 
Figure 6.14. Corrections to the borders and a new arrow image.

graphics/06fig14.jpg

Submenu Corrections

As you probably noticed in Figure 6.14, things are great at the top level but are not so great in the submenus. For one, the "Tutorials" entry has a downward-pointing arrow thanks to the last change we made. For another, the "Tutorials" submenu is still overlapping with the end of the "Publications" menu. Both need to be fixed.

The arrow is simple to fix. Well, really, both fixes are simple, but the arrow fix is simpler. All we have to do is drop the original background image (submenu.gif) into the background of any submenu list item that's descended from another submenu list item. This won't apply to the top-level links that contain submenus because they aren't descended from other submenu list items.

 div#nav ul ul li {border-bottom: 1px solid #CCC;} div#nav li.submenu li.submenu {background-image: url(submenu.gif);} div#nav ul.level1 li.submenu:hover ul.level2, div#nav ul.level2 li.submenu:hover ul.level3 {display:block;} 

At least, that would be all we'd have to do if it weren't for a bug in the script we're using for IE/Win. It apparently resets all the background styles to their defaults when an element is hovered, so sticking with that last change means that the arrow will tile throughout the whole background of the submenu. So, we'll make sure it gets the right message by declaring all the values again.

 div#nav li.submenu li.submenu {background: url(submenu.gif) 95% 50% no-repeat;} div#nav li.submenu li.submenu:hover {background-color: #EDD;} div#nav ul.level1 li.submenu:hover ul.level2, div#nav ul.level2 li.submenu:hover ul.level3 {display:block;} 

That fixes up the problem rather nicely.

Now for the placement of the sub-submenus. Actually, let's place the submenus first. We want their top to line up with the bottom of the top-level list items, like they do now, except we want to explicitly express that behavior. Also, we want the left side of the submenu's content to line up with the left edge of the list item's content. Because the submenu has a left border and the top-level list items don't, the content of the submenu is actually one pixel to the right. So we'll use a negative left value to compensate.

 div#nav ul.level1 li.submenu:hover ul.level2, div#nav ul.level2 li.submenu:hover ul.level3 {display:block;} div#nav ul.level2 {top: 1.5em; left: -1px;} </style> 

The top value is set to match the sum of the top-level list item's font-size and top and bottom padding, but only if the height of each list item's line is exactly 1em tall. We haven't said that explicitly, and we need to do so. Therefore,

 div#nav li {position: relative; list-style: none; margin: 0;   float: left; width: 7em; line-height: 1em;} 

Now we just need to position the sub-submenus correctly. For these, we want the top edges to line up and the sub-submenu to appear just to the left of its parent entry. So we'll bring back the left: 7em; that we used in the first half of the project and use a negative top value to pull the menu up to where we want it.

 div#nav ul.level2 {top: 1.5em; left: -1px;} div#nav ul.level3 {top: -1px; left: 7em;} </style> 

One more thing and we're done. Remember the change to borders that caused the top border to be taken away from submenus? That applies to sub-submenus as well, so we have to apply one to get the result shown in Figure 6.15.

 div#nav ul.level3 {top: -1px; left: 7em;   border-top: 1px solid #CCC;} 
Figure 6.15. Polishing up the submenus and sub-submenus.

graphics/06fig15.jpg

With that, we arrive at the style sheet shown in Listing 6.5.

Listing 6.5. Toolbar-Oriented Menu System Style Sheet
 body {background: #EEE; color: #000;   behavior: url(csshover.htc);} /* WinIE behavior call */ h1 {color: #AAA; border-bottom: 1px solid; margin-bottom: 0;} #main {color: #CCC; margin-left: 7em; padding: 2em 0 1px 5%;   border-left: 1px solid;} div#nav {float: left; margin: -1px 0 0 7em;   background: #FFF; border: 1px solid #AAA;} div#nav ul {margin: 0; padding: 0; background: white;   border: 1px solid #CCC; border-width: 0 1px;} div#nav li {position: relative; list-style: none; margin: 0;   float: left; width: 7em; line-height: 1em;} div#nav li:hover {background: #EBB;} div#nav li.submenu {background: url(dropmenu.gif) 95% 50% no-repeat;} div#nav li.submenu:hover {background-color: #EDD;} div#nav li a {display: block; padding: 0.25em 0 0.25em 0.5em;   text-decoration: none; width: 6.5em;} div#nav>ul a {width: auto;} div#nav ul ul {position: absolute; width: 7em;   display: none;} div#nav ul ul li {border-bottom: 1px solid #CCC;} div#nav li.submenu li.submenu {background-image: url(submenu.gif);} div#nav ul.level1 li.submenu:hover ul.level2, div#nav ul.level2 li.submenu:hover ul.level3 {display:block;} div#nav ul.level2 {top: 1.5em; left: -1px;} div#nav ul.level3 {top: -1px; left: 7em;   border-top: 1px solid #CCC;} 


More Eric Meyer on CSS
More Eric Meyer on CSS (Voices That Matter)
ISBN: 0735714258
EAN: 2147483647
Year: 2006
Pages: 109
Authors: Eric Meyer

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net