Unlimited Wordpress themes, plugins, graphics & courses! Unlimited asset downloads! From \$16.50/m

# How to Build an Off-Canvas Navigation With CSS Grid

Difficulty:IntermediateLength:ShortLanguages:

The off-canvas pattern is a classic approach to responsive navigation. When the viewport is small enough to warrant it, bulky navigation is hidden “off-canvas” and only brought into view when toggled.

Today we’re going to build an off-canvas navigation, using CSS to do the toggling (no JavaScript required) and our good friend Grid to form the page structure. Here’s the full page demo of what we’re working towards.

## Basic Page Structure

Let’s begin by building a basic page; we’re aiming for something like this:

This is a fairly typical semantic page structure; you’ll see that everything remains in a single column for small viewports, then the aside moves across on larger screens. The <nav> element is highlighted in blue for clarity.

Here’s our markup:

Now let’s add some visual styles and some Grid rules.

## Gettin’ Griddy With it

Begin by wrapping all our structural elements in a containing element of some kind–this will be our Grid container. I’m using <div class="container"></div>

Now add some basic grid styles:

Here we’re declaring that the container should be display: grid;, that it should have a single column of one fractional unit (not strictly necessary at this point, but we’re added it to be thorough), and that the gap between all grid items should be 10px.

Next add a couple of visual styles to make things a bit clearer:

## Make it Responsive

Let’s add a media query, so that when the viewport hits a certain size (let’s go for 600px) the layout changes.

So now, on larger screens, the grid declaration changes to grid-template-columns: repeat(4, 1fr);. This gives us four columns of equal width, so we then have to declare how wide we want each of our structural elements. The header, nav, and footer will all span 4 (span across four columns) whilst the section will span across just three, leaving a gap of one column for the aside to fill automatically.

Finally, some styles to alter the way the nav looks:

Here’s what we have so far:

## Venturing Off-Canvas

This is a perfect example of how CSS positioning can still work on structural elements, even within a declared Grid. We’re going to grab our nav, remove it from the document flow, and position it off-canvas. The other grid items will fall into place just fine.

Begin with another media query. We already have our min-width query, but this time we only want to style elements up to a max-width. Up until our viewport reaches that magic 600px we want the nav to be positioned off-canvas:

We’ve given the nav a fixed width, positioning it left by enough to hide it completely.

We used position fixed, but you could also use absolute here, depending on whether you want the nav to scroll with the window or not.

You’ll also notice the transition rule, which will take effect once we build some toggle controls. We’ll transition the nav panel back into view using transform. Thanks go to Rachel Nabors and Joe Zimmerman for reminding me that using transform is always more performant for animation than position

## Toggling

Having made our nav disappear, we now need some controls to bring it back when needed. Let’s add a link to trigger it, and a link to close it again.

and this to the nav:

We don’t need the open link to be visible on larger screens, so we’ll hide the .toggle elements within our min-width media query:

### :target

What’s important in the above links is the presence of a “fragment identifier” (the #nav in the href). These identifiers are used by browsers to navigate directly to specific elements on a page. In this case, we’re targeting whichever element matches the id “nav”, and once it’s been targeted we can style it using the :target pseudo class. No JavaScript necessary!

Note: using a fragment identifier in this fashion will cause an entry to be added to the browser history every time it’s clicked. This may not be the result your users want! Thanks to Joe Zimmerman for pointing this out.

Add the following to our max-width media query:

That’s it! That’s our toggle.

Here’s what we have now:

You’ll need to take a look at the full page demo to fully appreciate what it’s doing.

## Conclusion

And we’re done! I’ve kept styling down to a minimum so as not to get in the way, but feel free to go nuts and make this look exactly how you want.

You may also prefer a JavaScript toggle, instead of the :target, in which case you have all the pieces in place to make that work too.

I hope you enjoyed this little Grid exercise, stay tuned for more to come!