Tooltip Menu

A simple tooltip menu where the submenu will either appear above or below the main menu, depending on available space.

TooltipMenu

This is a simple tooltip menu that will show a tooltip submenu when hovering over an item. The submenu will either appear above or below the main menu, depending on where more space is available. Using Modernizr’s touch detection, the menu will either react on hover or on click. Example media queries show how to adjust the style for smaller screens.

The HTML

<ul id="cbp-tm-menu" class="cbp-tm-menu">
	<li>
		<a href="#">Home</a>
	</li>
	<li>
		<a href="#">Veggie made</a>
		<ul class="cbp-tm-submenu">
			<li><a href="#" class="cbp-tm-icon-archive">Sorrel desert</a></li>
			<li><a href="#" class="cbp-tm-icon-cog">Raisin kakadu</a></li>
			<li><a href="#" class="cbp-tm-icon-location">Plum salsify</a></li>
			<li><a href="#" class="cbp-tm-icon-users">Bok choy celtuce</a></li>
			<li><a href="#" class="cbp-tm-icon-earth">Onion endive</a></li>
			<li><a href="#" class="cbp-tm-icon-location">Bitterleaf</a></li>
			<li><a href="#" class="cbp-tm-icon-mobile">Sea lettuce</a></li>
		</ul>
	</li>
	<li>
		<a href="#">Pepper tatsoi</a>
		<ul class="cbp-tm-submenu">
			<li><a href="#" class="cbp-tm-icon-archive">Brussels sprout</a></li>
			<li><a href="#" class="cbp-tm-icon-cog">Kakadu lemon</a></li>
			<li><a href="#" class="cbp-tm-icon-link">Juice green</a></li>
			<li><a href="#" class="cbp-tm-icon-users">Wine fruit</a></li>
			<li><a href="#" class="cbp-tm-icon-earth">Garlic mint</a></li>
			<li><a href="#" class="cbp-tm-icon-location">Zucchini garnish</a></li>
			<li><a href="#" class="cbp-tm-icon-mobile">Sea lettuce</a></li>
		</ul>
	</li>
	<li>
		<a href="#">Sweet melon</a>
		<ul class="cbp-tm-submenu">
			<li><a href="#" class="cbp-tm-icon-screen">Sorrel desert</a></li>
			<li><a href="#" class="cbp-tm-icon-mail">Raisin kakadu</a></li>
			<li><a href="#" class="cbp-tm-icon-contract">Plum salsify</a></li>
			<li><a href="#" class="cbp-tm-icon-pencil">Bok choy celtuce</a></li>
			<li><a href="#" class="cbp-tm-icon-article">Onion endive</a></li>
			<li><a href="#" class="cbp-tm-icon-clock">Bitterleaf</a></li>
		</ul>
	</li>
</ul>

The CSS

/* Iconfont made with icomoon.com */
@font-face {
	font-family: 'cbp-tmicons';
	src:url('../fonts/tmicons/cbp-tmicons.eot');
	src:url('../fonts/tmicons/cbp-tmicons.eot?#iefix') format('embedded-opentype'),
		url('../fonts/tmicons/cbp-tmicons.woff') format('woff'),
		url('../fonts/tmicons/cbp-tmicons.ttf') format('truetype'),
		url('../fonts/tmicons/cbp-tmicons.svg#cbp-tmicons') format('svg');
	font-weight: normal;
	font-style: normal;
}

/* reset  list style */
.cbp-tm-menu,
.cbp-tm-menu ul {
	list-style: none;
}

/* set menu position; change here to set to relative or float, etc. */
.cbp-tm-menu {
	display: block;
	position: absolute;
	z-index: 1000;
	bottom: 0;
	width: 100%;
	background: #47a3da;
	text-align: right;
	padding: 0 2em;
	margin: 0;
	text-transform: capitalize;
}

/* first level menu items */
.cbp-tm-menu > li {
	display: inline-block;
	margin: 0 2.6em;
	position: relative;
}

.cbp-tm-menu > li > a {
	line-height: 4em;
	padding: 0 0.3em;
	font-size: 1.2em;
	display: block;
	color: #fff;
}

