纯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>
View Code

 

posted @ 2017-12-13 17:23  【云】风过无痕  阅读(1133)  评论(0编辑  收藏  举报