欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

网页导航菜单的子菜单平铺(带背景栏)实现

程序员文章站 2022-06-15 10:21:46
- 之前给公司做的一个小型知识库管理网站时遇到一个问题,在这里记录下解决的过程。 公司的美工要求首页导航菜单 要跟他们公司的网站风格保持一致,如图所示 (子菜单是平铺的) 我一看,心想很简单嘛 先贴一下通用菜单html结构
  • 热设计

     

    -

      之前给公司做的一个小型知识库管理网站时遇到一个问题,在这里记录下解决的过程。

       公司的美工要求首页导航菜单 要跟他们公司的网站风格保持一致,如图所示

     

    网页导航菜单的子菜单平铺(带背景栏)实现

     

     

    (子菜单是平铺的)

     

       网页导航菜单的子菜单平铺(带背景栏)实现

    我一看,心想很简单嘛

    先贴一下通用菜单html结构

    <li>
         <a href="" class="abc">热设计</a>
              <ul>
                   <li><a href="">设计规范</a></li>
                   <li><a href="">案例分享</a></li>
                   <li><a href="">经验文章</a></li>

              </ul>
         
    </li>

     只要设置子菜单的<li>css为float:left,并给<ul>设置背景就可以了嘛

    但是 实现的时候发现并不简单,因为<ul>的位置是基于一级菜单<li>的位置的,所以<ul>的背景栏只会从一级菜单的<li>的位置开始显示,不会显示通栏(背景栏会铺满页面)

    于是我想给子菜单的<ul>外面包一层<div>,并设置<div> position:absolute;   left:0;  top:0;并取消一级菜单<li>的position:relative属性

    最终得到这样的结果

    网页导航菜单的子菜单平铺(带背景栏)实现

     

    网页导航菜单的子菜单平铺(带背景栏)实现

     

    虽然背景栏铺满了,但是子菜单却不跟一级菜单对齐了。

    通常是设置以及菜单的<li>为position:relative;而子菜单的<ul>(或本例中外层的div)为position:absolute,(偏移多少可以自行设置left跟top)这样就可以使子菜单随父菜单对齐了,

    但是为了设置通栏的背景,去掉了一级菜单<li>的position:relative属性,导致子菜单无法跟踪父菜单;

    于是设想 仍设置一级菜单<li>为position:relative,而设置div为position:fixed(position为fixed时只会根据整个屏幕进行布局,并始终悬浮,父容器的position是否为relative并不影响)

    同时设置子菜单的<ul>为position:absolute,意图是想让子菜单<ul>跨过其父容器<div>,而去跟踪祖容器(即一级菜单的<li>)位置(因为了解到容器的position设置为absolute时,会去查找它父容器是否设置了position为relative,若设置了则根据其位置进行定位,若未设置就继续往上层祖容器查找,若都未设置,则根据页面进行定位)

    结果如图:

    网页导航菜单的子菜单平铺(带背景栏)实现

    网页导航菜单的子菜单平铺(带背景栏)实现

    子菜单全部移动到最左侧了(因为设置了left:0),说明子菜单没有追踪一级菜单的<li>,而是跟随了其父容器<div>的位置,就是说父容器只要设置了position属性,不管是否为relative,子容器都会根据其位置进行定位。

    这样从逻辑上确定了只靠css是无法实现需要的效果的

    {

       1 要想设置背景为通栏,只能设置div为positon:absolute;left:0;且不能设置一级菜单<li>的position属性;

       2 要想让子菜单追踪父菜单的位置,必须设置父菜单的position:relative,同时设置子菜单position:absolute;

       1与2互相矛盾

    }

    所以 我们只能另寻他法,即jquery

    jquery有一个名为 offset() 的方法,可以获取某个元素的位置(若该元素是基于父元素的位置定位的,在该方法获得相对于父元素的位置,不然则是相对于整个屏幕的位置)

    如元素p, var pos=p.offset(), pos具有两个属性:p.top , p.left,根据字面意思就可以了解其含义;同时offset(top:x;top:y)可以动态设置元素的位置

    我们在菜单的hover事件中对子菜单进行定位,代码如下所示

     

      var _this1 = null;
                $('.nav>li').hover(function () {
                    _this1 = $(this);
                    _this1.find('.second-nav').show();
                    var p = _this1.offset();
                    _this1.find('.second-nav').find('ul').offset({top:p.top+50,left:p.left-50})
                    _this1.find('.abc').css('color', ' #ff6a00')
                    var _this2 = null;
                    _this1.find('.second-nav').find('li').hover(function () {
                        _this2 = $(this);
                        _this2.find('.third-nav').show();
                        _this2.find('.third-nav').hover(function () {
                            $(this).show();
                        }, function () {
                            $(this).hide();
                        });
                    }, function () {
                        _this2.find('.third-nav').hide();
                    });
                }, function () {
                    _this1.find('.second-nav').hide();
                    _this1.find('.abc').css('color', ' #fff')
    
                });

    其中加粗斜体为新加的两行代码(其他的代码都是导航菜单原有的),其中_this变量为鼠标滑过的一级菜单标题的<li>,

    _this.offset()取得当前激活标题相对于屏幕的位置,并存入变量p,然后

    _this1.find('.second-nav').find('ul').offset({top:p.top+50,left:p.left-50})

    然后根据_this找到子代元素<ul>应用offset(top:x,left:y)方法进行定位,最后得到需要的结果

    网页导航菜单的子菜单平铺(带背景栏)实现

     

    网页导航菜单的子菜单平铺(带背景栏)实现

    现在来看,这实在不算什么问题,解决方案也很简单,如果对jquery了解够多的话

    当然,这都是后话了,当时还是纠结了好久,心路历程很曲折哈哈。

    还是要把基础学扎实。