.no-touch .cbp-tm-menu > li > a:hover,
.no-touch .cbp-tm-menu > li > a:active {
	color: #02639d;
}

/* sumbenu with transitions */
.cbp-tm-submenu {
	position: absolute;
	display: block;
	visibility: hidden;
	opacity: 0;
	padding: 0;
	text-align: left;
	pointer-events: none;
	-webkit-transition: visibility 0s, opacity 0s;
	-moz-transition: visibility 0s, opacity 0s;
	transition: visibility 0s, opacity 0s;
}

.cbp-tm-show .cbp-tm-submenu {
	width: 16em;
	left: 50%;
	margin: 0 0 0 -8em;
	opacity: 1;
	visibility: visible;
	pointer-events: auto;
	-webkit-transition: visibility 0s, opacity 0.3s;
	-moz-transition: visibility 0s, opacity 0.3s;
	transition: visibility 0s, opacity 0.3s;
}

.cbp-tm-show-above .cbp-tm-submenu {
	bottom: 100%;
	padding-bottom: 10px;
}

.cbp-tm-show-below .cbp-tm-submenu {
	top: 100%;
	padding-top: 10px;
}

/* extreme cases: not enough space on the sides */
.cbp-tm-nospace-right .cbp-tm-submenu {
	right: 0;
	left: auto;
}

.cbp-tm-nospace-left .cbp-tm-submenu {
	left: 0;
}

/* last menu item has to fit on the screen */
.cbp-tm-menu > li:last-child .cbp-tm-submenu {
	right: 0;
}

/* 	
arrow: depending on where the menu will be shown, we set 
the right position for the arrow
*/

.cbp-tm-submenu:after {
	border: solid transparent;
	content: " ";
	height: 0;
	width: 0;
	position: absolute;
	pointer-events: none;
}

.cbp-tm-show-above .cbp-tm-submenu:after {
	top: 100%;
	margin-top: -10px;
}

.cbp-tm-show-below .cbp-tm-submenu:after {
	bottom: 100%;
	margin-bottom: -10px;
}

.cbp-tm-submenu:after {
	border-color: transparent;
	border-width: 16px;
	margin-left: -16px;
	left: 50%;
}

.cbp-tm-show-above .cbp-tm-submenu:after {
	border-top-color: #fff;
}

.cbp-tm-show-below .cbp-tm-submenu:after {
	border-bottom-color: #fff;
}

.cbp-tm-submenu > li {
	display: block;
	background: #fff;
}

.cbp-tm-submenu > li > a {
	padding: 5px 2.3em 5px 0.6em; /* top/bottom paddings in 'em' cause a tiny "jump" in Chrome on Win */
	display: block;
	font-size: 1.2em;
	position: relative;
	color: #47a3da;
	border: 4px solid #fff;
	-webkit-transition: all 0.2s;
	-moz-transition: all 0.2s;
	transition: all 0.2s;
}

.no-touch .cbp-tm-submenu > li > a:hover,
.no-touch .cbp-tm-submenu > li > a:active {
	color: #fff;
	background: #47a3da;
}

/* the icons (main level menu icon and sublevel icons) */
.cbp-tm-submenu li a:before,
.cbp-tm-menu > li > a:before {
	font-family: 'cbp-tmicons';
	speak: none;
	font-style: normal;
	font-weight: normal;
	font-variant: normal;
	text-transform: none;
	line-height: 1;
	vertical-align: middle;
	margin-right: 0.6em;
	-webkit-font-smoothing: antialiased;
}

.cbp-tm-submenu li a:before {
	position: absolute;
	top: 50%;
	margin-top: -0.5em;
	right: 0.5em;
}

.cbp-tm-menu > li > a:not(:only-child):before {
	content: "f0c9";
	font-size: 60%;
	opacity: 0.3;
}

.cbp-tm-icon-archive:before {
	content: "e002";
}

.cbp-tm-icon-cog:before {
	content: "e003";
}

