Wednesday 27 November 2013

CSS3.0 Dropdown Menu

For all the menus on this page we use the same HTML template, which looks as follows:

<div id='cssmenu'>
  <ul>
     <li class='active'><a href='index.html'>Home</a></li>
     <li class='has-sub '><a href='#'>Products</a>
        <ul>
           <li class='has-sub '><a href='#'>Product 1</a>
              <ul>
                 <li><a href='#'>Sub Item</a></li>
                 <li><a href='#'>Sub Item</a></li>
              </ul>
           </li>
           <li class='has-sub '><a href='#'>Product 2</a>
              <ul>
                 <li><a href='#'>Sub Item</a></li>
                 <li><a href='#'>Sub Item</a></li>
              </ul>
           </li>
        </ul>
     </li>
     <li><a href='#'>About</a></li>
     <li><a href='#'>Contact</a></li>
  </ul>
</div>
We contain everything within a div with the id of "cssmenu". Inside, we find our list of menu items, one of which contain its own list, which in turn contains a final 3rd level item. You'll notice that the menus with submenus have a .has-sub class, which lets us target these for some extra CSS goodies. We also have a.active class for use when you have a certain page that should keep that specific item highlighted in some way (usually resembling the hover state).

CSS Base

@charset "UTF-8";
@import url(http://fonts.googleapis.com/css?family=Oxygen+Mono);

#cssmenu {padding: 0; margin: 0; border: 0;}
#cssmenu ul, #cssmenu li {list-style: none; margin: 0; padding: 0;}
#cssmenu ul {position: relative; z-index: 597; }
#cssmenu ul li { float: left; min-height: 1px; vertical-align: middle;}
#cssmenu ul li.hover,
#cssmenu ul li:hover {position: relative; z-index: 599; cursor: default;}
#cssmenu ul ul {visibility: hidden; position: absolute; top: 100%; left: 0; z-index: 598; width: 100%;}
#cssmenu ul ul li {float: none;}
#cssmenu ul ul ul {top: 0; left: auto; right: -99.5%; }
#cssmenu ul li:hover > ul { visibility: visible;}
#cssmenu ul ul {bottom: 0; left: 0;}
#cssmenu ul ul {margin-top: 0; }
#cssmenu ul ul li {font-weight: normal;}
#cssmenu a { display: block; line-height: 1em; text-decoration: none; }
Our first line here simply sets our character encoding to the lovely UTF-8 (so we can basically use any character we want in the file). Our second line adds the great Oxygen Mono font from Google's free web font service. Everything that follows is just the rough template for a horizontal dropdown. Resets, positioning, and a couple other extras are most of what you see. With everything thus far, you have a totally plain but functional drop down menu.
Plain Dropdown

Style Time

Now, this is the Flat Dropdown Tutorial, not the "ugly functional dropdown tutorial", so it's time to give our dropdown the proper look. Flat design is generally minimalistic in nature, and in the case of our dropdown, makes for super simple color application.
#cssmenu {
  background: #333;
  border-bottom: 4px solid #1b9bff;
  font-family: 'Oxygen Mono', Tahoma, Arial, sans-serif;
  font-size: 12px; 
}

  #cssmenu > ul { *display: inline-block; }

  #cssmenu:after, #cssmenu ul:after {
    content: '';
    display: block;
    clear: both; 
}
First thing's first. we set up some general background colors, add the accent border, and adjust our font to our menu. The 2nd rule is simply a fix for IE7 which isn't too happy about the floats we use. The 3rd rule is a clearfix, which is just another CSS trick we use when dealing with floats.
#cssmenu a {
    background: #333;
    color: #CBCBCB;
    padding: 0 20px; 
}
#cssmenu ul { text-transform: uppercase; }

    #cssmenu ul ul {
      border-top: 4px solid #1b9bff;
      text-transform: none;
      min-width: 190px; 
}
      #cssmenu ul ul a {
        background: #1b9bff;
        color: #FFF;
        border: 1px solid #0082e7;
        border-top: 0 none;
        line-height: 150%;
        padding: 16px 20px; 
}
      #cssmenu ul ul ul { border-top: 0 none; }

      #cssmenu ul ul li { position: relative }
In this portion, we setup our links, menu, and submenu properies. In particular, note that the a element is being used to apply paddings/line-height, and not the li. This way, the link is the one growing and expanding it's mouse area. If you were to apply the padding to the li, then there would be this border around the link that is not clickable. When you see "ul ul", this will apply to all submenus, while "ul ul ul" will only apply to the 3rd level submenus. Note, the last line sets a relative position the the list items in all our submenus. We'll need this for a small enhancement we'll be adding to our submenus shortly. So far, our menu looks like:
Initial Flat Dropdown
We need to adjust our main menu's height, as well as add proper hover states, so...
#cssmenu > ul > li > a { line-height: 48px;  }

#cssmenu ul ul li:first-child > a { border-top: 1px solid #0082e7; }
        #cssmenu ul ul li:hover > a { background: #35a6ff; }

        #cssmenu ul ul li:last-child > a {
          border-radius: 0 0 3px 3px;
          box-shadow: 0 1px 0 #1b9bff; 
}
        #cssmenu ul ul li:last-child:hover > a { border-radius: 0 0 0 3px; }

        #cssmenu ul ul li.has-sub > a:after {
          content: '+';
          position: absolute;
          top: 50%;
          right: 15px;
          margin-top: -8px;
}
The first line sets a line-height only for the direct children of the main menu (since all the submenu items use a different line-height). The rest adds some hover effects, and in particular with that last rule, will add a + sign to any submenu that can expand (using a handy pseudo element). The "position: relative" we applied earlier on was for this feature. With that, there's only a few more adjustments to make:
Near Complete Flat Dropdown Menu

Final Tweaks

    #cssmenu ul li:hover > a, #cssmenu ul li.active > a {
      background: #1b9bff;
      color: #FFF;
}
    #cssmenu ul li.has-sub > a:after {
      content: '+';
      margin-left: 5px; 
}
    #cssmenu ul li.last ul {
      left: auto;
      right: 0; 
}
      #cssmenu ul li.last ul ul {
        left: auto;
        right: 99.5%;
}
We only have 4 rules here, so let's go through each one. The first is in charge of setting the hover/active states for the menu items. The 2nd adds the "+" sign for the top level menu; which instead of being aligned to the right of the menu, simply is added to the label on the menu itself. The 3rd and 4th rule add a new.last class, which can be used on the last item in a menu to reverse the display of the submenu.

No comments:

Post a Comment