Creating Drop-Down MenusNow we need to take our horizontal list a step further and add drop-down choices. CSS-based drop-down menus aren't going to work in Internet Explorer for Mac. I will, however, show you a way you can use CSS so that your menu degrades nicely in this browser and still offers the user an acceptable navigation experience. In the following exercise, we'll assume that the horizontal menu items each have a related page, and we'll code their responses accordingly. All you need to do is add URLs in place of the # symbols in each link's HRef. Marking Up Drop-Down MenusTo mark up a drop-down menu, we need to nest a complete list within a list item of the horizontal menu. This nested list becomes the contents of that list item's drop-down menu. Figure 7.21 shows the finished menu so you can see what you are shooting for. Figure 7.21. Here's your completed drop-down menu.Here's the complete markup for a menu with four choices, each with a drop-down <body> <div id="listcontainer" class="clearfix"> <ul> <li><a href="#">Customers</a> <ul> <!-- drop down menu items --> <li><a href="#">Our Services</a></li> <li><a href="#">FAQs</a></li> <li><a href="#">Sign Up</a></li> <li><a href="#">Support</a></li> </ul> </li> <li><a href="#">Members</a> <ul> <!-- drop-down menu items--> <li><a href="#">Benefits</a></li> <li><a href="#">Programs</a></li> <li><a href="#">Renewals</a></li> <li><a href="#">Questions?</a></li> </ul> </li> <li><a href="#">Dealers</a> <ul> <!-- drop down menu items--> <li><a href="#">Join us</a></li> <li><a href="#">Programs</a></li> <li><a href="#">National Network Map</a></li> <li><a href="#">Support</a></li> </ul> </li> <li><a href="#">Distributors</a> <ul> <!-- drop down menu items--> <li><a href="#">Products</a></li> <li><a href="#">Dealer Finder</a></li> <li><a href="#">Commissions</a></li> <li><a href="#">Customers</a></li> </ul> </li> </ul> </div> </body> Here are a couple of notes about the markup:
Let's start simply. Instead of working immediately with the final markup earlier in this section, start with the horizontal navigation markup, which has a sublist added to only the first li. You will add the other nested lists after you have one menu working correctly. Here's the markup <body> <div id="listcontainer" class="clearfix"> <ul> <li><a href="#">Customers</a> <ul> <!-- drop down-down menu items --> <li><a href="#">Our Services</a></li> <li><a href="#">FAQs</a></li> <li><a href="#">Sign Up</a></li> <li><a href="#">Support</a></li> </ul> </li> <li><a href="#">Members</a></li> <li><a href="#">Dealers</a></li> <li><a href="#">Distributors</a></li> </ul> </div> </body> Now take a look at Figure 7.22. Figure 7.22. The submenu is not stacked like a drop-down yet, but it is inheriting the styles from the parent list, as shown when you point at a link.We need some styles specifically for the drop-down menu to get it to stack under its parent element. Instead of adding a class or ID to the submenu so we can target it, just write a selector that only affects a list that is within a list. For example, the selector ul li ul {…some CSS here…} only targets a ul element that is contained within the li element of a parent listjust what we want. As you can see in the following code, just three simple CSS declarations get you well on the way to the desired result div#listmenu ul li ul { <-- a margin:0; <-- b width:10em; <-- c } div#listmenu ul li ul li { width:100%; <-- d } <-- e
Now take a look at Figure 7.23. Figure 7.23. Although this menu needs better styling and doesn't yet open and close automatically, it is starting to look like a drop-down menu.If we set the width of the ul of the nested list, and then force the li elements within to be 100 percent of that width, they stack nicely. Without the 100 percent width on the li, the short words, "FAQs" and "Sign Up," would be on the same line, and each li element would be a different length. The next step is to get drop-downs correctly positioned with respect to the menu. The way to do this is to set the child element's position property to absolute and the parent's to relative. At the same time, we'll want to correctly style the drop-down's borders, so we can see that the drop-down is, in fact, accurately aligned to the menu. Here's the code div#listmenu li { float:left; <-- a position:relative; <-- b list-style-type:none; background-color:#FFA; border-right:1px solid #069; } div#listmenu ul li ul { margin:0; position:absolute; <-- c width:10em; } div#listmenu ul li ul li { width:100%; <-- d border-left:1px solid #069; <-- e border-bottom:1px solid #069; border-right:1px solid #069; } div#listmenu ul li ul li:first-child { border-top:1px solid #069; <-- f }
Now take a look at Figure 7.24. Figure 7.24. With the contextual positioning set, and the borders styled, you can see that the alignment of the drop-down to the menu is almost perfect.The drop-down is 1 pixel off because it aligns with the list item, not the list item's border, but because its positioning context is now its parent element (its position is set to absolute, the parent to relative), it's just a matter of defining a left offset to nudge it into the correct location. Here's what to do div#listmenu ul li ul { margin:0; position:absolute; width:10em; left:-1px; <-- a }
Now look at Figure 7.25. Figure 7.25. Now the drop-down is correctly positioned under the menu.With the exception of some styling problems in Internet Explorer (a missing top line, and the inherited left ul border from an earlier hack) that we will fix later, the drop-down is now nicely styled, and we're ready to make it visible only when the pointer is over the appropriate choice of the menu. In the horizontal menu, the element that changes is the one that is being hovered over, but in the case of the drop-down menu, that's not true. The drop-down should display when its parent menu (the choice on the horizontal menu) is hovered over. A brilliantly simple selector makes that happen. First, hide the drop-down when it's not being hovered over, like this body div#listcontainer ul li ul {display:none;} Display is inherited, so all the list items within the ul disappear too. With the drop-down hidden, next make it appear when the drop-down's menu choice is hovered, like this div#listcontainer ul li:hover ul {display:block;} This selector states that the drop-down ul should display when its parent li is hovered over. However, we also want the menu to remain visible when we move off the parent menu choice and onto the drop-down itself. To do so, group a second selector with the display:block declaration like this
div#listcontainer ul li:hover ul, div#listcontainer ul li ul:hover {display:block;}
Now the menu is displayed is when you hover over either the menu or the drop-down, and your menu springs to life (Figure 7.26). Figure 7.26. When the menu is hovered over, the drop-down displays. The menu remains highlighted while the user moves on to the drop-down.Now perform the fixes for Internet Explorer, like this * html div#listmenu ul li ul { <-- a border-top:1px solid #069; border-left:0px; <-- b }
Now Internet Explorer displays the drop-down as other browsers do. One thing you'll notice is that the drop-down text doesn't highlight when you are on a drop-down list item, only when you are on the text itself. Let's deal with that next. To deal with this, you might think you would need to set the drop-down links to block, but as it turns out, you have to set the parent (the menu) links to block for all browsers at this point. Here's how it works div#listmenu a { display:block; <-- a padding:0 6px; <-- b text-decoration:none; <-- c color:#069; <-- d }
Now you'll see Figure 7.27. Figure 7.27. Now the links highlight when the pointer moves over the list items.So now we can remove the Internet Explorer hack from the horizontal menu exercise that set the menu links to block; it turns out we need that setting for all browsers. You'll delete this line of code
* html a {display:block;} We now have drop-down menus built from basic list markup and without a line of JavaScript in sight. |