- 纯CSS下拉菜单(推荐) - 代码简洁,性能好,适合大多数情况。
- 基于jQuery的滑动/点击菜单 - 更灵活,可以实现更丰富的动画效果。
准备工作:模板文件结构
无论使用哪种方法,你都需要在模板文件中准备好HTML结构,通常是在网站的头部模板文件 head.htm 或 header.htm 中进行操作。

(图片来源网络,侵删)
假设你的栏目结构如下:
- 一级栏目 A
- 二级栏目 A1
- 二级栏目 A2
- 三级栏目 A2-1
- 三级栏目 A2-2
- 一级栏目 B
二级栏目 B1
- 一级栏目 C
纯CSS下拉菜单
这种方法的核心是利用CSS的 hover 伪类来控制子菜单的显示和隐藏。
第1步:修改模板文件,添加HTML结构
在 head.htm 中,找到你的导航区域,将默认的导航标签替换为以下结构:

(图片来源网络,侵删)
<!-- 顶部导航开始 -->
<div class="nav">
<ul id="topnav">
{dede:channel type='top' row='8'}
<li>
<a href="[field:typelink/]">[field:typename/]</a>
<!-- 检查是否有子栏目 -->
[field:sonlist]
<ul class="subnav">
<!-- 循环输出二级栏目 -->
{dede:son typeid='[field:id]'}
<li>
<a href="[field:typelink/]">[field:typename/]</a>
<!-- 检查二级栏目下是否有三级栏目 -->
[field:sonlist]
<ul class="sub-subnav">
{dede:son typeid='[field:id]'}
<li><a href="[field:typelink/]">[field:typename/]</a></li>
{/dede:son}
</ul>
{/field:sonlist}
</li>
{/dede:son}
</ul>
{/field:sonlist}
</li>
{/dede:channel}
<!-- 可以添加一个“首页”链接 -->
<li><a href='{dede:global.cfg_cmsurl/}/' class='nav-home'>首页</a></li>
</ul>
</div>
<!-- 顶部导航结束 -->
代码解析:
{dede:channel type='top' row='8'}: 调用顶级栏目(一级栏目)。[field:sonlist]: 这是一个自定义字段,但默认是不存在的。我们需要手动在DedeCMS的后台为其添加功能。- 如何添加
[field:sonlist]功能:- 打开
/include/taglib/channel.lib.php文件。 - 找到大约第92行左右的
$linktype = "<a href='".$typeinfos['typedir']."'>";这一行。 - 在这一行前面,添加如下代码:
// 判断是否有子栏目 $sonids = GetSonIds($typeid, 0, false); if($sonids != ''){ $GLOBALS['autoindex'] = 0; $sonlist = ''; $dsql->SetQuery("SELECT id,typename,typedir,isdefault,defaultname,ishidden,moresite,siteurl,sitepath FROM `dede_arctype` WHERE reid='$typeid' And ishidden<>1 order by sortrank asc"); $dsql->Execute('al'); while($row = $dsql->GetArray('al')) { $sonlist .= "<a href='".$row['typedir']."'>".$row['typename']."</a>\r\n"; } $fields['sonlist'] = $sonlist; }else{ $fields['sonlist'] = ''; } - 保存文件,这样
[field:sonlist]就会输出当前栏目下的所有二级栏目的链接。注意:上面的代码会直接输出链接,为了我们上面的HTML结构,需要做微调。 - 更简单的方法(推荐): 直接使用
{dede:son}标签嵌套,如上面的完整HTML代码所示,它更清晰,更符合逻辑,我们不需要修改channel.lib.php,直接使用{dede:son}即可。
- 打开
- 如何添加
第2步:添加CSS样式
在模板的CSS文件(如 style.css)中添加以下样式:
/* 导航容器样式 */
.nav {
width: 100%;
background-color: #333; /* 导航背景色 */
height: 40px;
line-height: 40px;
}
#topnav, #topnav ul {
list-style: none;
padding: 0;
margin: 0;
float: left; /* 导航居中布局需要调整 */
}
#topnav > li {
float: left;
position: relative;
margin-right: 1px;
}
#topnav > li > a {
display: block;
padding: 0 15px;
color: #fff;
text-decoration: none;
}
/* 鼠标悬停时,一级菜单背景变化 */
#topnav > li:hover > a {
background-color: #555;
}
/* 二级菜单样式 */
#topnav li ul.subnav {
position: absolute;
top: 40px; /* 与一级菜单高度相同 */
left: 0;
width: 180px;
background-color: #444;
display: none; /* 默认隐藏 */
z-index: 999;
}
/* 鼠标悬停在一级菜单上时,显示二级菜单 */
#topnav li:hover > ul.subnav {
display: block;
}
/* 三级菜单样式 */
#topnav li ul.subnav li {
position: relative;
width: 100%;
}
#topnav li ul.subnav li a {
display: block;
padding: 8px 15px;
color: #ccc;
border-bottom: 1px solid #555;
}
/* 鼠标悬停在二级菜单上时,显示三级菜单 */
#topnav li ul.subnav li:hover > ul.sub-subnav {
display: block;
}
#topnav li ul.subnav li ul.sub-subnav {
position: absolute;
top: 0;
left: 180px; /* 与二级菜单宽度相同 */
background-color: #444;
display: none; /* 默认隐藏 */
}
#topnav li ul.subnav li ul.sub-subnav li a {
border-bottom: none;
}
CSS解析:
position: absolute;: 将子菜单从正常的文档流中脱离,并相对于其最近的已定位祖先元素(这里是<li>)进行定位。top: 40px; left: 0;: 控制二级菜单相对于一级菜单的位置。display: none;: 默认隐藏子菜单。#topnav li:hover > ul.subnav { display: block; }: 这是核心的CSS选择器,当鼠标悬停在<li>元素上时,选择其直接子元素ul.subnav并将其display属性设置为block,从而实现显示。
基于jQuery的滑动/点击菜单
这种方法使用JavaScript来控制菜单的显示,可以实现更平滑的动画效果,并且可以解决iOS等设备上hover不生效的问题。

