Article
7 comments

Pure CSS Burger Menu

It is summer here in Vienna and nothing tastes better than a home made burger in the evening. The recipe for a burger is pretty simple. Put some self made patty on the grill. Wait a couple of minutes take the meat from the grill and assemble it all together with some additional component, such as cheese, onions and different kind of sauces, in a burger bun.

Jucy Lucies

To build a burger menu in SharePoint is that simple too, and far beyond rocket science. Again, no master page editing is needed to create such menu. To make sure it works on the premises as well as in Office 365.

Responsive Navigation Patterns

There are actually more patterns to create an appealing navigations in responsive web design, but a burger menu is the most commonly used on the web.
The official name is actually not a burger menu it is “mystery meat navigation“, when this is hidden only behind an icon with three bars or similar.

Mystery meat navigation (also abbreviated MMN) is a term used to describe user interfaces in which it is extremely difficult for users to discern the destinations of navigational hyperlinks—or, in severe cases, even to determine where the hyperlinks are. The typical form of MMN is represented by menus composed of icons that are replaced with the text only when the mouse cursor hovers over them. Annoying.

In my case beside the three bars I will also label the menu with “Menu” and use the build in Office 365 icon font to show the three burger menu stripes.

Add “Menu” in front of the navigation

The first thing that need to be done insert some HTML into our master page. Instead, of fire up SharePoint Designer or any other tool, we will do this just by using CSS (the actual code is SASS).
A couple of years now any major browser supports a special CSS selector named “::before” and the attribute “content”. This is supported even in IE8.

.ms-core-listMenu-horizontalBox {
    border: 1px lime solid;
    &::before{
        content: "Menu";
        color: red;
    }
}

The code above simply adds a lime border around the horizontal navigation menu and prepend the label “Menu” in front.

Burger Menu First Step - Prepend Menu before the navigation

Burger Menu First Step – Prepend Menu before the navigation

The lime border is not needed, but I used it to better highlight the elements. By adding this content we are half way there for transforming the elements into a burger menu.

Toggle Navigation items

The next thing that needs to be done is to implement the toggle that shows and hide the navigation entries. Again, this can be accomplished by using two so called pseudo-classes. “:hover” and “:focus”. Actually, in most cases only hover is needed, but some devices might use focus instead of hover.

.ms-core-listMenu-horizontalBox {
    border: 1px lime solid;
    &::before {
        content: "Menu";
        color: red;
    }

    // Hides the rest of the menu
    .ms-core-listMenu-root {
        display: none;
    }

    // on :focus or :hover shows the menu
    &:hover .ms-core-listMenu-root,
    &:focus .ms-core-listMenu-root {
        display: inline-block;
    }
}

This simple CSS changes allows to show and hide then navigation items. To make sure it is supported by most devices you can simply check out the documentation on Quirksmode.org
The result of this modification looks like this in action.

Simple burger menu hover - shows and hide the rest of the navigation.

Simple burger menu hover – shows and hide the rest of the navigation.

The code from before just includes the very basics of the menu toggle.

Polyfill hover with JavaScript

The following code is only required if older devices should be supported. Devices that handle the CSS hover / focus to tap transition not properly. Most newer devices support focus to show the drop down without JavaScript. Please also check the information about :hover and :focus support on quirksmode.org.

So in case your mobile device don’t support :focus or :hover event properly, a simple javascript can be added. This requires an additional style sheet class “.showBurger”.

.ms-core-listMenu-horizontalBox {
    border: 1px lime solid;
    &::before {
        content: "Menu";
        color: red;
    }

    // Hides the rest of the menu
    .ms-core-listMenu-root {
        display: none;
    }

    // on :focus or :hover shows the menu
    &:hover .ms-core-listMenu-root,
    &:focus .ms-core-listMenu-root,
    &.showBurger .ms-core-listMenu-root{
        display: inline-block;
    }
}

