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

Posted zjh1437

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了网页导航菜单的子菜单平铺(带背景栏)实现相关的知识,希望对你有一定的参考价值。

 

-

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

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

 

技术分享图片

 

 

(子菜单是平铺的)

 

   技术分享图片

我一看,心想很简单嘛

先贴一下通用菜单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了解够多的话

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

还是要把基础学扎实。

 










以上是关于网页导航菜单的子菜单平铺(带背景栏)实现的主要内容,如果未能解决你的问题,请参考以下文章

常用的几个JQuery代码片段

12个用得着的 JQuery 代码片段

如何将片段目标绑定到底部导航栏中的菜单项?

面向对象组件——下拉菜单

vue菜单切换导航栏不见了

请问如何设置bootstrap导航栏中的菜单项居中均匀分布?谢谢