(图片来源网络,侵删)
第1步:修改模板文件,添加HTML结构
HTML结构可以和方法一完全一样,也可以简化一些,因为jQuery可以更灵活地处理。
<!-- 顶部导航开始 -->
<div class="nav">
<ul id="topnav">
{dede:channel type='top' row='8'}
<li class="menu-item">
<a href="[field:typelink/]">[field:typename/]</a>
<!-- 用一个容器来包裹子菜单 -->
<div class="sub-menu-container">
{dede:son typeid='[field:id]'}
<div class="sub-menu-item">
<a href="[field:typelink/]">[field:typename/]</a>
{dede:son typeid='[field:id]'}
<div class="sub-sub-menu">
<a href="[field:typelink/]">[field:typename/]</a>
</div>
{/dede:son}
</div>
{/dede:son}
</div>
</li>
{/dede:channel}
<li><a href='{dede:global.cfg_cmsurl/}/' class='nav-home'>首页</a></li>
</ul>
</div>
<!-- 顶部导航结束 -->
注意: 这里我调整了HTML结构,用 div 包裹子菜单,方便jQuery选择器操作,你可以根据自己的喜好调整。
第2步:引入jQuery库
在模板文件的<head>部分,确保引入了jQuery库,通常放在{dede:include filename='head.htm'/}之前。
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
第3步:添加CSS样式
CSS可以简化,不需要hover伪类。
/* 导航容器样式(同上) */
.nav { width: 100%; background-color: #333; height: 40px; line-height: 40px; }
#topnav, #topnav ul { list-style: none; padding: 0; margin: 0; float: left; }
#topnav > li { float: left; position: relative; margin-right: 1px; }
#topnav > li > a { display: block; padding: 0 15px; color: #fff; text-decoration: none; }
/* 子菜单容器 */
.sub-menu-container {
position: absolute;
top: 100%;
left: 0;
background-color: #444;
min-width: 180px;
display: none; /* 默认隐藏 */
z-index: 999;
}
/* 三级菜单 */
.sub-sub-menu {
position: absolute;
top: 0;
left: 100%;
background-color: #444;
display: none; /* 默认隐藏 */
}
.sub-menu-item {
position: relative;
}
第4步:添加jQuery脚本
在模板文件的底部,</body>标签之前,添加以下jQuery代码:
<script>
$(document).ready(function(){
// 鼠标悬停显示子菜单
$('.menu-item').hover(
function() { // 鼠标进入
$(this).find('.sub-menu-container').stop(true, true).slideDown(200); // 使用slideDown实现滑动效果
},
function() { // 鼠标离开
$(this).find('.sub-menu-container').stop(true, true).slideUp(200);
}
);
// 如果需要三级菜单,可以再嵌套一个hover事件
$('.sub-menu-item').hover(
function() {
$(this).find('.sub-sub-menu').stop(true, true).slideDown(200);
},
function() {
$(this).find('.sub-sub-menu').stop(true, true).slideUp(200);
}
);
});
</script>
jQuery解析:
$(document).ready(function(){...});: 确保DOM加载完成后再执行脚本。$('.menu-item').hover(...): 为所有带有.menu-item类的元素绑定鼠标悬停事件。function() { ... }: 鼠标进入时执行的函数,使用.slideDown(200)让子菜单在200毫秒内滑动显示。function() { ... }: 鼠标离开时执行的函数,使用.slideUp(200)让子菜单在200毫秒内滑动隐藏。stop(true, true): 这个方法可以停止正在进行的动画,防止鼠标快速移动时动画卡顿。
总结与建议
| 特性 | 方法一 (纯CSS) | 方法二 (jQuery) |
|---|---|---|
| 性能 | 高,无JavaScript开销 | 稍低,需要加载jQuery库并执行JS |
| 兼容性 | 现代浏览器支持良好,iOS设备hover有兼容问题 |
非常好,所有浏览器和设备都支持 |
| 实现难度 | 简单,只需HTML和CSS | 稍复杂,需要HTML、CSS和JS |
| 动画效果 | 只能显示/隐藏,无法做平滑动画 | 可以轻松实现滑动、淡入淡出等动画 |
| 代码量 | CSS可能较长 | HTML和CSS相对简洁,JS代码量小 |
我的建议:
- 对于大多数追求性能和简洁的网站,方法一(纯CSS)是首选,它足够强大,且不依赖任何外部库。
- 如果你的网站需要动画效果,或者希望在移动设备上有更好的交互体验,或者你的网站本身就已经大量使用了jQuery,那么方法二(jQuery)是更好的选择。
在实际操作中,请根据你网站的实际情况和栏目结构,对提供的代码进行微调。