The code that assigned this additional style sheet class looks like this.

var polyfillBurger = polyfillBurger || {};

(function($) {
    'use strict';

    polyfillBurger = function(element) {

        // show burger event definition
        var showHideBurger = function(event) {
            event.preventDefault();
            
            if ($(this).hasClass('showBurger')) {
                $(this).removeClass('showBurger');
            
            } else {
                $(this).addClass('showBurger');
            
            }

        };

        // request element with burger
        var burger = $(element);

        // check if burger exists
        if (burger !== undefined &&
            burger.length !== 0) {

            // register burger menu
            burger.on('click', showHideBurger);
            burger.each(function(index, el) {
                $(el).on('click', showHideBurger);
            });

        }

    };

    $(document).ready(function() {
        polyfillBurger('.ms-core-listMenu-horizontalBox');
    });

}(jQuery));

When the burger menu is clicked the additional style sheet class will be assigned to the whole navigation to make sure the menu is displayed. Through an additional tap on the navigation the style sheet class will be removed again. This script only makes sure that even older browser and devices support this method on most modern devices this script is not needed.
To embed this JavaScript without editing the Master Page you can use the Core.EmbedJavaScript Project form Office Dev Pattern and Practices. Detailed information how to use it can be found at the MSDN – Customize your SharePoint site UI by using JavaScript.

Final thoughts and code

With these simple CSS modifications a simple burger menu can be applied to any navigation. The additional javascript, that can be registered through a custom action, adds support for a huge variety of devices.
The last question unanswered how touch-able controls on mobile devices has to be. This question was answered by Microsoft during their design research for the user interface development for Windows Phone 7 a long time ago. They researched the fingertips of many people and created a great guideline.

Microsoft Window 8 Touch-Guidance

Microsoft Window 8 Touch-Guidance – Source: Microsoft

Touchable will start at a minimum size of 7mm or in other words 26px. While the regular index finger is 11mm a soft tap only use 7mm of the while finger tip.
The Spacing between controls should at least be 2mm or 5px. This reduces the errors while taping on a different element.
As you can see on the chart above. Any control size with a range from 30px to 50px is fine to work with.
White those minimum sizes in mind you are able to create a great responsive experience.
Applied to the burger menu I came up with the following final style sheet definitions using SASS.

.ms-core-listMenu-horizontalBox {
    border: 1px lime solid;
    &::before {
        content: "Menu";
        color: $red;
        display: inline-block;
        font-family: office365icons, o365Icons;
        content: "\e020  Menu";
        font-size: 1.5em;
        padding: 0.2em;
    }
    .ms-core-listMenu-root {
        display: none;
    }
    &:hover,
    &:focus,
    .showBurger {
        &::before {
            background-color: $red;
            color: white;
        }
        .ms-core-listMenu-root {
            box-sizing: border-box;
            position: absolute;
            left: 0px;
            width: 100%;
            display: block;
            background-color: $red;
            color: white;
            padding: 0.35em;
            .static {
                display: block;
                line-height: 1.25em;
                padding: 0.25em 0.5em;
            }
            .menu-item {
                display: block;
                color: white;
                margin: 0px;
                &:hover {
                    background-color: $orange;
                }
            }
        }
        .static.ms-navedit-editArea {
            display: none;
        }
    }
}

The compiled style the will look like this.

.ms-core-listMenu-horizontalBox {
    border: 1px lime solid;
}

.ms-core-listMenu-horizontalBox::before {
    content: "Menu";
    color: #dd314d;
    display: inline-block;
    font-family: office365icons, o365Icons;
    content: "\e020  Menu";
    font-size: 1.5em;
    padding: 0.2em;
}

.ms-core-listMenu-horizontalBox .ms-core-listMenu-root {
    display: none;
}

.ms-core-listMenu-horizontalBox:hover::before,
.ms-core-listMenu-horizontalBox:focus::before,
.ms-core-listMenu-horizontalBox .showBurger::before {
    background-color: #dd314d;
    color: white;
}