.cbp-tm-icon-users:before {
	content: "e004";
}

.cbp-tm-icon-earth:before {
	content: "e005";
}

.cbp-tm-icon-location:before {
	content: "e006";
}

.cbp-tm-icon-mobile:before {
	content: "e007";
}

.cbp-tm-icon-screen:before {
	content: "e008";
}

.cbp-tm-icon-mail:before {
	content: "e009";
}

.cbp-tm-icon-contract:before {
	content: "e00a";
}

.cbp-tm-icon-pencil:before {
	content: "e00b";
}

.cbp-tm-icon-article:before {
	content: "e00c";
}

.cbp-tm-icon-clock:before {
	content: "e00d";
}

.cbp-tm-icon-videos:before {
	content: "e00e";
}

.cbp-tm-icon-pictures:before {
	content: "e00f";
}

.cbp-tm-icon-link:before {
	content: "e010";
}

.cbp-tm-icon-refresh:before {
	content: "e011";
}

.cbp-tm-icon-help:before {
	content: "e012";
}

/* Media Queries */
@media screen and (max-width: 55.6875em) {
	.cbp-tm-menu {
		font-size: 80%;
	}
}

@media screen and (max-height: 25.25em), screen and (max-width: 44.3125em) {

	.cbp-tm-menu {
		font-size: 100%;
		position: relative;
		text-align: center;
		padding: 0;
		top: auto;
	}

	.cbp-tm-menu > li {
		display: block;
		margin: 0;
		border-bottom: 4px solid #3793ca;
	}

	.cbp-tm-menu > li:first-child {
		border-top: 4px solid #3793ca;
	}

	li.cbp-tm-show > a,
	.no-touch .cbp-tm-menu > li > a:hover,
	.no-touch .cbp-tm-menu > li > a:active {
		color: #fff;
		background: #02639d;
	}

	.cbp-tm-submenu {
		position: relative;
		display: none;
		width: 100%;
	}

	.cbp-tm-submenu > li {
		padding: 0;
	}

	.cbp-tm-submenu > li > a {
		padding: 0.6em 2.3em 0.6em 0.6em;
		border: none;
		border-bottom: 2px solid #6fbbe9;
	}

	.cbp-tm-submenu:after {
		display: none;
	}

	.cbp-tm-menu .cbp-tm-show .cbp-tm-submenu {
		display: block;
		width: 100%;
		left: 0;
		margin: 0;
		padding: 0;
		bottom: auto;
		top: auto;
	}
	
}

Tiny break: 📬 Want to stay up to date with frontend and trends in web design? Subscribe and get our Collective newsletter twice a tweek.

The JavaScript

/**
 * cbpTooltipMenu.js v1.0.0
 * http://www.codrops.com
 *
 * Licensed under the MIT license.
 * http://www.opensource.org/licenses/mit-license.php
 * 
 * Copyright 2013, Codrops
 * http://www.codrops.com
 */
