纯css实现无限嵌套菜单
效果图:
demo:关键的地方都以颜色明显标识
<!DOCTYPE html> <html> <head> <title>menu</title> <meta charset="UTF-8" > <style type="text/css"> .menu { display: inline-block; box-shadow: 0 5px 15px #d8d8d8; } .menu-item { width: 100px; position: relative; padding: 5px 10px 5px 50px; border-bottom: 1px solid #e5f0f6; } .item-child { position: absolute; } .menu-item:hover{ background: #eefbff; } .menu-item .item-child{ top: 0; left: calc(100% + 3px); visibility: hidden; opacity: 0; box-shadow: 0 5px 15px #d8d8d8; transition: visibility 0.5s ease, opacity 0.5s ease; } .menu-item:hover > .item-child{ visibility: visible; opacity: 1; } .menu-item > .item-child:active {/* 这种方式无法触发点击事件,最好改为js处理消失 */ display: none; } span::after { content: '...'; right: 10px; position: absolute; } span:only-child::after { content: ''; } </style> </head> <body> <div class="wrap"> <div class="menu"> <div class="menu-item"> <span>title-1</span> <div class="item-child"> <!-- 一级嵌套 --> <div class="menu-item"> <span>title-1-1</span> </div> <div class="menu-item"> <span>title-1-2</span> </div> <div class="menu-item"> <span>title-1-3</span> <div class="item-child"> <!-- 二级嵌套 --> <div class="menu-item"> <span>title-1-3-1</span> </div> <div class="menu-item"> <span>title-1-3-2</span> </div> <div class="menu-item"> <span>title-1-3-3</span> </div> </div> </div> </div> </div> <div class="menu-item"> <span>title-2</span> <div class="item-child"> <div class="menu-item"> <span>title-2-1</span> </div> <div class="menu-item"> <span>title-2-2</span> </div> <div class="menu-item"> <span>title-2-3</span> </div> <div class="menu-item"> <span>title-2-4</span> </div> </div> </div> </div> </div> </body> </html>
二、基于jquery plugin版本
<!DOCTYPE html> <html> <head> <title>menu</title> <script type="text/javascript" src="js/jquery.min.js"></script> <meta charset="UTF-8" > <style type="text/css"> .cmenu { display: inline-block; box-shadow: 0 5px 15px #d8d8d8; position: absolute; } .cmenu-item { width: 100px; position: relative; padding: 5px 10px 5px 50px; border-bottom: 1px solid #e5f0f6; } .item-child { width: 0; position: absolute; top: 0; visibility: hidden; opacity: 0; box-shadow: 0 5px 15px #d8d8d8; transition: all .3s ease .2s; } .cmenu-item:hover{ background: #eefbff; } .cmenu-item:hover > .item-child{ width: 100%; visibility: visible; opacity: 1; } .item-child>.cmenu-item{ height: 0; padding: 0; transition: all .3s ease .2s; } .cmenu-item:hover>.item-child>.cmenu-item{ height: 20px; padding: 5px 10px 5px 50px; } .cmenu.item-left .item-child { left: calc(100% + 1px); } .cmenu.item-right .item-child { right: calc(100% + 1px); } .cmenu span::after { content: '...'; right: 10px; position: absolute; } .cmenu span:only-child::after { content: ''; } .hidden { display: none; } .disabled{ color: silver; } </style> </head> <body> <div class="wrap"> <div id="mn" style="position: absolute;right: 900px;"></div> </div> </body> <script type="text/javascript"> (function($){ function _init(ctn,op){ ctn.innerHTML = ''; ctn.classList.add('cmenu'); _initEvent(ctn,op);/*绑定事件*/ if(op.url){ $.getJson(op.url,function(data){ _createMenuItem(ctn,data); }); }else if(op.data) _createMenuItem(ctn,op.data,op); } function _createMenuItem(pNode,data,op){/* 迭代生成子孙节点 */ data.map(function(item){ var itemNode = $('<div class="cmenu-item"></div>'), spanNode = $('<span>'+item.text+'</span>'); itemNode.data('info',item); if(item.show == false) itemNode.addClass('hidden'); if(item.disable == true) itemNode.addClass('disabled'); $(pNode).append(itemNode.append(spanNode)); if(item.children) { var childNode = $('<div class="item-child"></div>'); $(itemNode).append(childNode); _createMenuItem(childNode,item.children,op); } }); } function _initEvent(ctn,op){ $(ctn).off('click'); $(ctn).on('click',function(){ event = window.event || arguments.callee.caller.arguments[0]; var node = event.target, cList = node.classList; if(!Array.from(cList).includes('cmenu-item')) node = $(node).parents('.cmenu-item:first'); var infoRow = $(node).data('info'); if(!infoRow.disable && op.click && typeof op.click == 'function') op.click(infoRow); $('.item-child').addClass('hidden'); event.stopPropagation(); setTimeout(function(){ $('.item-child').removeClass('hidden'); },50); }); $(ctn).off('mouseenter').on('mouseenter',function(){ var pageX = document.documentElement.clientWidth, itemX = ctn.offsetLeft, isLess = pageX-itemX-100<200; if(isLess){ ctn.classList.remove('item-left'); ctn.classList.add('item-right'); }else{ ctn.classList.add('item-left'); ctn.classList.remove('item-right'); } }); } $.fn.cmenu = function(options,param){ /* 判断是否为对外调用API */ if(typeof option == 'string') $.fn.cmenu.methods[options](this,param); /* 初始化组件 */ var op = $.extend({},$.fn.cmenu.defaults,options); return this.each(function(){ _init(this,op); }); } $.fn.cmenu.methods = { } $.fn.cmenu.defaults = { } })(jQuery) /* 上面的js放到公共js文件中即可 */ var data = [ {text:'编程类',id:1,cls:'', children:[ {text:'Java',show:true,disable: true}, {text:'Javascript',id:4,cls:'',show:false}, {text:'Python',id:5,cls:'',show:true, children:[ {text:'object',disable: true}, {text:'array'}, {text:'string'}, {text:'array'}, {text:'string'}, {text:'array'}, {text:'string'}, {text:'array'}, {text:'string'}, {text:'array'}, {text:'string'}, {text:'array'}, {text:'string'} ] } ] }, {text:'算法类',id:2,cls:'',show:true} ]; $('#mn').cmenu({data:data,click:clickEvent}); function clickEvent(row){ console.log(row); } </script> </html>