1. 推荐方法:使用DedeCMS自带的channel - 这是最标准、最灵活的方法,能自动获取网站栏目,并且能方便地控制样式。
  2. 备用方法:纯CSS/HTML实现 - 适用于栏目固定、不常变化的情况,代码更直接。

使用DedeCMS channel 标签(推荐)

这种方法的核心是利用DedeCMS的{dede:channel}标签来无限级地获取栏目数据,然后通过CSS来控制其显示为横向下拉菜单。

dede模板首页左侧横向三级菜单
(图片来源网络,侵删)

第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关键点:

dede模板首页左侧横向三级菜单
(图片来源网络,侵删)
  • display: flex; 是实现顶级菜单横向排列的现代方法,非常推荐。
  • position: relative;position: absolute; 是实现下拉菜单定位的核心,父级relative,子级absolute
  • hover 伪类是触发下拉效果的关键,当鼠标移到.topnav-item上时,它的子元素.subnav才会显示。

第3步:高级技巧(为当前栏目和父级栏目添加高亮)

为了让用户知道当前在哪个栏目下,我们可以用CSS高亮显示。

  1. 修改HTML:给需要高亮的li添加一个特定的类名,比如activecurrent

    <!-- 在顶级栏目循环中 -->
    {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中定义它。

  2. extend.func.php中添加函数

    dede模板首页左侧横向三级菜单
    (图片来源网络,侵删)
    // 判断当前栏目是否是顶级栏目或其父级栏目
    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函数。

  3. 在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 方法二 (纯HTML/CSS)
数据来源 动态从数据库获取,自动更新 手动编写,静态内容
维护性 ,后台添加/删除栏目,菜单自动更新 ,每次修改需手动编辑模板文件
灵活性 ,可以控制显示数量、类型等 ,结构固定
适用场景 绝大多数网站,特别是内容经常更新的 栏目非常少且固定的企业展示型网站

对于DedeCMS项目,强烈推荐使用方法一,它更符合CMS的设计理念,能让您的工作更高效。