这是一个比较简单实用的菜单,最重要的是他不需要引用jQuery库。菜单在垂直方向上能做到自适应,当主菜单靠近顶部,子菜单将会在下面,当主菜单靠近底部,子菜单在上面。运用Modernizr的触摸检测功能,我们可以让子菜单的响应在pc上是hover,而在触摸设备上是点击。例子中还示范了如何在宽度比较窄的情况下如何调整布局。分享一个最好用的UI前端框架!
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>
- <a style="font-family: Arial; white-space: normal; background-color: #ffffff;" target="_blank" href="/topic/1132907">前端UI分享</a>
- </ul>
css代码分享一个最好用的UI前端框架!
- /* 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;
- }
- <a style="font-family: Arial;" target="_blank" href="/topic/1132907">前端UI分享</a>
- .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;
- }
- <a style="font-family: Arial;" target="_blank" href="/topic/1132907">前端UI分享</a>
- /* 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;
- }
- <a style="font-family: Arial;" target="_blank" href="/topic/1132907">前端UI分享</a>
- .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%;
- }
- }
- <a style="font-family: Arial;" target="_blank" href="/topic/1132907">前端UI分享</a>
- @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;
- }
- }
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();
- }
- <a target="_blank" href="/topic/1132907">前端UI分享</a>
- 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' );
- }
- }
- },
- arget="_blank" href="/topic/1132907">前端UI分享</a>
- _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 );