demosthenes.info

I’m Dudley Storey, the author of Pro CSS3 Animation. This is my blog, where I talk about web design and development with , and . To receive more information, including news, updates, and tips, you should follow me on Twitter or add me on Google+.

web developer guide

my books

Book cover of Pro CSS3 AnimationPro CSS3 Animation, Apress, 2013

my projects

A Sass color keyword system for designers. Replaces CSS defaults with improved hues and more memorable, relevant color names.

CSSslidy: an auto-generated #RWD image slider. 3.8K of JS, no JQuery. Drop in images, add a line of CSS. Done.

tipster.ioAutomatically provides local tipping customs and percentages for services anywhere.

Photograph of a woman in a hooded cloak

A Responsive, Animated Menu For Single-Column Web Designs

mobile / navigation

Estimated reading time: 4 minutes, 18 seconds

Screenshot of Skullduggery responsive site in portrait aspect ratioAdapting UI elements to changing screen sizes and aspect ratios is one of the greatest challenges of : a bar that works when a device is held in landscape mode often fails when the screen is turned 90°.

Responsive UI is easier when the design is simple, so I’ll start with just that: a single-column page for the fictional Skullduggery Incorporated. I’ve made the design available on CodePen for you to inspect and play with.

Skullduggery offers a number of services, which are linked in a navigation bar under a header. The nav element has an ARIA role to aid in :

<header>
<h1>Skullduggery, Inc</h1>
<h2>“Service with a smile and a stab”</h2>
</header>
<nav role="navigation">
<a href="#">Defenestration</a>
<a href="#">Poisoning</a>
<a href="#">Garroting</a>
<a href="#">Duels</a>
</nav>

The page has a single fluid image (provided by Aditya Mopur under a Creative Commons license) and some paragraph text. On large and medium format devices the page will look like the illustration above.

The base CSS for the page is:

 * { margin: 0; }
html { font-size: 62.5%; background:#180303; }
body, a {
font-family: Forum, cursive;
color: #ecede3;
text-decoration: none;
}
header { padding: 2rem 0; }
h1 {
font-size: 5rem;
text-shadow: 4px 4px 3px rgba(0,0,0,0.3);
}
h2 {
font-size: 2.5rem;
font-weight: 100;
margin-left: 10rem;
}
h1, h2 { text-align: center; }
a, p { font-size: 2rem; padding: 2rem; }
a:hover { background: #000; }
p { line-height: 160%; margin: 8rem; }
nav {
background: #350c0c; padding: 1.2rem 0;
box-shadow: 0 8px 6px rgba(0,0,0,0.3);
}

Creating A Responsive Design

As the viewport narrows, there is reduced space for the design. In response we will use media queries to reduce font sizes and margins at design breakpoints:

@media screen and (max-width: 800px) {
p { margin: 4rem; }
}
@media screen and (max-width: 490px) {
h1 { font-size: 4rem; }
h2 { font-size: 2rem; margin-left: 4rem;  }
nav, nav a { padding: 1rem; }
p { margin: 1rem; }
}

Below 460 pixels wide, the links inside the nav element begin to wrap to the left. That can be fine in certain instances, but often makes the navigation look cluttered and disorganized. Let’s clean up the navigation by turning the links into display: block, forcing them onto separate lines:

@media screen and (max-width: 460px) {
nav { padding: 0; }
nav a { display: block; padding: 1.2rem; }
}

Screenshot of Skullduggery responsive site in portrait aspect ratioAdding An Adaptive Menu

That looks much better, but you can see a problem in the screenshot to the right: the navigation bar now takes up a lot of vertical space, pushing the page content off the screen. What we really want at small viewport widths is for the navigation bar to be minimized until the user needs it. Here, we’re going to achieve that by adding an element at the start of the navbar with a Unicode symbol that has become the broadly accepted visual shortcut for menu access in responsive sites:

<nav role="navigation">
<a href="#">&#9776; Menu</a>
<a href="#">Defenestration</a>
<a href="#">Poisoning</a>
<a href="#">Garroting</a>
<a href="#">Duels</a>
</nav>

We only want the new element to appear at small viewport sizes, so we’ll turn it off in our base :

nav a:first-child { display: none; }

… and turn it back on again when the browser is 460 pixels wide or less:

@media screen and (max-width: 460px) {
nav a:first-child { display: block; }

Screenshot of Skullduggery responsive site in portrait aspect ratioThat’s doesn’t quite solve our problem... but the next step does. At 460px we’re going to reduce the height of the menu bar so we can only see the first link, i.e. the one we have just made visible, hiding the other links by using overflow: hidden. Finally, we’ll expand the menu bar to its natural height by responding a hover event on it, using :focus as a backup. The final @media query becomes:

@media screen and (max-width: 460px) {
nav { padding: 0; height: 5rem; overflow: hidden; }
nav a { display: block; padding: 1.2rem; }
nav a:first-child { display: block; }
nav:hover, nav:focus { height: auto; }
}

Animating The Menu bar

We can animate the expansion of the navbar with a silky-smooth CSS transition, with one caveat: browsers do not currently support an element’s transition to its “natural” height. To animate the menu we must set an explicit height for it:

@media screen and (max-width: 460px) {
nav {
padding: 0; height: 5rem;
overflow: hidden;
transition: .7s height ease-in-out;
}
nav a { display: block; padding: 1.2rem; }
nav a:first-child { display: block; }
nav:hover, nav:focus { height: 23rem; }
}

(Remember that you’ll need to add a vendor prefix for the animation to work in some browsers).

The one potential downside to this approach is that the menu bar will remain open after the user touches it: the ability to close it with a touch without going to another page would require us to add some .

Conclusion

As you can see, creating a responsive UI element is easy for simple pages; design methodologies change when we get to larger and more complex sites, which we will look at shortly.

Banner image provided by Kristina Ruth Play with the code for this responsive menu on CodePen

comments powered by Disqus

This site helps millions of visitors while remaining ad-free. For less than the price of a cup of coffee, you can help pay for bandwidth and server costs while encouraging further articles.