3分钟解决Layui导航菜单多列显示难题:从纵向堆叠到横向扩展的实战方案
你是否还在为Layui导航菜单只能纵向堆叠而烦恼?当菜单项超过10个时,页面滚动条变得冗长;当子菜单层级过深时,用户需要反复点击展开;当界面宽度足够却只能单列显示时,宝贵的横向空间被白白浪费。本文将通过3种实战方案,教你如何利用Layui原生组件实现多列菜单,让导航体验从"不得不滑"升级为"一目了然"。
读完本文你将获得:
- 掌握
layui-menu-item-parent横向子菜单的核心配置 - 学会用CSS Grid实现自定义多列布局
- 理解菜单组件与
dropdown模块的联动机制 - 获取3套可直接复用的多列菜单代码模板
原生方案:利用parent类型实现二级横向扩展
Layui的基础菜单(menu)组件本身已内置横向扩展能力,通过layui-menu-item-parent类可实现二级菜单的横向展开。这种方案的优势是完全基于原生API,无需额外引入样式,兼容性最佳。
核心实现原理
基础菜单的层级结构定义在docs/menu/index.md中,通过设置type: 'parent'属性,可将子菜单从默认的纵向堆叠改为横向排列:
<li class="layui-menu-item-parent" lay-options="{type: 'parent'}">
<div class="layui-menu-body-title">
横向扩展菜单 <i class="layui-icon layui-icon-right"></i>
</div>
<div class="layui-panel layui-menu-body-panel">
<ul>
<!-- 横向排列的子菜单项 -->
<li><div class="layui-menu-body-title">选项1</div></li>
<li><div class="layui-menu-body-title">选项2</div></li>
<li><div class="layui-menu-body-title">选项3</div></li>
</ul>
</div>
</li>
完整示例代码
以下是一个包含横向子菜单的完整菜单结构,改编自docs/menu/examples/demo.md中的官方示例:
<div class="layui-panel" style="width: 260px; margin: 16px;">
<ul class="layui-menu" id="demo-menu">
<!-- 常规菜单项 -->
<li><div class="layui-menu-body-title">首页</div></li>
<li><div class="layui-menu-body-title">产品中心</div></li>
<!-- 横向多列子菜单 -->
<li class="layui-menu-item-parent" lay-options="{type: 'parent'}">
<div class="layui-menu-body-title">
服务支持 <i class="layui-icon layui-icon-right"></i>
</div>
<div class="layui-panel layui-menu-body-panel">
<ul style="display: flex; flex-wrap: wrap; width: 400px;">
<li style="width: 50%;"><div class="layui-menu-body-title">技术文档</div></li>
<li style="width: 50%;"><div class="layui-menu-body-title">API参考</div></li>
<li style="width: 50%;"><div class="layui-menu-body-title">常见问题</div></li>
<li style="width: 50%;"><div class="layui-menu-body-title">联系客服</div></li>
</ul>
</div>
</li>
<li class="layui-menu-item-divider"></li>
<li><div class="layui-menu-body-title">关于我们</div></li>
</ul>
</div>
<script>
layui.use(function(){
var dropdown = layui.dropdown;
dropdown.on('click(demo-menu)', function(options){
console.log('点击了:', options);
});
});
</script>
实现效果与局限
原生方案通过flex-wrap: wrap和固定宽度实现了2列布局,但存在明显局限:
- 仅支持二级菜单横向扩展,三级菜单仍为纵向堆叠
- 菜单项宽度需要手动计算,无法自适应容器宽度
- 不支持动态调整列数,响应式能力有限
进阶方案:CSS Grid实现自定义多列布局
当原生方案无法满足需求时,我们可以通过CSS Grid布局对菜单结构进行改造。这种方案的优势是灵活性极高,支持任意列数配置,且能自动适应容器宽度。
核心CSS改造
在页面样式中添加以下自定义CSS,覆盖Layui默认的菜单样式:
/* 多列菜单容器 */
.layui-menu-multi-column {
display: grid;
grid-template-columns: repeat(3, 1fr); /* 3列布局 */
gap: 8px 16px;
padding: 10px;
}
/* 菜单项样式调整 */
.layui-menu-multi-column li {
width: 100%;
box-sizing: border-box;
}
/* 响应式调整:小屏幕变为2列 */
@media (max-width: 768px) {
.layui-menu-multi-column {
grid-template-columns: repeat(2, 1fr); /* 2列布局 */
}
}
菜单结构改造
修改菜单HTML结构,将需要多列显示的子菜单容器添加layui-menu-multi-column类:
<li class="layui-menu-item-parent" lay-options="{type: 'parent'}">
<div class="layui-menu-body-title">
产品分类 <i class="layui-icon layui-icon-right"></i>
</div>
<div class="layui-panel layui-menu-body-panel">
<ul class="layui-menu-multi-column">
<li><div class="layui-menu-body-title">手机数码</div></li>
<li><div class="layui-menu-body-title">电脑办公</div></li>
<li><div class="layui-menu-body-title">家用电器</div></li>
<li><div class="layui-menu-body-title">家居生活</div></li>
<li><div class="layui-menu-body-title">服饰鞋包</div></li>
<li><div class="layui-menu-body-title">美妆个护</div></li>
</ul>
</div>
</li>
实现效果与优势
这种方案实现了以下关键特性:
- 支持任意列数配置(通过
grid-template-columns) - 自动平分列宽,无需手动计算百分比
- 响应式布局,在小屏幕上自动调整列数
- 保持与Layui原生样式的兼容性
高级方案:结合dropdown模块实现动态多列
对于需要动态加载菜单项或更复杂交互的场景,我们可以结合Layui的dropdown模块(下拉菜单)来实现多列显示。这种方案的优势是支持异步加载数据,且交互体验更丰富。
动态渲染实现
<button id="multi-column-dropdown" class="layui-btn">
动态多列菜单 <i class="layui-icon layui-icon-down"></i>
</button>
<script>
layui.use(['dropdown', 'util'], function(){
var dropdown = layui.dropdown;
var util = layui.util;
// 模拟异步加载菜单数据
function loadMenuData(callback) {
setTimeout(function(){
callback([
{title: '选项1', id: 1},
{title: '选项2', id: 2},
{title: '选项3', id: 3},
{title: '选项4', id: 4},
{title: '选项5', id: 5},
{title: '选项6', id: 6}
]);
}, 300);
}
// 渲染多列菜单
dropdown.render({
elem: '#multi-column-dropdown',
id: 'multi-column-dropdown',
show: function(options){
var that = this;
var content = document.createElement('div');
content.className = 'layui-menu-multi-column';
loadMenuData(function(data){
var html = '<ul style="display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px;">';
data.forEach(function(item){
html += `<li><div class="layui-menu-body-title">${item.title}</div></li>`;
});
html += '</ul>';
content.innerHTML = html;
// 将内容添加到下拉菜单
that.content(content);
});
return false; // 阻止默认显示
},
click: function(obj){
console.log('点击了:', obj);
layui.layer.msg('选中: ' + obj.title);
}
});
});
</script>
核心技术点解析
-
动态内容加载:通过
show回调函数实现异步加载菜单数据,适合从后端API获取动态菜单 -
灵活布局控制:利用
grid-template-columns: repeat(3, 1fr)实现均等3列布局,如需不等宽可改为1fr 2fr 1fr -
事件处理:保持与Layui
dropdown模块的事件机制兼容,通过click回调处理选中逻辑
三种方案的对比与选择指南
| 方案类型 | 实现难度 | 兼容性 | 灵活性 | 适用场景 |
|---|---|---|---|---|
| 原生parent类型 | ★☆☆☆☆ | 最佳 | 低 | 简单二级横向菜单 |
| CSS Grid改造 | ★★☆☆☆ | 良好(IE11+) | 中 | 固定列数多列菜单 |
| dropdown动态渲染 | ★★★☆☆ | 良好 | 高 | 动态数据/复杂交互 |
决策流程图
graph TD
A[选择多列菜单方案] --> B{是否需要动态数据?};
B -- 是 --> C[使用dropdown动态渲染];
B -- 否 --> D{是否需要响应式?};
D -- 是 --> E[CSS Grid改造];
D -- 否 --> F[原生parent类型];
E --> G[配置grid-template-columns];
F --> H[设置layui-menu-item-parent];
避坑指南与最佳实践
常见问题解决方案
-
样式冲突:自定义CSS可能与Layui默认样式冲突,建议使用特定类名隔离样式,如
.my-menu .layui-menu-item -
层级显示异常:如子菜单被其他元素遮挡,需调整
z-index属性:.layui-menu-body-panel { z-index: 1005; /* 确保高于其他元素 */ } -
动态加载闪烁:使用
dropdown动态加载时,可添加加载动画:<div class="layui-anim layui-anim-rotate layui-icon layui-icon-loading" style="font-size: 24px;"></div>
性能优化建议
- 避免过深的菜单层级(建议不超过3级)
- 多列菜单项数量控制在20个以内
- 动态菜单使用节流加载(throttle)
- 复杂菜单考虑使用虚拟滚动
总结与扩展学习
本文介绍的三种方案覆盖了从简单到复杂的多列菜单需求,均基于Layui原生组件实现,保证了与框架的兼容性。通过这些方案,我们可以解决导航菜单在空间利用和用户体验上的常见痛点。
扩展学习资源
- 官方菜单组件文档:docs/menu/index.md
- dropdown模块API:docs/dropdown/index.md
- Layui布局系统:docs/layout/index.md
建议收藏本文,并根据实际项目需求选择合适的实现方案。如果您有更好的多列菜单实现方式,欢迎在评论区分享您的经验!
本文示例代码已同步至项目示例目录:examples/menu-multi-column.html(假设路径,实际请根据项目结构调整)
Kimi-K2.5Kimi K2.5 是一款开源的原生多模态智能体模型,它在 Kimi-K2-Base 的基础上,通过对约 15 万亿混合视觉和文本 tokens 进行持续预训练构建而成。该模型将视觉与语言理解、高级智能体能力、即时模式与思考模式,以及对话式与智能体范式无缝融合。Python00
GLM-4.7-FlashGLM-4.7-Flash 是一款 30B-A3B MoE 模型。作为 30B 级别中的佼佼者,GLM-4.7-Flash 为追求性能与效率平衡的轻量化部署提供了全新选择。Jinja00
VLOOKVLOOK™ 是优雅好用的 Typora/Markdown 主题包和增强插件。 VLOOK™ is an elegant and practical THEME PACKAGE × ENHANCEMENT PLUGIN for Typora/Markdown.Less00
PaddleOCR-VL-1.5PaddleOCR-VL-1.5 是 PaddleOCR-VL 的新一代进阶模型,在 OmniDocBench v1.5 上实现了 94.5% 的全新 state-of-the-art 准确率。 为了严格评估模型在真实物理畸变下的鲁棒性——包括扫描伪影、倾斜、扭曲、屏幕拍摄和光照变化——我们提出了 Real5-OmniDocBench 基准测试集。实验结果表明,该增强模型在新构建的基准测试集上达到了 SOTA 性能。此外,我们通过整合印章识别和文本检测识别(text spotting)任务扩展了模型的能力,同时保持 0.9B 的超紧凑 VLM 规模,具备高效率特性。Python00
KuiklyUI基于KMP技术的高性能、全平台开发框架,具备统一代码库、极致易用性和动态灵活性。 Provide a high-performance, full-platform development framework with unified codebase, ultimate ease of use, and dynamic flexibility. 注意:本仓库为Github仓库镜像,PR或Issue请移步至Github发起,感谢支持!Kotlin07
compass-metrics-modelMetrics model project for the OSS CompassPython00