Multi-Level Push Menu

An experimental push menu with multi-level functionality that allows endless nesting of navigation elements.

MultiLevelPushMenu

View demo Download source

Today we want to share another menu experiment with you. For sure you are familiar with the off-canvas navigation on mobile apps and the implementations for responsive websites like the one by David Bushell. We tried to explore the possibility of creating a nested multi-level menu, something that could be quite useful for menus with lots of content (like navigations of online stores). The result is a “push” menu that can (theoretically) contain infinite nested sub-menus. When opening a sub-level, the whole navigation pushes the content more, allowing a slice of the parent menu to be visible. Optionally, this slice can be visible or not, in which case the sub-menu will simply cover its parent.

Working with nested structures is quite tricky because when we, for example, move the parent then all children will of course move as well. So we are using a couple of tricks that will maintain the right 3D translates for the sub-menus and their children. The main idea is to increment the value for the translate so that we guarantee that the sub-levels are not shown once we push everything a bit more for showing the slices of the parents. This is of course not necessary in the case where the sub-menu is covering the parent menu.

Please note that we are using 3D Transforms which only work in modern browsers. You will find a fallback example for non-supporting browsers in the end of the component.css file where we simply show the first level menu. The same we do for the no JS case.

We are using the following nested structure for the menu:

<!-- mp-menu -->
<nav id="mp-menu" class="mp-menu">
	<div class="mp-level">
		<h2 class="icon icon-world">All Categories</h2>
		<ul>
			<li class="icon icon-arrow-left">
				<a class="icon icon-display" href="#">Devices</a>
				
				<div class="mp-level">
					<h2 class="icon icon-display">Devices</h2>
					<ul>
						<li class="icon icon-arrow-left">
							<a class="icon icon-phone" href="#">Mobile Phones</a>

							<div class="mp-level">
								<h2>Mobile Phones</h2>
								<ul>
									<li><a href="#">Super Smart Phone</a></li>
									<li><a href="#">Thin Magic Mobile</a></li>
									<li><a href="#">Performance Crusher</a></li>
									<li><a href="#">Futuristic Experience</a></li>
								</ul>
							</div>

						</li>
						<li class="icon icon-arrow-left">
							<!-- ... -->
						</li>
						<li class="icon icon-arrow-left">
							<!-- ... -->
						</li>
					</ul>
				</div>
			</li>
			<li><!-- ... --></li>
			<!-- ... -->
		</ul>
	</div>
</nav>
<!-- /mp-menu -->

…where each level is wrapped into a division with the class mp-level.

Normally, we would have used fixed positioning for a menu of this kind but since there is quite an peculiar “problem” with that (transforms will make it behave like an absolute positioned element), we’ll have to use absolute positioning which will leave us with some unwanted behavior of the site (scrolling of menu and dependence of document height). So we’ve used a little trick to avoid the menu being scrollable or to be cut off if the site’s content is too short by using the following page structure:

<div class="container">
	<!-- Push Wrapper -->
	<div class="mp-pusher" id="mp-pusher">

		<!-- mp-menu -->
		<nav id="mp-menu" class="mp-menu">
			<!-- ... -->
		</nav>
		<!-- /mp-menu -->

		<div class="scroller"><!-- this is for emulating position fixed of the nav -->
			<div class="scroller-inner">
				<!-- site content goes here -->
				</div>
			</div><!-- /scroller-inner -->
		</div><!-- /scroller -->

	</div><!-- /pusher -->
</div><!-- /container -->

Where we set the following styles for the elements:

html, 
body, 
.container,
.scroller {
	height: 100%;
}

.scroller {
	overflow-y: scroll;
}

.scroller,
.scroller-inner {
	position: relative;
}

.container {
	position: relative;
	overflow: hidden;
	background: #34495e;
}

This will allow the content to be scrolled when the menu is closed and it will also make the menu being 100% of the window height. Basically, we are emulating what fixed positioning would do here.

This is how the plugin can be called:

new mlPushMenu( document.getElementById( 'mp-menu' ), document.getElementById( 'trigger' ) );
Or, if the submenus should cover the previous levels: 
new mlPushMenu( document.getElementById( 'mp-menu' ), document.getElementById( 'trigger' ), {
	type : 'cover'
} );

For the demos we are using the beautiful Linicons iconfont by Sergey Shmidt created with the help of the IcoMoon app.

We hope you enjoy this menu and find it useful.

View demo Download source

