Navigation Drawer Pattern With Topcoat CSS Library

Recently I have been playing around with the Topcoat library. Essentially Topcoat is a set of pure CSS-based components for building high performance HTML applications. These apps can be either hosted HTML web apps or native apps packaged with PhoneGap/Cordova. In the app that I’m currently working on I wanted to have a slideable navigation bar that follows the so-called Drawer or Off Canvas UI pattern. Topcoat itself doesn’t come with a built-in implementation of it but all the necessary components are there, so it was just a matter of few lines of CSS and JavaScript to have it running beautifully. In my implementation I also used a simple media query for high-resolution screens like on tablets or desktops where slideable navigation is not necessary.

Below is an example of how it would work on mobile devices. Click a button in the upper left corner to slide it in and out:

Below is an example that will work on high-res screens (to make it work inside an iframe of my blog I had to set the media query to 640px but normally you would probably go for something over 800px). If you are reading this on a mobile device it may still look like the example above; give it a shot on a desktop or on a tablet 😉

Here is a snippet of HTML code with a layout definition:

<!DOCTYPE html>
<html>
    
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
        <title>Topcoat Drawer Example</title>
        <link rel="stylesheet" type="text/css" href="css/topcoat-mobile-dark.css">
        <link rel="stylesheet" type="text/css" href="css/style.css">
        <!--[if lt IE 9]>
            <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
        <![endif]-->
    </head>
    
    <body>
        <div class="topcoat-navigation-bar">
            <div class="topcoat-navigation-bar__item left quarter">
                <a id="slide-menu-button" class="topcoat-icon-button--quiet slide-menu-button">
                    <span class="topcoat-icon topcoat-icon--menu-stack"></span>
                </a>
            </div>
            <div class="topcoat-navigation-bar__item center half">
                <h1 class="topcoat-navigation-bar__title">Topcoat Drawer</h1>
            </div>
            <div class="topcoat-navigation-bar__item right quarter">
                <a class="topcoat-icon-button--quiet">
                    <span class="topcoat-icon topcoat-icon--edit"></span>
                </a>
            </div>
        </div>
        <nav class="side-nav">
            <div class="topcoat-list__container side-nav__list__container">
                <ul class="topcoat-list side-nav__list">
                    <li class="topcoat-list__item side-nav__list__item">
                        <a href="#" class="side-nav__button">Item</a>
                    </li>
                    <li class="topcoat-list__item side-nav__list__item is-active">
                        <a href="#" class="side-nav__button">Item</a>
                    </li>
                    <li class="topcoat-list__item side-nav__list__item">
                        <a href="#" class="side-nav__button">Item</a>
                    </li>
                </ul>
            </div>
        </nav>
        <div class="main-content"></div>
        <script src="//use.edgefonts.net/source-sans-pro:n3,n4,n6;source-code-pro:n3.js"></script>
        <script src="js/main.js"></script>
    </body>

</html>

A bit of JavaScript that controls sliding in and out:

window.onload = function () {

    var slideMenuButton = document.getElementById('slide-menu-button');
    slideMenuButton.onclick = function (e) {
        var cl = document.body.classList;
        if (cl.contains('left-nav')) {
            cl.remove('left-nav');
        } else {
            cl.add('left-nav');
        }
    };

}

Custom CSS code that adds the Drawer/Off Canvas pattern to Topcoat:

html, body {
    margin:0;
    padding:0;
    height: 100%;
}
body {
    font-family: source-sans-pro, sans-serif;
    position: relative;
    width: 100%;
    height:100%;
    overflow: hidden;
    -webkit-font-smoothing: antialiased;
}
body.left-nav .topcoat-navigation-bar, body.left-nav .main-content {
    left:250px;
}
.topcoat-navigation-bar {
    position:absolute;
    width:100%;
    z-index:100;
    transition: left 0.2s ease-out;
    -webkit-transition: left 0.2s ease-out;
    transform: translate3d(0, 0, 0);
    -webkit-transform: translate3d(0, 0, 0);
}
.side-nav {
    display:block;
    position:absolute;
    top:0;
    left:0;
    width:320px;
    height:100%;
    background-color:#353535;
}
.side-nav__list__container {
    margin-top:4rem;
    border-top:none;
    border-bottom:none;
}
.side-nav__list {
    border-top:none;
}
.side-nav__list__item {
    padding:0;
}
.side-nav__list__item.is-active {
    background-color:#353535;
}
.side-nav__button {
    display:block;
    width:100%;
    height:100%;
    padding: 1.25rem;
    box-sizing: border-box;
    color: #c6c8c8;
    text-decoration:none;
}
.side-nav__button:hover {
    background-color:#747474;
}
.side-nav__button:active {
    background-color:#353535;
}
.main-content {
    position: absolute;
    background: inherit;
    left: 0;
    padding-top:4rem;
    width:100%;
    height:100%;
    transition: left 0.2s ease-out;
    -webkit-transition: left 0.2s ease-out;
    transform: translate3d(0, 0, 0);
    -webkit-transform: translate3d(0, 0, 0);
    -moz-box-shadow: 0px 0px 8px 2px rgba(0, 0, 0, 0.57);
    -webkit-box-shadow: 0px 0px 8px 2px rgba(0, 0, 0, 0.57);
    box-shadow: 0px 0px 8px 2px rgba(0, 0, 0, 0.57);
}
@media screen and (min-width: 640px) { /* @media screen and (min-width: 880px) { */
    .slide-menu-button {
        display:none;
    }
    .main-content {
        left:320px;
        right:0;
        width:auto;
    }
}


10 comments

  1. Neil

    I tried your example but it does not display as per your images. Is it possible that you can share your code? Would make our life much better :)

  2. Nicco

    Hey, it looks like the menu icon does not get displayed with the latest version of Topcoat :(
    With your version of the topcoat css works fine.

  3. Jarrod

    Nice!

    There seems to be a hidden button in the top-right corner? (you need to click there to see it). It’s accessible when the draw is closed, and in the iPad version.

    That by design or accident? :)

https://outof.me

Leave a Reply to Jarrod Cancel reply

You may use the following HTML:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>