How to Create Responsive Menus with CSS

Navigation menus occupy a prominent visual space on most websites. As a result, nav elements tend to attract some of the most creative CSS and JavaScript techniques to achieve smooth transitions and beautiful transformations. However, good navigation is about a lot more than creating beautiful visual elements. Website navigation menus affect how search engines rank the pages of your website and how visitors move from one page of your site to another. A lot hinges on getting your website navigation right.

Rules of Good Navigation

Considering how important good navigation menus are to the success of your website, you should spend some time thoughtfully evaluating your current navigation scheme and considering making adjustments. The good news is that when it comes to navigation menus, in most case, less is more, and simplifying your menus is usually a step in the right direction. Here are three simple guidelines that will help you design more effective website navigation elements.

Put it Where Visitors Expect It

Website visitors expect the primary navigation menu to appear in one of two places:

  1. As a horizontal bar along the top of the web page, either immediate above or immediately below the website logo.
  2. As a vertical sidebar along the left-hand side of the webpage.

By placing navigation menus where your visitors expect to find them you make your website easier to use, and a website that is easier to use can expect a lower bounce rate and more opportunities to convert visitors into customers.

Keep it Short and Simple

Simple navigation menus are better than complex ones. Both the layout of your menu and the text you use to label menu items should be as simple as possible. When selecting text labels for your navigation menu items, keep the text short and don’t be afraid of getting creative by using labels that are unique to your industry or business. Unless you really need a complex menu to make your site navigable, make your menu is a single bar containing just a handful of items. Provide submenus on major parent pages rather than trying to fit all of your pages into a single, complicated navigation element. Avoid drop-down menus if possible since usability studies have found that most website visitors are annoyed by them, and they can create barries to accessibility if poorly designed. Drop-down menus also have the effect of diluting the number of visitors that visit your major parent pages. Instead of visiting the parent page, if drop-down menus are provided visitors use them to bypass the parent page and head directly to the child page. Mega drop-down menus are the one exception to the rule that drop-down menus are ineffective. If you have a very large and complex website, mega menus are an effective tool and one that tests well.

Be Thoughtful About the Order of Menu Items

In a list of links, the links appearing at the beginning and end of the list tend to get the most attention. Use this to your advantage. Be thoughtful and strategic about the first and last links in your navigation elements. Are you giving up the first position to a “Home” link? Consider removing that link entirely since virtually all web users today expect to reach the homepage by clicking on a website icon in the upper lefthand position on every page. Instead, use that valuable virtual real estate for your most important page. Order the rest of your links in order of importance. It is also a standard convention to position a “Contact” link as the final element in a navigation menu and to left-align the link if the menu design is a horizontal navigation bar.

How to Create a Simple Navigational Menu

A navigation menu is a list of links, as a result, most navigation menus are built using an unordered list of anchor elements. For our purposes, we’re going to create a list of five list items.

<nav>   <ul>     <li><a href="">Home</a></li>     <li><a href="">Products</a></li>     <li><a href="">Services</a></li>     <li><a href="">Shop</a></li>     <li><a href="">Contact</a></li>   </ul> </nav> 

The first thing we need to do is remove the standard styling that appears around unordered list items. We’ll need a few lines of CSS to do that.

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

If we render what we have so far, it’s just a simple list of vertically aligned links.

Now that we have the basic building blocks of our navigation element set up we can lay them out any way we want.

Simple Nav Arranged Horizontally

The most common way for navigation elements to appear is as a horizontal bar along the top of the website. There are at least three different CSS techniques we can use to align links horizontally rather than in a vertical list. In the code block below we’ve nested all three techniques into a single rule.

li {   display: inline-block;   display: inline;   float: left; } 

Ten years ago, everyone was using the float: left; method to create horizontal navigation menus. More recently the display: inline; trick has seen gains in popularity. However, the current thinking in design circles is that display: inline-block; is the simplest and most effective way to accomplish our goal and it’s the method we’re going to demonstrate in this example. Whatever the strategy you choose to use, what we’re trying to accomplish is to break the list items out of their standard behavior as full-width block level elements, and cause them to display as inline elements in a line next to each other. With our elements now positioned horizontally let’s apply some basic styling using a pre-selected color scheme.

