纯CSS实现下拉菜单(推荐,最常用)
这是最标准、最简洁的方法,通过CSS的 hover 属性来实现鼠标悬停时显示子菜单,它不需要JavaScript,加载速度快,兼容性好。

核心思路:
- HTML结构:导航菜单的HTML结构必须是嵌套的,即父级菜单项包含子菜单项。
- CSS样式:
- 默认状态下,隐藏子菜单 (
display: none;)。 - 当鼠标悬停在父级菜单项上时 (
hover),显示子菜单 (display: block;)。 - 使用CSS定位(
position: absolute)来将子菜单精确地放置在父级菜单的下方。
- 默认状态下,隐藏子菜单 (
详细操作步骤:
第1步:确保导航栏的HTML结构正确
这是最关键的一步,织梦的 {dede:channel} 标签默认生成的是扁平结构,我们需要修改模板文件,让它生成带有嵌套关系的HTML代码。
-
登录织梦后台,进入 【模板】-> 【模板管理】**。
-
找到你当前使用的模板,点击 【默认模板管理】。
-
在列表中找到
head.htm或header.htm文件(通常是网站头部文件),点击 【修改】。
(图片来源网络,侵删) -
找到调用导航栏的代码,它通常是这样的:
<div id="nav"> <ul> {dede:channel type='top' row='8'} <li><a href='[field:typeurl/]'>[field:typename/]</a></li> {/dede:channel} </ul> </div> -
修改代码,将其改为支持二级菜单的嵌套结构,我们需要使用
{dede:channel}的son或sonlevel属性来获取子栏目。<div id="nav"> <ul> {dede:channel type='top' row='8'} <li> <a href='[field:typeurl/]'>[field:typename/]</a> <!-- 检查是否有子栏目,如果有则显示 --> [field:son] <div class="subnav"> <ul> {dede:son} <li><a href='[field:typeurl/]'>[field:typename/]</a></li> {/dede:son} </ul> </div> [/field:son] </li> {/dede:channel} </ul> </div>代码解释:
[field:son]...[/field:son]:这是一个条件判断,只有当前栏目有子栏目时,才会执行其中的内容。{dede:son}:这个标签会循环输出当前顶级栏目下的所有直接子栏目(二级栏目)。
重要提示:如果你的菜单有三级或更多层级,CSS会变得非常复杂,建议先实现二级菜单,三级菜单通常需要结合JavaScript来实现更友好的交互。
第2步:编写CSS样式
-
同样在模板管理中,找到并修改你的CSS文件,通常是
/templets/你的模板/style.css或/templets/你的模板/css.css。 -
在CSS文件末尾添加以下样式:
/* 1. 导航栏主菜单样式 */ #nav { background-color: #333; /* 导航背景色 */ height: 40px; line-height: 40px; } #nav ul { list-style: none; /* 去掉列表前的点 */ margin: 0; padding: 0; display: flex; /* 使用flex布局让菜单项水平排列 */ } #nav li { position: relative; /* 关键:为子菜单定位提供参考 */ padding: 0 15px; } #nav a { color: #fff; text-decoration: none; display: block; } #nav a:hover { color: #ff0; /* 鼠标悬停时的文字颜色 */ } /* 2. 子菜单样式 - 这是核心 */ #nav li .subnav { /* 关键:隐藏子菜单 */ display: none; /* 关键:将子菜单从文档流中脱离,以便精确定位 */ position: absolute; /* 关键:定位在父级li的左下方 */ left: 0; top: 40px; /* 导航栏的高度 */ /* 子菜单背景和边框 */ background-color: #444; border: 1px solid #666; /* 防止子菜单项撑开父级li的宽度 */ width: 150px; z-index: 1000; /* 确保子菜单显示在内容之上 */ } /* 3. 子菜单列表样式 */ #nav li .subnav ul { list-style: none; margin: 0; padding: 0; } #nav li .subnav li { width: 100%; padding: 0; } #nav li .subnav a { padding: 8px 15px; border-bottom: 1px solid #555; } /* 4. 鼠标悬停时显示子菜单 - 这是魔术发生的地方 */ #nav li:hover .subnav { display: block; }
第3步:清空缓存并刷新网站
- 在织梦后台,点击右上角的 【生成】-> 【一键更新所有】**,或者至少更新一下首页和HTML页面。
- 清除浏览器缓存,然后刷新你的网站首页,查看效果。
当你将鼠标移动到有子栏目的菜单项上时,应该就能看到下拉菜单了。
使用JavaScript实现(更灵活)
纯CSS方法在移动端(触摸设备)上无法触发 hover 事件,如果你的网站需要适配移动端,或者需要更复杂的交互效果(如点击展开),可以使用JavaScript。
核心思路:
- HTML结构:和方法一一样,先确保HTML是嵌套结构。
- JavaScript:
- 获取所有带有子菜单的父级菜单项(
li元素)。 - 为它们添加鼠标悬停(
mouseover)或点击(click)事件监听器。 - 在事件触发时,通过修改子菜单的
style.display属性来显示或隐藏它。
- 获取所有带有子菜单的父级菜单项(
操作步骤:
第1步:HTML结构(同方法一)
确保你的 header.htm 文件中的导航栏HTML是嵌套结构,参考方法第一步。
第2步:编写CSS和JavaScript
-
CSS:基本样式和方法一一样,但需要去掉
#nav li:hover .subnav这条规则,因为显示/隐藏将由JS控制。/* ... 其他样式保持不变 ... */ /* 删除 #nav li:hover .subnav 这一条 */ /* 初始状态下,子菜单仍然是隐藏的 */ #nav li .subnav { display: none; position: absolute; left: 0; top: 40px; background-color: #444; border: 1px solid #666; width: 150px; z-index: 1000; } /* ... 其他样式保持不变 ... */ -
JavaScript:
- 在你的
head.htm或footer.htm文件中,</body>标签之前添加以下JS代码。
<script> document.addEventListener('DOMContentLoaded', function() { // 获取所有包含子菜单的父级 li 元素 const parentItems = document.querySelectorAll('#nav > ul > li:has(.subnav)'); parentItems.forEach(function(item) { // 鼠标悬停事件 item.addEventListener('mouseover', function() { // 找到当前li下的子菜单并显示 const subnav = this.querySelector('.subnav'); if (subnav) { subnav.style.display = 'block'; } }); // 鼠标离开事件 item.addEventListener('mouseout', function() { const subnav = this.querySelector('.subnav'); if (subnav) { subnav.style.display = 'none'; } }); }); }); </script>代码解释:
DOMContentLoaded:确保DOM(页面结构)加载完成后再执行JS代码。document.querySelectorAll('#nav > ul > li:has(.subnav)'):这是一个强大的选择器,它会选中#nav下的ul下的所有包含.subnav子元素的li,如果你的浏览器不支持has()选择器,可以用更兼容的方式:const allLi = document.querySelectorAll('#nav > ul > li'); const parentItems = Array.from(allLi).filter(li => li.querySelector('.subnav'));addEventListener:为每个符合条件的li添加事件监听。mouseover和mouseout:模拟了CSS的hover效果。
- 在你的
第3步:清空缓存并刷新网站
同样,在后台生成页面,并清除浏览器缓存查看效果。
使用现成的织梦导航插件
如果你对代码不太熟悉,或者想要更丰富的功能(如响应式、动画效果等),可以直接使用第三方开发的织梦导航菜单插件。
- 搜索插件:在织梦官方论坛、DedeCMS吧、或者其他CMS资源网站搜索“织梦 导航菜单插件”、“织梦 下拉菜单”等关键词。
- 下载安装:找到合适的插件,下载并按照插件的说明文档进行安装和配置。
- 调用标签:安装成功后,插件通常会提供一套新的调用标签,你只需要在模板中用新的标签替换掉旧的
{dede:channel}即可。
优点:
- 开箱即用,配置简单。
- 通常自带响应式设计,移动端友好。
- 功能更丰富,可能有动画、多级菜单等。
缺点:
- 增加了网站的插件数量,可能影响性能。
- 依赖第三方,后续更新和维护可能不及时。
总结与建议
| 方法 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| 纯CSS | 代码简洁、性能好、标准、SEO友好 | 移动端不兼容(无法触发hover)、多级菜单实现复杂 | 首选方案,适用于大多数PC端网站,且菜单层级不超过二级。 |
| JavaScript | 兼容性好(可适配移动端)、交互灵活 | 需要额外引入JS代码,代码量稍多 | 需要移动端适配,或需要更复杂交互(如点击展开)的网站。 |
| 插件 | 功能强大、配置简单、响应式 | 增加依赖、可能影响性能、定制性差 | 对代码不熟悉,追求快速实现,且需要高级功能的用户。 |
对于绝大多数用户,强烈推荐从方法一开始尝试,它能帮助你理解织梦菜单的底层结构,并且是最高效、最标准的实现方式,如果遇到移动端兼容问题,再考虑升级到方法二。