;( function( window ) {
	
	'use strict';

	var document = window.document,
		docElem = document.documentElement;

	function extend( a, b ) {
		for( var key in b ) { 
			if( b.hasOwnProperty( key ) ) {
				a[key] = b[key];
			}
		}
		return a;
	}

	// from https://github.com/ryanve/response.js/blob/master/response.js
	function getViewportH() {
		var client = docElem['clientHeight'],
			inner = window['innerHeight'];
		if( client < inner )
			return inner;
		else
			return client;
	}

	// http://stackoverflow.com/a/11396681/989439
	function getOffset( el ) {
		return el.getBoundingClientRect();
	}

	// http://snipplr.com/view.php?codeview&id=5259
	function isMouseLeaveOrEnter(e, handler) { 
		if (e.type != 'mouseout' && e.type != 'mouseover') return false; 
		var reltg = e.relatedTarget ? e.relatedTarget : 
		e.type == 'mouseout' ? e.toElement : e.fromElement; 
		while (reltg && reltg != handler) reltg = reltg.parentNode; 
		return (reltg != handler); 
	}

	function cbpTooltipMenu( el, options ) {	
		this.el = el;
		this.options = extend( this.defaults, options );
		this._init();
	}

	cbpTooltipMenu.prototype = {
		defaults : {
			// add a timeout to avoid the menu to open instantly
			delayMenu : 100
		},
		_init : function() {
			this.touch = Modernizr.touch;
			this.menuItems = document.querySelectorAll( '#' + this.el.id + ' > li' );
			this._initEvents();
		},
		_initEvents : function() {
			
			var self = this;

			Array.prototype.slice.call( this.menuItems ).forEach( function( el, i ) {
				var trigger = el.querySelector( 'a' );
				if( self.touch ) {
					trigger.addEventListener( 'click', function( ev ) { self._handleClick( this, ev ); } );
				}
				else {
					trigger.addEventListener( 'click', function( ev ) {
						if( this.parentNode.querySelector( 'ul.cbp-tm-submenu' ) ) {
							ev.preventDefault();
						}
					} );
					el.addEventListener( 'mouseover', function(ev) { if( isMouseLeaveOrEnter( ev, this ) ) self._openMenu( this ); } );
					el.addEventListener( 'mouseout', function(ev) { if( isMouseLeaveOrEnter( ev, this ) ) self._closeMenu( this ); } );
				}
			} );

		},
		_openMenu : function( el ) {

			var self = this;
			clearTimeout( this.omtimeout );
			this.omtimeout = setTimeout( function() {
				var submenu = el.querySelector( 'ul.cbp-tm-submenu' );

				if( submenu ) {
					el.className = 'cbp-tm-show';
					if( self._positionMenu( el ) === 'top' ) {
						el.className += ' cbp-tm-show-above';
					}
					else {
						el.className += ' cbp-tm-show-below';
					}
				}
			}, this.touch ? 0 : this.options.delayMenu );

		},
		_closeMenu : function( el ) {
			
			clearTimeout( this.omtimeout );

			var submenu = el.querySelector( 'ul.cbp-tm-submenu' );

			if( submenu ) {
				// based on https://github.com/desandro/classie/blob/master/classie.js
				el.className = el.className.replace(new RegExp("(^|\s+)" + "cbp-tm-show" + "(\s+|$)"), ' ');
				el.className = el.className.replace(new RegExp("(^|\s+)" + "cbp-tm-show-below" + "(\s+|$)"), ' ');
				el.className = el.className.replace(new RegExp("(^|\s+)" + "cbp-tm-show-above" + "(\s+|$)"), ' ');
			}

		},
		_handleClick : function( el, ev ) {
			var item = el.parentNode,
				items = Array.prototype.slice.call( this.menuItems ),
				submenu = item.querySelector( 'ul.cbp-tm-submenu' )

			// first close any opened one..
			if( this.current &&  items.indexOf( item ) !== this.current ) {
				this._closeMenu( this.el.children[ this.current ] );
				this.el.children[ this.current ].querySelector( 'ul.cbp-tm-submenu' ).setAttribute( 'data-open', 'false' );
			}

			if( submenu ) {
				ev.preventDefault();

				var isOpen = submenu.getAttribute( 'data-open' );

				if( isOpen === 'true' ) {
					this._closeMenu( item );
					submenu.setAttribute( 'data-open', 'false' );
				}
				else {
					this._openMenu( item );
					this.current = items.indexOf( item );
					submenu.setAttribute( 'data-open', 'true' );
				}
			}

		},
		_positionMenu : function( el ) {
			// checking where's more space left in the viewport: above or below the element
			var vH = getViewportH(),
				ot = getOffset(el),
				spaceUp = ot.top ,
				spaceDown = vH - spaceUp - el.offsetHeight;
			
			return ( spaceDown <= spaceUp ? 'top' : 'bottom' );
		}
	}

	// add to global namespace
	window.cbpTooltipMenu = cbpTooltipMenu;

} )( window );

Manoela Ilic

Manoela is the main tinkerer at Codrops. With a background in coding and passion for all things design, she creates web experiments and keeps frontend professionals informed about the latest trends.

Stay in the loop: Get your dose of frontend twice a week

