- 推荐方法:使用DedeCMS自带的
channel - 这是最标准、最灵活的方法,能自动获取网站栏目,并且能方便地控制样式。 - 备用方法:纯CSS/HTML实现 - 适用于栏目固定、不常变化的情况,代码更直接。
使用DedeCMS channel 标签(推荐)
这种方法的核心是利用DedeCMS的{dede:channel}标签来无限级地获取栏目数据,然后通过CSS来控制其显示为横向下拉菜单。

(图片来源网络,侵删)
第1步:准备HTML结构
在您的首页模板文件(通常是 index.htm)中,找到您希望放置菜单的位置,加入以下HTML代码,这里我们使用一个常见的列表结构。
<div id="mainNav">
<ul class="nav">
<!-- 顶级菜单开始 -->
<li class="topnav-item">
<a href="{dede:global.cfg_cmsurl/}/">首页</a>
</li>
{dede:channel type='top' row='8'}
<li class="topnav-item">
<a href="[field:typelink/]">[field:typename/]</a>
<!-- 二级菜单开始 -->
{dede:son typeid='[field:id/]'}
<ul class="subnav">
<li>
<a href="[field:typelink/]">[field:typename/]</a>
<!-- 三级菜单开始 -->
{dede:son typeid='[field:id/]'}
<ul class="subnav-sub">
<li><a href="[field:typelink/]">[field:typename/]</a></li>
{/dede:son}
<!-- 三级菜单结束 -->
</li>
</ul>
{/dede:son}
<!-- 二级菜单结束 -->
</li>
{/dede:channel}
<!-- 顶级菜单结束 -->
</ul>
</div>
代码解释:
{dede:channel type='top' row='8'}: 获取顶级栏目(父类ID为0的栏目),最多显示8个。[field:typelink/]是栏目链接,[field:typename/]是栏目名称。{dede:son typeid='[field:id/]'}: 这是关键!它获取当前顶级栏目的所有直接子栏目(即二级栏目)。typeid属性动态地绑定了顶级栏目的ID。- 内层的
{dede:son}同理,它获取二级栏目的子栏目(即三级栏目)。 class="topnav-item",class="subnav",class="subnav-sub"是我们用来添加CSS样式的类名。
第2步:编写CSS样式
在您的模板CSS文件(/templets/您的模板名/style/css.css)中,添加以下CSS代码来控制菜单的样式和下拉效果。
/* 导航菜单容器 */
#mainNav {
width: 100%; /* 或固定宽度 */
background-color: #333; /* 背景色 */
height: 40px; /* 高度 */
}
/* 顶级菜单列表 */
.nav {
list-style: none; /* 去掉列表点 */
margin: 0;
padding: 0;
display: flex; /* 使用Flex布局实现横向排列 */
justify-content: flex-start; /* 靠左对齐 */
}
/* 顶级菜单项 */
.topnav-item {
position: relative; /* 关键:为下拉菜单定位提供参考 */
}
/* 顶级菜单链接 */
.topnav-item a {
display: block; /* 让a标签撑满li */
color: #fff;
text-decoration: none;
line-height: 40px; /* 行高等于高度,实现垂直居中 */
padding: 0 20px;
}
/* 鼠标悬停在顶级菜单项上时的样式 */
.topnav-item:hover a {
background-color: #555;
}
/* 二级菜单容器(默认隐藏) */
.subnav {
position: absolute; /* 绝对定位,相对于.topnav-item */
top: 100%; /* 位于顶级菜单项的下方 */
left: 0;
background-color: #444;
list-style: none;
margin: 0;
padding: 0;
width: 180px; /* 二级菜单宽度 */
display: none; /* 默认隐藏 */
z-index: 1000; /* 确保菜单在上层 */
}
/* 鼠标悬停在顶级菜单项上时,显示二级菜单 */
.topnav-item:hover .subnav {
display: block;
}
/* 二级菜单项 */
.subnav li {
width: 100%;
}
/* 二级菜单链接 */
.subnav li a {
display: block;
color: #fff;
text-decoration: none;
padding: 10px 15px;
border-bottom: 1px solid #555;
}
/* 鼠标悬停在二级菜单项上时的样式 */
.subnav li:hover a {
background-color: #666;
}
/* 三级菜单容器(默认隐藏) */
.subnav-sub {
position: absolute; /* 绝对定位,相对于其父级.subnav li */
left: 100%; /* 位于二级菜单项的右侧 */
top: 0;
background-color: #555;
list-style: none;
margin: 0;
padding: 0;
width: 160px; /* 三级菜单宽度 */
display: none; /* 默认隐藏 */
}
/* 鼠标悬停在二级菜单项上时,显示三级菜单 */
/* 注意:这里的选择器要能精准定位到包含三级菜单的二级菜单项 */
.subnav li:hover .subnav-sub {
display: block;
}
/* 三级菜单链接样式(可复用二级菜单的样式,或单独定义) */
.subnav-sub li a {
display: block;
color: #fff;
text-decoration: none;
padding: 10px 15px;
border-bottom: 1px solid #666;
}
.subnav-sub li:hover a {
background-color: #777;
}
CSS关键点:

(图片来源网络,侵删)
display: flex;是实现顶级菜单横向排列的现代方法,非常推荐。position: relative;和position: absolute;是实现下拉菜单定位的核心,父级relative,子级absolute。hover伪类是触发下拉效果的关键,当鼠标移到.topnav-item上时,它的子元素.subnav才会显示。
第3步:高级技巧(为当前栏目和父级栏目添加高亮)
为了让用户知道当前在哪个栏目下,我们可以用CSS高亮显示。
-
修改HTML:给需要高亮的
li添加一个特定的类名,比如active或current。<!-- 在顶级栏目循环中 --> {dede:channel type='top' row='8'} <li class="topnav-item [field:typename function="is_current(@me)"/]"> ... </li> {/dede:channel}注意:
function="is_current(@me)"是一个自定义函数,您需要在/include/extend.func.php中定义它。 -
在
extend.func.php中添加函数:
(图片来源网络,侵删)// 判断当前栏目是否是顶级栏目或其父级栏目 function is_current($typename) { global $tid; $arr = GetSonIds($tid); // 获取当前栏目及其所有子栏目的ID $topids = GetTopids($tid); // 获取当前栏目的顶级栏目ID // 如果当前栏目ID在顶级栏目列表中,或者当前栏目是顶级栏目 $dsql = new DedeSql(false); $dsql->SetQuery("SELECT id FROM `dede_arctype` WHERE typename='$typename' AND reid=0"); $dsql->Execute('t'); if ($row = $dsql->GetArray('t')) { if ($row['id'] == $topids) { return ' active'; } } return ''; }上面的函数可能有点复杂,一个更简单的方法是在首页模板里直接判断当前顶级栏目ID。
更简单的高亮方法:
在首页模板的顶级栏目循环前,先获取当前顶级栏目ID。
{dede:gettopid typeid='0' function='getTopid(@me)'} {dede:channel type='top' row='8'} <li class="topnav-item [field:id function="(@me == $GLOBALS['topid']) ? 'active' : '' "/]"> <a href="[field:typelink/]">[field:typename/]</a> ... </li> {/dede:channel}然后在
extend.func.php里写getTopid函数。 -
在CSS中添加高亮样式:
.topnav-item.active a { background-color: #007bff; /* 高亮颜色,比如蓝色 */ }
纯CSS/HTML实现(备用)
如果您只有固定的几个栏目,不常变动,可以直接手写HTML。
第1步:HTML结构
<div id="mainNav">
<ul class="nav">
<li class="topnav-item"><a href="/">首页</a></li>
<li class="topnav-item">
<a href="#">产品服务</a>
<ul class="subnav">
<li>
<a href="#">软件开发</a>
<ul class="subnav-sub">
<li><a href="#">Web开发</a></li>
<li><a href="#">移动App</a></li>
<li><a href="#">小程序</a></li>
</ul>
</li>
<li>
<a href="#">UI设计</a>
<ul class="subnav-sub">
<li><a href="#">网站设计</a></li>
<li><a href="#">APP界面</a></li>
</ul>
</li>
</ul>
</li>
<li class="topnav-item">
<a href="#">关于我们</a>
<ul class="subnav">
<li><a href="#">公司简介</a></li>
<li><a href="#">发展历程</a></li>
<li><a href="#">联系我们</a></li>
</ul>
</li>
<!-- 更多顶级菜单... -->
</ul>
</div>
第2步:CSS样式
CSS样式与方法一完全相同,直接复制即可,这种方法的好处是结构清晰,但缺点是每次在后台添加新栏目,都需要手动修改模板文件,不利于维护。
| 特性 | 方法一 (DedeCMS channel
| |
|---|---|---|
| 数据来源 | 动态从数据库获取,自动更新 | 手动编写,静态内容 |
| 维护性 | 高,后台添加/删除栏目,菜单自动更新 | 低,每次修改需手动编辑模板文件 |
| 灵活性 | 高,可以控制显示数量、类型等 | 低,结构固定 |
| 适用场景 | 绝大多数网站,特别是内容经常更新的 | 栏目非常少且固定的企业展示型网站 |
对于DedeCMS项目,强烈推荐使用方法一,它更符合CMS的设计理念,能让您的工作更高效。
