To get started, we first need solid HTML for our navigation. We'll use
a links for the individual links—they're certainly the element for the job. And since we know this is the site navigation, we'll wrap it in a
nav element, which means "a set of links for getting around a site, page, or article." Finally, inside the
nav, we'll use an unordered list (
ul) to contain the listing of links. This is helpful for users browsing the site using a screen-reader because it tells them how many links there are, so they can skip the nav altogether if it seems too long.
By starting with the HTML only, we ensure semantic element structure, rather than choosing elements based upon their appearance.
The full HTML with only default browser styles looks like this:
When implementing a responsive design, it's nearly always best to use a mobile-first approach, meaning the first styles you write, those written outside any media query, are those for the smallest viewport width. This ensures that you start from a state of lower complexity, then gradually add complexity with media queries as the viewport gets wider.
The mobile-first approach keeps you from having to work backwards, subtracting back out complexity that you have already added.
Styling the List
First off, let's get rid of the bullets that indicate the individual list items (
li) using the
list-style. We only want to do this for list items in the nav, not any other potential list items that might appear elsewhere on the website, so we can use a decendant selector using a space to only select for list items within a
Make sure you only select the list items in the navigation. Otherwise, your styles will be applied to all list items on the site.
The bullets are gone! But there's a problem—all the text is indented somewhat from the left side of the page. Using the developer tools inspector, we will see that this results from the
padding-left that is on the
ul by default. We can remove it by zeroing out that padding, making sure again to only do so for unordered lists that are decendants of a
Styling the Links
To add a little visual separation, let's add some
padding to each link and a line between them using
border-bottom. While we're at it, we can remove the default underline from the link text using
Hmmm, that looks kind of funny. The borders don't stretch all the way across the space available, and something weird is happening vertically that causes the borders to overlap the text. So what's going on?
Well, links (
a) are inline be default, which means their content boxes only extend as far as the text they contain. And inline elements don't respect padding or margin on the vertical axis. That explains the issues we see.
By applying the padding to the
a selector, we can ensure the entire area is clickable.
We could solve the problem by placing the padding and border on the
li selector instead because list items are block by default. However, if we did so, users wouldn't be able to tap within the padded area to visit the link. Only the links are clickable here. So instead, let's simply make the links block using the
Now that the navigation looks good in its default state, it's time to make sure the links give a visual indication of interaction by styling the hover, focus, and active states.
Since the hover and focus states both exist to let the user know the link is ready to be clicked, we'll use a comma-separated multi-selector to style them both the same with color and background. And we'll get rid of the default focus style using the
outline property. Finally, we'll simply use a different background color for the active state:
Try hovering over the links. Can you figure out how to change the background color on hover? Can you make the borders thicker?
Making it Responsive
Now that we have good-looking navigation styles for mobile, we can add media queries to create different layouts for larger viewport sizes.
The most common design pattern is to have the nav links sit side-by-side on larger screens, so let's create a media query where we'll apply our new styles (let's try
600px wide and up) and set the links to
inline-block. We choose this instead of
inline to ensure that any vertical padding or margin is still applied.
The links are still stacking, so what's going on? If you recall, each link is wrapped in a list item, which are themselves block elements by default. So we'll need to change them as well. Since their sizes are currently determined by the links they contain, it doesn't matter much whether we set them to
inline-block, but we'll go with
inline-block just to be consistent:
Grab the lower-right corner of the demo and resize the viewport. Note how it changes between the mobile layout and the side-by-side layout depending on the width.
So far, so good. But let's get rid of the borders under the links. They look a little funny in this layout:
There you have it! A simple responsive navigation that follows common design patterns. If you wanted you could alter the hover, focus, and active states within the media query. Or you could add a second media query to change the styles further on even larger viewport widths. Or you could create more imaginative navigation layouts at any of the sizes. This example is just here to get you started.