Previous:
Next:

Tagged with:

Mary Lou (Manoela Ilic) is a freelance web designer and developer with a passion for interaction design. She studied Cognitive Science and Computational Logic and has a weakness for the smell of freshly ground peppercorns.

View all contributions by

Website: http://tympanus.net/

Related Articles

Feedback 217

Comments are closed.
  1. 1

    I found a bug. I have no clues how to fix it.
    Only on Firefox ( i havent tested IE)
    if you have a fixed element inside the mp-pusher (e.g. try to add a position:fixed to the codrop top bar ).
    this fixed element will disappear once you click on the trigger.
    Do you have any idea how to solve it?
    cheers

  2. 2

    Love this. I would just very much see a version that does not depend on 3d transforms so it can be used in older browsers too. I know there has been made a jQuery plugin about Mary’s lovely menu (https://github.com/adgsm/multi-level-push-menu) which works in IE8. However, I would like to use 3d transforms in browsers that supports it and as a fallback I’d use the jQuery plugin. Unfortunately it’s not the exact same markup structure in the jQuery plugin which makes it difficult to use both Mary’s menu and the jQuery plugin. Has anyone got any experience with fallbacks to IE8+ using the one with 3d transforms and the jQuery plugin?

    Thanks in advance.
    /Aske

    • 4

      first change line 98 of mlpushmenu.js to:
      this.eventtype = ‘click';

      (Windows phone IE doesn’t recognize ‘touchStart’)
      then in your css add:

      @-ms-viewport {
      width: auto;
      }

      This fixes scrolling.

    • 5

      The fix by Matt doesn’t work. If i modify the line 98, the menu never appear when i it the button…

  3. 6

    I found a bug in iOS, if the page has a lot of content and is a very high page, when you touch the iOS bar to slide up to the top, it does not. Has anyone noticed this and have any solutions?

  4. 7

    Hi, what if I have a lot of items in the list so I need a scroll function in menu? Thanks :)

    • 8

      Yep, my issue too. My lazy workaround is just to create more levels- split the categories up more….

  5. 9

    Getting this: Uncaught TypeError: Cannot read property 'querySelectorAll' of null mlpushmenu.js:89
    How can el be undefined?

  6. 10

    I have found this to be one of the best slider navs out there and I really appreciate all the work put in to this so thanks for sharing it! While using it I ran into a few bugs that I found solutions to so I want to share those with the community in case anyone else runs into them but haven’t found a solution here yet. I know, I probably should have read the previous comments first but here goes:

    iOS scrolling issues.
    fix:
    I added these lines to my css
    .scroller {
    overflow-y: scroll;
    }
    .scroller {
    -webkit-overflow-scrolling: touch;
    }
    .scroller > * {
    -webkit-transform: translateZ(0px);
    }
    This gives smooth scrolling to iOS while also fixing those blank areas you get while scrolling where you have to wait until you stop scrolling for the content to display.

    Windows Phone 8.0 clicking the button to open the nav didn’t work.
    fix:
    in mlpushmenu.js change line 98 from:
    this.eventtype = mobilecheck() ? ‘touchstart’ : ‘click';
    to:
    this.eventtype = ‘click';
    (that browser doesn’t recognize ‘touchstart’ as an event. )

    Windows Phone 8.0 Scrolling didn’t work.
    fix:
    in my css I added these lines:
    body, html, .scroller {
    -ms-overflow-style: none !important;
    }
    @-ms-viewport {
    width: auto;
    }

    remaining issues:
    IE 9 and below: the plugin doesn’t seem to work but at that point I would call it ‘progressive enhancement’ or ‘graceful degradation’ (your pick) and switch to a more simple navigation solution for those browsers.

    Hopefully this is helpful to someone.

  7. 11

    Hi, there, try to work with this multilevelpushmenu, but got two Problems, what, if the list of menu-items is too long for a site on a screen or a smartphone, but you don’t want to have a scrollbar? And on my smartphone the menu-icon to open the menu-levels often does not react (only whe I touched several times…) Has anyone got an idea?

    Thanks
    glupto

  8. 12

    This is very nice, but there is one problem. Once there is the right push, the right area is not resized and any content that was previously close to the right edge vanishes.

    I want it to resize automatically… is that possible?

  9. 13

    Does anyone knows if the code was updated with the fixes? Or is it “bugged” since the beginning ?!
    I’m asking this because i really liked!

Comments are closed.