Fresh news, inspo, code demos, and UI animationsโ€”zero fluff, all quality. Make your Mondays and Thursdays creative!

Feedback 56

Comments are closed.
  1. What about submenus ?

    Also the mobile responsive version doesn’t react onclick but onhover: unusable on mobile devices.

    • Did you actually try the mobile version or did you just resize the window ๐Ÿ™‚ ?

    • It does work with JS turned off: it’s a normal link then.
      If you would like the submenu to appear you could do that with :hover although you would have to choose then if you want it to appear above or below.
      Cheers, ML

  2. nice! I like it! but shouldn’t we call these simply drop-downs? (or “drop-ups”)
    for me, a tooltip is a very simple helper, with a few info or hint.
    but maybe that’s just a technical thing.

  3. Awesome look..
    Wanted to try it on ie7 it didnt worked for me..
    Can u please tell me which old ver of ie is compatible with this menu?

  4. Absolutely love this! Is there any easy way to make it stick to the top of the viewport once scrolled past?

  5. Thanks, looks very cool. But in there isn’t “home” element, the first tooltip doesn’t close

    • OK got it! I’ve fixed it and the download files are now updated. Thanks a lot for your feedback. Cheers, ML

  6. sup-menu here li link cant work why? how to sup-menu with top li href link create please help?

  7. Really liking this Mary Lou! How difficult would this be to adapt for left/right usage? For example if I hovered over an icon for it to display a tooltip div of content to the left/right depending on available space?

  8. I really like this menu and have been trying to implement it, however I can not get the first item(menu item you hover over) to be clickable for some reason. wondering if there is a fix for that?

    • Hello there,

      I have the same problem, if someone could help me i’ll be appriciated.

      And btw, Great Job Mary Lou.

    • Ok, I got it working.

      Just have removed the line:

      j.addEventListener(“click”, function (m) {
      if (this.parentNode.querySelector(“ul.cbp-tm-submenu”)) {
      m.preventDefault()
      }
      });

  9. Is there anyway to enable the menu items as links too? This would be perfect if I could.

  10. I`ve tried this menu and i can say it is great, but i encountered an issue with it. I cannot assign links to each of the section from the menu. With id`s it works very well but when i try to put some links in it is not working anymore.

    Do you have any suggestions on this ??

    Thank you

  11. this is awesome, i just have a quick question. How do I add rounded borders to the submenu? I’ve tried placing the border-radius property on just about everything and can’t figure out why its not doing it. Help?

  12. Hello Mary Lou,

    First of all, thank you very much for this design. It helped me a LOT on my site, but I got a question.

    I’m having problems making this work on IE7. Is it possible to run it on this version or do you need additional scripting? If so, could you help me with that?

    Thanks in advance!

  13. I love this menu! Works great in Chrome and Firefox but having trouble in IE10. Any ideas?

  14. Hi ! beautiful menu ! but but i does not work on ie8 !! thats killing me ! is there a solution? Thanks !!

  15. Very nice. Thanks for your sharing and knowledge.
    For this tooltip menu, is it possible that the anchor link of the parent menu (in your demo, they are “Veggie made,” “Pepper Tatsoi”) can also be enabled?
    In the demo, when I click “veggie made,” it cannot link to URL that I assigned in the markup.

    Thanks in advance,
    Chris

  16. Hi, I am using this and still working fine in all browser except ie8.
    Can you please give me better solution for ie8?
    It’s very important for me.

    Thanx…

  17. Hello, I am facing a problem regarding the use of this code in Explorer8. It does not run in the browser. Is there any solution for this?

  18. Hello. To solve the problem of the menu which does not display under IE8, I added this Javascript code;

    $(“.cbp-tm-menu .menuSelect1”).hover(function()
    {
    $(“.cbp-tm-menu .menuSelect1”).addClass(“cbp-tm-show”);
    },

    function()
    {
    $(“.cbp-tm-menu .menuSelect1”).removeClass(“cbp-tm-show”);
    }
    );

    “MenuSelect1” is the class of the “li” corresponding to the one that you hover.

    It is of the do-it-yourself, but that works under IE8 ๐Ÿ™‚

  19. When the cbp-tm-show class or any other class is applied to the li it replaces the entire class=”” with just cbp-tm-show, is there anyway to change the code so it appends the class names instead?

  20. I am searching for an IE8-Fix, too. I searched several hours but I’m not able to fix it.
    Please, if anyone got a solution post it here… ๐Ÿ™

  21. Hi!

    I got it! I finally got it!! I got it running under IE8! ๐Ÿ™‚ ๐Ÿ™‚

    Just replace your “cbpTooltipMenu.js” with this one:
    There are changes in the Top and in the middle of the file. I hope this helps some people save some time! ๐Ÿ˜‰

    Greetings.
    jo

    /** * cbpTooltipMenu.js v1.0.0 * http://www.codrops.com * * Licensed under the MIT license. * http://www.opensource.org/licenses/mit-license.php * * Copyright 2013, Codrops * http://www.codrops.com */ /* IE 8 Shim */ if (!Array.prototype.forEach) { Array.prototype.forEach = function (fn, scope) { 'use strict'; var i, len; for (i = 0, len = this.length; i < len; ++i) { if (i in this) { fn.call(scope, this[i], i, this); } } }; } ;( function( window ) { 'use strict'; var document = window.document, docElem = document.documentElement; function extend( a, b ) { for( var key in b ) { if( b.hasOwnProperty( key ) ) { a[key] = b[key]; } } return a; } // from https://github.com/ryanve/response.js/blob/master/response.js function getViewportH() { var client = docElem['clientHeight'], inner = window['innerHeight']; if( client < inner ) return inner; else return client; } // http://stackoverflow.com/a/11396681/989439 function getOffset( el ) { return el.getBoundingClientRect(); } // http://snipplr.com/view.php?codeview&id=5259 function isMouseLeaveOrEnter(e, handler) { if (e.type != 'mouseout' && e.type != 'mouseover') return false; var reltg = e.relatedTarget ? e.relatedTarget : e.type == 'mouseout' ? e.toElement : e.fromElement; while (reltg && reltg != handler) reltg = reltg.parentNode; return (reltg != handler); } function cbpTooltipMenu( el, options ) { this.el = el; this.options = extend( this.defaults, options ); this._init(); } cbpTooltipMenu.prototype = { defaults : { // add a timeout to avoid the menu to open instantly delayMenu : 100 }, _init : function() { this.touch = Modernizr.touch; this.menuItems = document.querySelectorAll( '#' + this.el.id + ' > li' ); this._initEvents(); }, _initEvents : function() { var self = this; Array.prototype.forEach.call(this.menuItems, function( el, i ) { var trigger = el.querySelector( 'a' ); if( self.touch ) { trigger.addEventListener( 'click', function( ev ) { self._handleClick( this, ev ); } ); } else { $(el).on({mouseenter: function() { self._openMenu(this); } ,mouseleave: function(){ self._closeMenu(this); } }); /*IE8 Doesn't support addEventListener, but it does support attachEvent if (el.addEventListener){ el.addEventListener( 'mouseover', function(ev) { if( isMouseLeaveOrEnter( ev, this ) ) self._openMenu( this ); } ); el.addEventListener( 'mouseout', function(ev) { if( isMouseLeaveOrEnter( ev, this ) ) self._closeMenu( this ); } ); } else if (el.attachEvent){ el.attachEvent( 'onmouseover', function(ev) { if( isMouseLeaveOrEnter( ev, this ) ) self._openMenu( this ); } ); el.attachEvent( 'onmouseout', function(ev) { if( isMouseLeaveOrEnter( ev, this ) ) self._closeMenu( this ); } ); } */ } } ); }, _openMenu : function( el ) { var self = this; clearTimeout( this.omtimeout ); this.omtimeout = setTimeout( function() { var submenu = el.querySelector( 'ul.cbp-tm-submenu' ); if( submenu ) { el.className = 'cbp-tm-show'; if( self._positionMenu( el ) === 'top' ) { el.className += ' cbp-tm-show-above'; } else { el.className += ' cbp-tm-show-below'; } } }, this.touch ? 0 : this.options.delayMenu ); }, _closeMenu : function( el ) { clearTimeout( this.omtimeout ); var submenu = el.querySelector( 'ul.cbp-tm-submenu' ); if( submenu ) { // based on https://github.com/desandro/classie/blob/master/classie.js el.className = el.className.replace(new RegExp("(^|\\s+)" + "cbp-tm-show" + "(\\s+|$)"), ' '); el.className = el.className.replace(new RegExp("(^|\\s+)" + "cbp-tm-show-below" + "(\\s+|$)"), ' '); el.className = el.className.replace(new RegExp("(^|\\s+)" + "cbp-tm-show-above" + "(\\s+|$)"), ' '); } }, _handleClick : function( el, ev ) { var item = el.parentNode, items = Array.prototype.slice.call( this.menuItems ), submenu = item.querySelector( 'ul.cbp-tm-submenu' ) // first close any opened one.. if( typeof this.current !== 'undefined' && items.indexOf( item ) !== this.current ) { this._closeMenu( this.el.children[ this.current ] ); this.el.children[ this.current ].querySelector( 'ul.cbp-tm-submenu' ).setAttribute( 'data-open', 'false' ); } if( submenu ) { ev.preventDefault(); var isOpen = submenu.getAttribute( 'data-open' ); if( isOpen === 'true' ) { this._closeMenu( item ); submenu.setAttribute( 'data-open', 'false' ); } else { this._openMenu( item ); this.current = items.indexOf( item ); submenu.setAttribute( 'data-open', 'true' ); } } }, _positionMenu : function( el ) { // checking where's more space left in the viewport: above or below the element var vH = getViewportH(), ot = getOffset(el), spaceUp = ot.top , spaceDown = vH - spaceUp - el.offsetHeight; return ( spaceDown <= spaceUp ? 'top' : 'bottom' ); } } // add to global namespace window.cbpTooltipMenu = cbpTooltipMenu; } )( window );

    • ๐Ÿ™ It’s not working man.. I tried it but nope. Anyway maybe i did a mistake? ( I just replaced my ToolTip Menu by yours)

  22. Hey! I’m Impressed!

    How can i modyfy the code that menu will drop at the bottom even if it will be at mobile size?

    • I answer my own question, just I have to add this in the .css:
      /* for the FIRST element of the menu*/ .cbp-tm-menu li:first-child .cbp-tm-submenu{ left: 100%; } .cbp-tm-menu li:first-child .cbp-tm-submenu:after{ /* arrow*/ left: 30%; } /* for the LAST element of the menu*/ .cbp-tm-menu li:last-child .cbp-tm-submenu{ left: 0; } .cbp-tm-menu li:last-child .cbp-tm-submenu:after{/* arrow*/ left: 70%; }

  23. Hey,
    I wanted to know if there was some way to keep the main links in their hover state when we move our pointer to the sub menus.
    (Basically I want the darker blue colour the “Veggie Made” gets to remain when my pointer is over the sub menus)
    And thanks for an awesomely written tutorial! ๐Ÿ™‚

  24. I really like this menu, but I’m having some trouble with it. It’s working perfectly well on my desktop and is responding when is make the window smaller, but the mobile version shows the full menu. Can anyone offer any advice?

    Also, I’d actually prefer it if the mobile version actually collapsed completely, leaving only the menu symbol. Do you have a working example of that?

  25. Hi! i love your menu, but how can we add a 3er SUbmenu type ?

    <ul> <li> <a> Principal</a> <ul class='cbp-tm-submenu'> <li> <a> Second </a> <ul class='cbp-tm-submenu'> <li> <a> item</a></li> <li> <a> item</a></li> <li> <a> item</a></li> </ul> <!-- items !--> </li> </ul><!-- second !--> </li> </ul> <!-- Principal !-->

  26. Haizz, i am so bad :”(, i can’t do any think with this tut because my english is so bad T__T