.ms-core-listMenu-horizontalBox:hover .ms-core-listMenu-root,
.ms-core-listMenu-horizontalBox:focus .ms-core-listMenu-root,
.ms-core-listMenu-horizontalBox .showBurger .ms-core-listMenu-root {
    box-sizing: border-box;
    position: absolute;
    left: 0px;
    width: 100%;
    display: block;
    background-color: #dd314d;
    color: white;
    padding: 0.35em;
}

.ms-core-listMenu-horizontalBox:hover .ms-core-listMenu-root .static,
.ms-core-listMenu-horizontalBox:focus .ms-core-listMenu-root .static,
.ms-core-listMenu-horizontalBox .showBurger .ms-core-listMenu-root .static {
    display: block;
    line-height: 1.25em;
    padding: 0.25em 0.5em;
}

.ms-core-listMenu-horizontalBox:hover .ms-core-listMenu-root .menu-item,
.ms-core-listMenu-horizontalBox:focus .ms-core-listMenu-root .menu-item,
.ms-core-listMenu-horizontalBox .showBurger .ms-core-listMenu-root .menu-item {
    display: block;
    color: white;
    margin: 0px;
}

.ms-core-listMenu-horizontalBox:hover .ms-core-listMenu-root .menu-item:hover,
.ms-core-listMenu-horizontalBox:focus .ms-core-listMenu-root .menu-item:hover,
.ms-core-listMenu-horizontalBox .showBurger .ms-core-listMenu-root .menu-item:hover {
    background-color: #ee9105;
}

.ms-core-listMenu-horizontalBox:hover .static.ms-navedit-editArea,
.ms-core-listMenu-horizontalBox:focus .static.ms-navedit-editArea,
.ms-core-listMenu-horizontalBox .showBurger .static.ms-navedit-editArea {
    display: none;
}

The final result of the burger menu looks like this.

Final Burger Menu - Including fallback javascript

Final Burger Menu – Including fallback javascript

It also don’t use any third party icon font. The three burger stripes comes from the Office 365 icon font.

Disclaimer: The CSS class that is used in this example might change in future. If this happens the burger menu won’t show up anymore but have no critical impact on the overall behavior of SharePoint. CSS Dom injects are safe from throwing exception. While JavaScript DOM injections might cause problems, throw exceptions and interfere with other SharePoint related scripts.

The complete source code for this can also be found on my responsive SharePoint GIT-Hub repository.

7 Comments

  1. Great post Stefan! Amazing what can be achieved with CSS. Though with your JavaScript requirement you will require an add-in to inject it to all pages if you want to avoid changing the masterpage. Or did you achieve that by other means?

    Reply

    • Thank you Mathias. Forgot to mention that you can add the JavaScript via a custom action and inject it into all pages. A good sample for that can be found on the MSDN and on Office Dev Pattern and Practices.

      In general the script is only required to support older browsers and devices. On Desktop it should work with IE8+.

      I updated those information in the blog post above.

      /Stefan

      Reply

  2. This seems like a great solution! I’m having trouble implementing the MENU button; the border appears, but not the MENU button. This is O365 environment. Can you help me troubleshoot?

    Reply

  3. Hi This a great article.. just wondering if we can do this on click instead of hover.

    Reply

  4. Hi Stefan, I just started working with this kind of stuff recently and this is definitely the most helpful article I have found so far. I have been making a mobile menu and using your example as a reference but one thing I am stuck on is a second level of navigation. For instance in your example when you hover/click on “First Test Link” if it had a few link pop up in between the First and Second Test link. If you hvae any suggestions or help on one more level of naviagation in the burger menu it would be super appreciated! Thanks again for an amazing article!

    Reply

Leave a Reply

Required fields are marked *.


This site uses Akismet to reduce spam. Learn how your comment data is processed.