WordPress 多级导航菜单
多级导航菜单, 是指菜单存在多个层次, 层层嵌套, 当鼠标移动到某个菜单时, 如果其包含子菜单则将相应的子菜单显示出来. 本文将提供此功能在 WordPress 的实现方法, 一般的 HTML 页面和其他程序也可以加工套用.
时隔 9 个多月, 关于导航菜单的话题又回来了. 上次写到三级菜单就不写了是因为我发现自己根本用不上, 就没去研究. 最近我在做一个小玩意儿用到了这个, 所以把它给做了出来并集成到 iNove 主题上. 因为内容繁多, 所以还是以之前的文章和代码作为基础来展开讲解, 希望这个文章会对大家有所帮助.
为了简化处理, 明确目标, 这次我们会以二级导航菜单作为原型进行扩展. 本文只对多级菜单相关处理进行讨论, 其他内容请参考以前的几篇关于菜单导航的文章, 文章链接你可以在本文相关话题中找到.
相关话题:
WordPress 导航菜单
二级导航菜单
淡出淡入导航菜单
滚动导航菜单
jQuery 导航菜单
多级导航菜单
点选式导航菜单 (待定话题)
作业分析:
因为菜单由本来的二级菜单变成了多级菜单, 所以菜单结构会有些变化 (会有新的更深层的子菜单加入). 另外, 页面的样式和脚本都会有相应的变更, 重点在于对 JavaScript 的加工.
主要操作如下:
1. 鼠标移动到一级菜单的菜单项时, 如果该菜单项包含了二级菜单, 那么在下方显示其子菜单.
2. 鼠标移动到 N (N >= 2) 级菜单的菜单项时, 如果该菜单项包含了 N+1 级菜单, 那么在右侧显示其子菜单.
预想结构:
<div id="menubar"> <ul class="menus"> <li class="..."><a href="http://.../">Home</a></li> <li class="..."> <a href="http://.../">菜单1</a> <ul class="children"> <li class="..."><a href="http://.../">菜单11</a></li> <li class="..."> <a href="http://.../">菜单12</a> <ul class="children"> <li class="..."><a href="http://.../">菜单121</a></li> <li class="..."><a href="http://.../">菜单122</a></li> <li class="..."><a href="http://.../">菜单123</a></li> <li class="..."><a href="http://.../">菜单124</a></li> </ul> </li> <li class="..."> <a href="http://.../">菜单13</a> <ul class="children"> <li class="..."><a href="http://.../">菜单131</a></li> <li class="..."><a href="http://.../">菜单132</a></li> </ul> </li> </ul> </li> <li class="..."> <a href="http://.../">菜单2</a> <ul class="children"> <li class="..."><a href="http://.../">菜单21</a></li> </ul> </li> <li class="..."> <a href="http://.../">菜单3</a> <ul class="children"> <li class="..."><a href="http://.../">菜单31</a></li> <li class="..."> <a href="http://.../">菜单32</a> <ul class="children"> <li class="..."><a href="http://.../">菜单321</a></li> <li class="..."><a href="http://.../">菜单322</a></li> </ul> </li> </ul> </li> ... </ul> </div>
实施操作:
1. 调出无限级菜单 (子分类)
是否还记得如何设定列表的深度? 可以通过参数 depth 来进行设定. 当我们将深度设为 1 时不显示子分类, 将深度设为 2 时显示二级菜单. 现在我们要无限制层数的菜单, 所以可以去除这个参数, 系统会自动返回所有菜单. 所以显示菜单的代码如下:
<?php wp_list_pages('depth=2&title_li=0&sort_column=menu_order'); ?>
2. 修改菜单的样式
在子菜单项添加 display:inline; 以免在 IE (IE6/IE7/IE8) 中发生错位.
/* 子菜单的菜单项 */ #menubar ul.children li { float:none; /* 垂直排列 */ margin:0; padding:0; /* multi 2009/06/11 ADD START */ display:inline; /* 对 IE 来说十分很重要 */ /* multi 2009/06/11 ADD END */ }
追加包含子菜单的菜单项的样式
#menubar ul.children li a.subtitle { border-right:3px solid #4281B7; width:97px; }
添加当前菜单的效果, 以明确当前路径.
#menubar ul.menus li a:hover, /* multi 2009/06/11 ADD START */ #menubar ul.menus li a.current { /* multi 2009/06/11 ADD END */ background:#4281B7; /* 背景颜色 */ }
3. 加载菜单
加载菜单是应该分开处理, 对于对层次的菜单, 菜单显示有两种状态. (1) 作为二级菜单显示在上一级菜单的下方; (2) 而三级和以上层次的菜单则会显示在上一级菜单的右侧.
// 找到所有的菜单 var menus = this.obj.getElementsByTagName('ul'); for (var i = 0; i < menus.length; i++) { // 找到菜单的父节点 (包括标题链接部分) var menu = menus[i].parentNode; // 如果菜单的父节点就是根菜单, 显示一般的菜单 if(menu.parentNode === this.obj) { new Menu(menu, opacity); // 如果菜单的父节点不是根菜单, 说明当前菜单是子菜单 } else { new Menu(menu, opacity, 1); // 在子菜单的标题链接上加上 class 名, 以便定义样式 menu.firstChild.className += ' subtitle'; } }
4. 菜单的初始化
添加一个参数, 以识别是否为子菜单 (三级以上的菜单); 去除 overflow:hidden; 的设置, 否则子菜单无法显示出来.
initialize: function(target, opacity, sub) { this.util = new MenuUtil(); // 获取目标菜单 (没多余元素) this.obj = this.util.cleanWhitespace(target); // 定义透明度, 默认透明 this.opacity = opacity || 1; /* multi 2009/06/11 ADD START */ // 是否为子菜单 this.sub = sub || -1; /* multi 2009/06/11 ADD START */ // 获取菜单 this.menu = this.obj.childNodes // 重要! 如果菜单不包含菜单项, 则不进行处理 if (this.menu.length < 2) { return; } // 菜单标题和菜单体 this.title = this.menu[0]; this.body = this.menu[1]; // 定义初始样式 this.util.setStyle(this.body, 'visibility', 'hidden'); this.util.setStyle(this.body, 'position', 'absolute'); /* multi 2009/06/11 DELETE START */ //this.util.setStyle(this.body, 'overflow', 'hidden'); /* multi 2009/06/11 DELETE END */ this.util.setStyle(this.body, 'display', 'block'); // 添加监听器 this.addListener(this.obj, 'mouseover', this.util.bind(this, this.activate), false); this.addListener(this.obj, 'mouseout', this.util.bind(this, this.deactivate), false); }
5. 对菜单和子菜单分开处理
菜单 (二级菜单) 的位置是相对于窗口的, 而子菜单 (三级或以上菜单) 是的位置是相对于上一级菜单的, 所以必须判断是哪种菜单类型, 并以不同的方法来确定位置. 另外, 两者要显示的位置也不相同, 所以在激活方法内还需要以不同的方式将 top 和 left 位置计算出来.
// 获取当前菜单体的位置 (子菜单) if(this.sub == 1) { var pos = this.util.currentOffset(this.title); var left = this.util.getWidth(this.body); var top = pos[1]; // 获取当前菜单体的位置 (菜单) } else { var pos = this.util.cumulativeOffset(this.title); var left = pos[0]; var top = pos[1] + this.util.getHeight(this.title); // 子菜单不需要设置不透明度, 否则会形成多重透明, 效果不好. this.util.setStyle(this.body, 'opacity', this.opacity); }
6. 添加当前菜单的 className
为了更好的表示当前菜单的上级菜单, 在激活菜单的时候为当前菜单加上 className.
// 当前选中菜单加上 class 名为, 以便定义样式 this.title.className += ' current';
并且在解除菜单的时候移除菜单上的 className.
// 离开菜单时取消当前菜单上的 class 名, 恢复原本的样式 this.title.className = this.title.className.replace('current', '');
演示主题:
以 WordPress 自带主题 default 为基础, 仅做学习参考使用, 修改过的文件有 header.php 和 style.css, 添加了文件 js/menu.js
下载主题: default_with_menubar_5.zip
下回预告:
下次讨论点选式菜单, 或者 CSS 实现的菜单, 或者 jQuery 实现的各类菜单.
菜单是出来了,没法下拉,继续学习~
不错的讲解,正好需要集成这个功能
效果感觉很好哈,试试看……
请问子菜单的背景要怎么设?
#menubar ul.menus li a:hover,
#menubar ul.menus li a.current {
background:#4281B7; /* 背景颜色 */
这个背景颜色是鼠标移到子菜单上才显示的,但是鼠标在一级菜单上时下拉子菜单的背景是透明的,怎么样让子菜单只要显示出来就有背景?
特来道谢
感谢你的这个多级导航菜单
帮了我不少忙
谢谢mg12
我做了,不好看,我不知道如何弄成竖排的
Internet Explorer 8 have been my most used browser this year, it is definitely stable and fast loading too. .'
Internet Explorer 8 is very good because it is as stable as Opera. I hate the previous versions of IE like IE6 because it hangs frequently. .
@wpmuer
Purecss 是什么主题? 我不能保证代码不修改就能适用所有主题, 请找主题作者问一下吧.
@John
这是 WP 默认就生成的.
@bolo
Yeah~
@John
wp_list_pages的depth等于0或大于1,当存在子页面时就自动生成了
请问楼主那个中的class=children 是怎么加进去的?thanks!
首先感谢楼主的教程
想向楼主请教
我想把这种菜单添加到其他主题
Purecss 但始终无法显示多级效果
但是在其他的主题中成功了
请问这是问什么
希望楼主赐教
谢谢mg12,是我没注意仔细看,以为通不过xhtml是这个原因,现在问题已解决。
@mg12
@SorryDreams
ul 里面嵌套 li, li 再嵌套 ul, 为什么不符合嵌套规则? 可以通过 XHTML 的.
可以实现预想的效果,但是ul里面嵌套ul,不符合嵌套规则,也通不过xhtml检验吧。有没有其他方法?
哦 这个可以试一试的
Thanks a lot for this tip.
@mg12
原来如此~ 我可以帮你测试哈哈~~
@chisdy
这篇文章就是教你怎么用的, 以后我的所有主题都会集成.
@brea
不是, 我显卡驱动有点问题, 我还没配置好. 等闲点再弄.
@zozoozo
你试试Highslide4WP。
@mg12
不好意思,少写了个0,是3.0.11~~
不过以我浅薄的经验,linux似乎不太容易垮的吧。。。你是不是干什么坏事了
这东西好,哪都能用。