/*Add a color to the entire menu*/ ul {   background-color: #F2C777; } /*Force the list to expand to contain the  links, add some padding around each link, and apply a link text color*/ li a {   display: block;   padding: 10px;   color: #7C785B; } /*Cause the links to change color when hovered on*/ li a:hover {   background-color: #EC8C65; } 

Now we can pull our full code block together and see what we’ve created.

Here’s the full code block that recreates that menu.

<style>   ul {     list-style-type: none;     padding: 0;     margin: 0;     background-color: #F2C777;   }   li {     display: inline-block;   }   li a {     display: block;     padding: 10px;     color: #7C785B;   }   li a:hover {     background-color: #EC8C65;   } </style> <nav>   <ul>     <li><a href="">Home</a></li>     <li><a href="">Products</a></li>     <li><a href="">Services</a></li>     <li><a href="">Shop</a></li>     <li><a href="">Contact</a></li>   </ul> </nav> 

There’s a lot more you can do to enhance the visual appeal of this menu. Consider the overall visual style of your page and incorporate some of the same visual styles. Here are a few ideas to get your creative juices flowing:

  • Have the link text color change at the same time as the link background color when a visitor hovers their mouse a link on the menu.
  • Use the box-shadow property to add a shadow to the drop-down menu to give it depth and separation from the content that it covers up when opened.
  • Use the float: left; rule to left-align the “Contact” link.
  • Add vertical borders between the link elements to provide greater separation between the menu items.
  • Adjust the padding around link elements to better reflect the overall style and spacing of your website.

You can learn all of the techniques necessary to make these changes by reviewing our other CSS Tutorials.

Simple Nav Arranged Vertically

Another popular position for navigation elements is on the left-hand side of a web page. To create this effect we need to start with the clean block of code without the CSS rules, we used to create the horizontal layout. Here the basic HTML we’re going to use to create a vertical navigation menu.

<style>   ul {     list-style-type: none;     padding: 0;     margin: 0;   } </style> <nav>   <ul>     <li><a href="">Home</a></li>     <li><a href="">Products</a></li>     <li><a href="">Services</a></li>     <li><a href="">Shop</a></li>     <li><a href="">Contact</a></li>   </ul> </nav> 

The first thing we’re going to do is to define the anchor elements as block-level elements so that when we apply padding to them they won’t collapse on top of eachother. We’ll also go ahead and apply a width to our entire list, which will be the width of our navigation menu.

/*Set a fixed width for the navigation element*/ ul {   width: 200px; } /*Cause each link to fill the entire row*/ li a {   display: block; } 

Those changes won’t be obvious unless we also add some styling to our menu. With a few of the same styling rules, we used in our horizontal navbar example, we can bring our vertical navigation menu to life. However, vertical menus often look better when the link text is centered within each link and with a soft border to seperate each link, so we’ll add those styles at this point as well.

/*Add a color to the entire menu*/ ul {   background-color: #F2C777; } /*Add a border below each link*/ li {   border-bottom: 1px #D25458 solid; } /*Remove the border form the last link in the list*/ li:last-child {   border-bottom: none; } /*Add some padding around each link, center the text in each link, and apply a text color*/ li a {   padding: 10px;   text-align: center;   color: #7C785B; } /*Cause the links to change color when hovered on*/ li a:hover {   background-color: #EC8C65; } 

Now when we render the menu in a browser, we see a vertical navigation menu that is 200 pixels wide, where each link takes up the full width of the navigation menu, and where the background color of each link changes color to let us know which link we’re hovering over.

If you want the full code block from that example to use for own projects, here it is:

<style>   ul {     list-style-type: none;     padding: 0;     margin: 0;     width: 200px;     background-color: #F2C777;   }   li a {     display: block;     padding: 10px;     text-align: center;     color: #7C785B;   }   li a:hover {     background-color: #EC8C65;   }   li {     border-bottom: 1px #D25458 solid;   }   li:last-child {     border-bottom: none;   } </style> <nav>   <ul>     <li><a href="">Home</a></li>     <li><a href="">Products</a></li>     <li><a href="">Services</a></li>     <li><a href="">Shop</a></li>     <li><a href="">Contact</a></li>   </ul> </nav> 

Creating Sticky Navigation

One effect you see on some websites is for the navigation menu to remain visible as the rest of the content of the page scrolls up and down. In order to do this, we need to force the ul that contains our navigation to fill the entire height or width of the window (depending on whether we’re using the vertical or horizontal layout). We then need to fix the menu’s position. Using the vertical bar we just created we can make this navigation bar a full-height menu that is fixed in position with just two additional lines of CSS.

/*Add these lines to the full code block for the vertical menu  and it will appear fixed to the right-hand side of the window.*/ ul {   height: 100%;   position: fixed; } 

If using the horizontal navbar rather than the vertical navigation, the code to force the menu to behave as “sticky navigation” is very similar.

/*Add these lines to the full code block for the horizontal    menu and it will appear fixed to the top of the window.*/ ul {   width: 100%;   position: fixed;   top: 0; } 

Making Your Nav Responsive

While our horizontal navbar menu looks pretty good on a fullsize screen, it doesn’t do very well on smaller screens. Thankfully, with a simple media query, we can cause our navigation menu to revert back to it’s vertical orientation. The result will be that our navigation menu looks great on screens of all sizes. We’re also going to borrow the border styling from our vertical menu so that it will be applied when our screen reaches a width of fewer than 500 pixels.

@media screen and (max-width: 500px) {   li {     display: block;     border-bottom: 1px #D25458 solid;   }   li:last-child {     border-bottom: none;    } } 

That media query will only take effect if the browser window in which the website is being rendered is less than 500 pixels wide. In that event, the list items will become block-level elements and the border styling will be applied. Keep in mind that the media query must be the last set of rules in our CSS hierarchy. Otherwise, the media query rules will be overwritten by the rules that follow it. Here’s how our horizontal navbar renders with our new media query.

Drag the bottom right corner of the frame above to view menu responsiveness.

Our vertical nav can also be transformed into a full-width menu at the breakpoint of our choosing with the addition of just one additional CSS rule to our media query. All we need to do is force the entire list to grow to the full width of the viewport and the vertical nav will work well on any device. Why would we want to do this? Our vertical navigation menu is only 200 pixels wide and will look pretty good on most devices as-is. While it may be true that our nav menu looks ok on smaller screens, at some point space next to the menu will become cramped and crowded and create layout issues. The exact break point where the vertical nav menu needs to snap to full-screen width will vary depending on the rest of the content on the web page, but for this example, we’ll use the same 500-pixel value that we used for our horizontal nav bar.

@media screen and (max-width: 500px) {   /*Force the menu to grow to the full width of the screen*/   ul {      width: 100%;   }     /*The rest of the query is copied from our horizontal menu*/      li {     display: block;     border-bottom: 1px #D25458 solid;   }   li:last-child {     border-bottom: none;    } } 

Working with Multi-Level Navigational Menus

While drop-down menus aren’t recommended by most design experts, they are still quite common on the web. If you’ve decided that a drop-down menu is the best choice available for your website, you can create both horizontal and vertical navigation menus with drop-down elements nested within the menu using just HTML and CSS.

Adding Drop-Down Links to a Horizontal Navbar

Adding drop-down links to a horizontal navbar is pretty straightforward. The first thing we need to is to add the dropdown menu links to our HTML. We’re going to use a div to hold our links and place the entire div inside of the list item that we want to use for our drop down menu items. Let’s add two different drop-down menus: one under products and a second under services. We’re going to add the class dropbutton to both of the list items that contain the drop down elements so that we can apply CSS rules directly to them without affecting the other list items. In addition, we’re going to add the class droplinks to the div elements that contain the drop down links so that we can select them for CSS styling.

<nav>   <ul>     <li><a href="">Home</a></li>     <!--Add a class to the list item with the drop menu-->     <li class="dropbutton"><a href="">Products</a>       <!--Add dropdown menu links before closing li tag-->       <div class="droplinks">         <a href="">Widgets</a>         <a href="">Cogs</a>         <a href="">Gears</a>       </div>     </li>     <!--Add a class to the list item with the drop menu-->     <li class="dropbutton"><a href="">Services</a>       <!--Add dropdown menu links before closing li tag-->       <div class="droplinks">         <a href="">Handshakes</a>         <a href="">Winks</a>         <a href="">Smiles</a>       </div>     </li>     <li><a href="">Shop</a></li>     <li><a href="">Contact</a></li>   </ul> </nav> 

We now need to write three CSS rulesets to cause the drop menu items to be hidden unless the drop link containing the menu is hovered over.

.droplinks {    /*Break the div out of the layout flow of the list*/   position: absolute;   /*Give the div a background color and width*/   background-color: #F2D299;   min-width: 140px;   /*Hide the div from view*/   display: none; } .droplinks a {   /*Match the padding applied to the other menu items*/   padding: 10px;   /*For the links to each fill a complete row in the containing div*/   display: block; } 

What we’ll do to make the drop down elements appear is use the :hover selector to change the display property of the div that contains the drop down elements fromnonetoblock`.

.dropbutton:hover .droplinks{   /*Cause the div to be displayed only when a website visitor   hovers their mouse over the list item containing the div*/   display: block;       } 

Now when we render the menu in a browser, the drop-menu links are hidden by default but appear when we hover over the top menu items that contain the drop down elements.

If you happen to be viewing this page on a smartphone, or if you resize your browser window, you may notice that this menu isn’t responsive. That’s because drop-down menus that open automatically on :hover don’t work well when laid out vertically because when they open they force the menu items below them down. Then when the mouse moves off of the drop down menu it closes and the menu moves back up. If a visitor is trying to select an item from the menu that sits below a drop down element, this behavior can be very frustrating. For this reason, we’ve removed the media query that applied the responsive styling. If you want to see how to make a horizontal menu with drop down elements fully responsive, you’ll just have to keep reading.

Adding Drop-Down Links to a Vertical Navbar

If you’ve been following along with our vertical navbar example, we can also add drop-down elements to the vertical menu design. The first step is to get our HTML whipped into shape. We need to add the drop down menu links nested inside a div just as we did in our horizontal drop down menu. However, we need to add a few additional classes and IDs as well as a new anchor element that we didn’t add to our horizontal nav bar with drop down elements. In a vertical menu, it isn’t a good idea to use the :hover attribute to cause the drop-down menu to open. If the drop-down elements appear in the middle of the menu they will force the rest of the menu to shift down. This creates a problem if you want to move the mouse down to items below the drop down menu since the menu automatically closes once your mouse pointer moves past the drop down elements and the rest of the menu moves back up. As you can imagine, a menu that jumps up and down as you try to select a menu item can become very frustrating very quickly. So unstead of using the :hover selector to open the drop down menu, we’re going to use the :target selector. We’re going to add a new anchor element in the same list item as the drop down menu links. We’ll add it between the link that is already present in the list item, but before our drop down elements. We’ll also wrap both of these anchor elements in a div. We’re going to use the unicode symbol 〉 as the content of our new link. We can add this character to our HTML with the character code &#12297;. This symbol will serve as a button which we’ll use to open and close the drop down menu. In a minute, we’ll also add some additional classes and an ID, but to give you a sense of what we’ve done so far, here is one of our drop-down list items with the new link and div added.

<li class="dropbutton">   <div>     <a href="#">Products</a>     <!--New element that will open the drop down menu-->     <a href="#">?</a>   </div>   <div class="droplinks">     <a href="#">Widgets</a>     <a href="#">Cogs</a>     <a href="#">Gears</a>   </div> </li> 

Now we need to add a few new classes and an ID. We will apply unique classes to the existing link that hides the drop down elements (class="droplabel"), and to the button HTML we just added (`class=”dropopen”). Finally, we will apply a unique ID to each of the div elements that contain our drop down menu items and link to these new ID elements with the buttons we just created. Here’s what our HTML will look like after making all of those changes.

<nav>   <ul>     <li><a href="#">Home</a></li>     <li class="dropbutton">       <div class="dropbox">         <a class="droplabel" href="#">Products</a>         <a class="dropopen" href="#dropdown1">?</a>       </div>       <div class="droplinks" id="dropdown1">         <a href="#">Widgets</a>         <a href="#">Cogs</a>         <a href="#">Gears</a>       </div>     </li>     <li class="dropbutton">       <div class="dropbox">         <a class="droplabel" href="#">Services</a>         <a class="dropopen" href="#dropdown2">?</a>       </div>       <div class="droplinks" id="dropdown2">         <a href="#">Handshakes</a>         <a href="#">Winks</a>         <a href="#">Smiles</a>       </div>     </li>     <li><a href="#">Shop</a></li>     <li><a href="#">Contact</a></li>   </ul> </nav> 

Now we’re ready to start writing CSS rules. First, let’s take care of some basic styling that will make our new drop down elements and buttons match yet stand out from the main menu links.

/*All we're doing is matching the rule we created  previously to apply a border to the bottom of our link elements. This time, we're using a slightly different color.*/ .droplinks a {   border-bottom: 1px #EC8C65 solid; } /*We'll add a new selector to the rule that prevents the border from being applied to the last time in the list*/ li:last-child,  .droplinks a:last-child {   border-bottom: none; } /*We also need to add a border between the list item that contains the drop down link and the top drop down lik*/ .droplinks a:first-child {   border-top: 1px #EC8C65 solid; } 

Next we need to format the list item that holds the drop down elements as well as the button that displays the drop down elements. What we want to do is have both appear on a single line with the button pushed all the way to the right while the link takes up the rest of the available space. The first step in the process is to format the div that holds the label and button links. We’ll give the div a fixed height that matches the height of our other link elements and also center align any text in the div.

.dropbox {   height: 38px;   text-align: center; } 

Now we need to style the label and button elements within the div that we just styled. First, we’ll float the button to the right and apply a background color that will make it stand out from the rest of the link so that it will be obvious to a visitor that it is a button. Then we’ll give it a calculated height to ensure that it fits within the available space. In addition, we need to trim the right-hand padding due to the layout of the unicode symbol we’ve selected. Second, we need to make the link that hides the drop down elements an inline-block element so that it will allow the button to slide up next to it on the right-hand side. Next we will apply padding to the left side of the link. We will use the value 42px; to match the space taken up by the button on the right-hand side (32 pixels) plus the 10 pixels already applied to the link. Finally, we will use a calculation to cause the width to be equal to 100% of the menu, less the total horizontal padding on the link element (52 pixels) and less the width of the button on the right-hand side of the link (32 pixels).

.dropopen {   background-color: #F2D299;   display: inline-block;   float: right;   height: calc(100% - 20px);   padding-right: 4px; }  .droplabel {   display: inline-block;   padding-left: 42px;   width: calc(100% - 84px); } 

Next we need to get our drop down links styled with a background-color, and we’ll match the color that we used for the button background. Instead of using display: none; to hide the drop down menu links, this time, we’ll use max-height: 0; to collapse the entire div and overflow: hidden; to hide the links while the div is collapsed. Finally, we’re going to go ahead and add some CSS transition styling to the menu to give it a more fluid feel when the drop down menus open and close.

.droplinks {   background-color: #F2D299;   max-height: 0;   overflow: hidden;    -webkit-transition: all .5s linear;   -moz-transition: all .5s linear;   -o-transition: all .5s linear;   transition: all .5s linear; } 

The last step is to add a CSS rule that will open up the collapsed divs when the buttons are clicked. To do this, we’ll use .droplinks:target as the selector. This selector is activated when an element with the attribute class="droplinks" is targeted. When the buttons we’ve created are clicked they will target the div that contains the same ID as the button link. This will activate the :target selector and the styles contained within this rule will take effect. To open the collapsed div elements, we simply apply a max-height that is greater than what is needed to display all of the links in our drop down menu. In this case, 150px works well.

.droplinks:target {   max-height: 150px; } 

Now we can pull all of the code together to produce our vertical menu with click-activated drop-down menus that remain open until another link is clicked.

Drag the bottom right corner of the frame above to view menu responsiveness.

Extra Credit

Now that we have a method of effectively adding drop-down elements to a vertical menu, it would be ideal to go back and apply the same technique to our horizontal menu. The strategy here is to go ahead and use the vertical menu HTML and to use a media query to display the button and add all of the styles used for our responsive vertical menu with drop downs.

Drag the bottom right corner of the frame above to view menu responsiveness.

Creating Great Navigation Menus

Navigation menus are one of the most important design, usability, and accessibility features of every website. They are one of the most prominent visual elements on the page, website visitors depend on them to reach the content they are looking for, and the design of your site navigation even has SEO implications. Now that you’ve completed this tutorial you know the fundamental guidelines to follow in designing your navigation elements, and the HTML and CSS techniques to craft beautiful and functional menus.