ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

layui数据表格自动换行全攻略:从CSS覆盖到性能避坑

layui数据表格自动换行全攻略:从CSS覆盖到性能避坑 做后台管理系统这些年被layui数据表格整得最无语的一次是业务部门跑过来说退款原因列的字全被省略号截断了每次核对订单都得点开详情看原因效率太低了。当时第一反应是加宽列结果调宽之后旁边几列被挤得没法看这才意识到layui数据表格自动换行不是加个列宽就能解决的事得从它默认的截断机制入手。这篇文章我就把layui数据表格自动换行的解决办法一次性说清楚包括CSS覆盖方案、列级style配置、固定列和表头这种特殊位置的处理、以及换行后行高和性能会踩的坑。适合正在做layui后台项目、被表格文案截断问题搞得头疼的前端朋友。1. 先搞清楚layui表格为什么默认要截断而不是换行1.1 省略号的真正来源.layui-table-cell的nowrap组合layui的table模块里每个单元格并不是直接用td来显示文本而是td内嵌套了一个叫.layui-table-cell的div真正控制文本展示的是这个div而不是td本身。以常用的layui 2.x版本为例它的默认样式大致是这样.layui-table-cell { height: 28px; line-height: 28px; padding: 0 15px; position: relative; box-sizing: border-box; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }这四行是核心white-space: nowrap表示不换行overflow: hidden把超出部分藏起来text-overflow: ellipsis再把藏起来的边界显示成省略号。三层一配合长文本看起来就是内容…。很多人一上来直接加word-break: break-all发现根本不生效原因就在这里——white-space: nowrap还压着场人家字面意思就是不许换行你告诉浏览器单词可以折断有什么用必须先解除nowrap的限制让文本有换行的机会。1.2 table-layout: fixed让列宽固定内容再多也顶不开列另一个容易被忽略的机制是layui表格默认使用了table-layout: fixed。这个声明表示表格的列宽完全由table或col的宽度决定单元格内容长不长、短不短都不参与列宽计算。它的好处是表头拖动列宽、异步渲染能精确计算坏处也很明显内容再长也不可能把列撑开唯一的出路就是在固定宽度内被截断或换行。所以想靠内容自己把列顶宽来展示完整文本此路不通。这也是为什么很多人在论坛里问为什么我的列宽设了minWidth还是被截断——因为table-layout: fixed下列宽分配规则优先于内容尺寸单元格里的文本只能在给定的宽度里想办法。1.3 动手之前先定一个原则全局改还是局部改开始写CSS之前先判断一下需求范围。如果整个系统所有表格都希望完整展示内容比如内部管理系统、报表系统这种以信息完整性为先的可以直接上全局CSS覆盖。如果只是某个业务列需要展示长文本比如退款原因、审核备注、地址明细那就用列级style或templet局部处理这样不容易误伤其他表格也方便后面针对特殊列微调。我个人在项目里的做法是全局兜底 列级特例组合默认允许所有单元格自动换行但给操作列、状态列、标签列这类不适合换行的列单独加一个class保持原来的单行截断。这种组合的好处是业务新增列时不用每次想着配样式长文本自动能换行特殊列只要记得加class就行。2. 两个最常用的换行方案全局CSS覆盖与列级style2.1 全局CSS覆盖三行样式搞定90%场景如果确定要全局开启自动换行最直接的办法就是覆盖.layui-table-cell的默认样式。我在实际项目里用的基础版是这样.layui-table-cell { height: auto !important; min-height: 28px; line-height: 20px; white-space: normal; word-break: break-all; overflow: visible; }逐行说下为什么这样写height: auto !important让单元格高度跟随内容撑开这是换行的前提。加!important是为了压过layui自带的28px固定高度如果你的项目没有其他样式冲突不加也可以。min-height: 28px保留原来单行时的视觉高度避免只有一行文本时表格看起来变矮变挤。line-height: 20px原来28px行高配单行没问题一旦换行成两行、三行28px的行高会让多行文本间距过大。改成20px视觉上更紧凑也更接近普通表格行高的阅读体验。white-space: normal这是换行开关必须从nowrap改成normal。word-break: break-all让连续的长串字符比如URL、订单号、英文串也能在单元格边缘断开换行而不是整体溢出或撑破布局。overflow: visible解除内容被裁掉的限制。这里要注意如果你只改了white-space没改overflow换行后的文本如果还超出高度依然会被隐藏所以visible也很重要。写完这三行后刷新页面表格里所有长文本都会自动换行不再出现省略号。这套CSS我用了很多项目覆盖了90%以上的常见场景。2.2 列级style不动全局只改需要的列如果不想全局开闸layui在表格列配置里提供了一个style属性可以直接给td加内联样式。比如这样table.render({ elem: #table, cols: [[ { field: orderNo, title: 订单号, width: 160 }, { field: reason, title: 退款原因, minWidth: 200, style: white-space: normal; word-break: break-all; }, { field: remark, title: 备注, templet: function (d) { return div classremark-cell d.remark /div; }} ]] });这里有一个特别容易踩的细节style属性作用在td上而真正装文本的.layui-table-cell是td的子元素。你只给td加white-space: normal子元素上如果还有white-space: nowrap照样不换行。因为CSS的继承规则里white-space是可继承属性但layui的cell自带样式优先级更高内联的td样式不一定能压过它。所以列级style想完全生效还要配合一个CSS选择器td[style*white-space: normal] .layui-table-cell { height: auto; min-height: 28px; line-height: 20px; overflow: visible; }如果你不喜欢用属性选择器更稳妥的方式是在列配置里加className然后在CSS里通过类名精准控制{ field: reason, title: 退款原因, className: col-wrap }.col-wrap .layui-table-cell { height: auto; min-height: 28px; line-height: 20px; white-space: normal; word-break: break-all; overflow: visible; }这样写逻辑更清晰也容易维护。2.3 两种方案怎么选直接看这张对比维度全局CSS覆盖列级style/className控制改动量一处CSS搞定所有表格每个表格要单独配置列影响范围全部layui表格只影响指定列维护成本低新列自动生效高容易漏配适合场景内部系统、报表系统面向用户、表格样式多样风险点状态列、操作列可能被误伤列多了容易看漏要挨个检查我的建议是新项目或者整体以信息展示为主的系统直接上全局覆盖省心。老项目或者表格类型特别多、固定列按钮密集的系统用列级方案更安全。两种方案也不是互斥的完全可以混用下面第五部分会给出我现在的标准组合模板。3. 固定列、表头和合计行的换行这三个位置最容易翻车3.1 固定列换行总是漏掉因为它是独立渲染的表格用了fixed: left或fixed: right的列layui会复制一份表格放到专门的.layui-table-fixed层里。这个层是独立渲染的和主体的.layui-table并排显示。所以经常出现一种怪象中间列都换行成功了左边固定列还在截断省略号——因为你的全局CSS虽然写了.layui-table-cell但固定列里的单元格也类名相同理论上是能命中的。为什么有时候固定列不生效实测下来主要是版本差异和样式优先级问题。稳妥起见补一组针对固定层的样式.layui-table-fixed .layui-table-cell { height: auto !important; min-height: 28px; line-height: 20px; white-space: normal; word-break: break-all; overflow: visible; }另一个实际经验固定列如果放的是操作按钮比如编辑、删除、审核按钮组列宽本来就留得窄让它换行反而会把按钮挤成竖排非常难看。所以固定列不要无脑全局换行建议只对固定列里确实需要展示长文本的列加className其他按钮列继续保持单行。3.2 表头title太长也想换行先想清楚要不要表头title实际上也在.layui-table-cell里默认同样受nowrap约束。要让它换行可以这样处理.layui-table th .layui-table-cell { height: auto !important; white-space: normal; word-break: break-all; line-height: 20px; overflow: visible; }但这里有一个连锁反应表头换行后高度增加如果你给表格配置了固定height表格总高度不变的情况下表头变高会压缩表格可视内容区的高度表格看起来会比原来矮一截。所以要不要让表头换行得先想清楚布局。我的习惯是表头尽量控制在10个字以内实在写不下就精炼措辞把完整说明放到title属性里鼠标悬停还能看到提示。这样既保证表头清爽又兼顾信息完整比直接让表头换行体验更好。如果你确实需要长表头换行记得把外层容器或表格高度改成auto别用固定值。3.3 合计行totalRow的长文本最容易在验收时被当场抓包开过totalRow: true的朋友应该遇到过合计行里的文本一样会被截断。合计行有自己的样式容器类名一般落在.layui-table-total下。如果合计行里放的是合计1234元这种短文本不处理也没事但有些系统会在合计行放计算说明或者汇总备注文本一长就露馅。补一段针对性样式.layui-table-total .layui-table-cell { height: auto !important; min-height: 28px; line-height: 20px; white-space: normal; word-break: break-all; overflow: visible; }这个位置容易漏的原因在于验收的人会先看正文列有没有换行合计行是第二眼才会注意到的地方。建议改完全局样式后把正文、表头、合计、固定列全过一遍再提测。4. 换行之后麻烦才开始行高、对齐与性能问题4.1 行高错位一列换两行、一列换三行单元格对不齐开启换行后第一个冒出来的新问题就是行高不一致。比如订单号列一行显示完退款原因列内容长换了两行收货地址列更长换了三行。虽然tr的高度会按最高单元格撑开但其他列单元格的文本默认是顶部对齐的结果就是行内上部有字、下部留白视觉上参差不齐非常影响阅读。解决办法有两个思路。一是全局统一文本的行高和padding把单行、多行的视觉差距降到最低.layui-table-cell { line-height: 20px; padding-top: 6px; padding-bottom: 6px; }这样即使各列行数不同每行的文本间距是一致的看起来不会太乱。二是针对特定列做垂直居中让多行文本在单元格里相对居中.layui-table-view .layui-table-cell { display: -webkit-box; -webkit-box-align: center; }不过display: -webkit-box这种写法本质上是弹性盒布局会让text-overflow: ellipsis彻底失效。如果你还有列需要省略号截断就得先想好优先级。我更推荐第一种方案保持display: block用行高和padding统一节奏副作用最小。4.2 固定高度表格下的换行滚动条和内容溢出纠缠不清layui表格常配height: full-200或者固定像素值外层会形成一个滚动容器。开启换行后行高动态变化有两个典型问题第一个是纵向滚动条出现这其实是正常现象因为总行高超过容器高度了。不需要处理但要让产品知道这个表现。第二个比较阴间td的overflow: visible之后如果外层.layui-table-body还有overflow: hidden的限制长内容在换行过程中会溢出到下一行然后被切割掉一半看起来像文字出框。我的经验是开启换行后检查一下.layui-table-body的overflow设置必要时改成overflow-x: auto; overflow-y: auto给内容留出滚动空间。另外如果表格列数多、总宽度超过容器原本就有横向滚动条再加上换行后的纵向滚动条横纵滚动条同时出现操作体验会很差。所以开启换行的表格尽量合理分配列宽避免横向滚动。4.3 大数据量下换行会影响渲染性能别硬撑layui表格在数据量较大时会走按需渲染或虚拟滚动逻辑。行高固定时虚拟滚动的计算很轻松直接按预设行高算就行一旦开启换行每行高度都不同虚拟滚动对行高的预判就会失准极端情况下会出现滚动跳跃、白屏、内容错位。对这个问题我的建议很实际需要换行的表格数据量控制在几千行级别超过1万行就不要再全局换行改用截断加弹窗查看详情的方案。产品上完全可以通过点击单元格弹层显示完整内容来兼顾海量数据和信息完整性技术上硬上换行反而给自己找麻烦。5. 我现在的标准处理流程一套组合拳解决95%的换行需求5.1 完整示例全局兜底加列级特例的处理模板经过几个项目的调试我现在team里的通用模板是这样的。CSS部分/* 全局允许所有单元格自动换行 */ .layui-table-cell { height: auto !important; min-height: 28px; line-height: 20px; white-space: normal; word-break: break-all; overflow: visible; } /* 固定列单独补充换行 */ .layui-table-fixed .layui-table-cell { height: auto !important; min-height: 28px; line-height: 20px; white-space: normal; word-break: break-all; overflow: visible; } /* 表头长标题自动换行 */ .layui-table th .layui-table-cell { height: auto !important; white-space: normal; word-break: break-all; line-height: 20px; overflow: visible; } /* 不需要换行的列操作按钮、状态标签等 */ .no-wrap .layui-table-cell { height: 28px !important; line-height: 28px !important; white-space: nowrap !important; overflow: hidden !important; text-overflow: ellipsis !important; }列配置里给不需要换行的列加className: no-wraptable.render({ elem: #table, url: /api/order/list, height: full-120, cols: [[ { field: status, title: 状态, width: 90, className: no-wrap, templet: function (d) { return d.status 1 ? 已开通 : 未开通; }}, { field: action, title: 操作, width: 160, toolbar: #barDemo, className: no-wrap }, { field: reason, title: 退款原因, minWidth: 200 }, { field: address, title: 收货地址, minWidth: 220 } ]] });这样整张表格的长文本列全部能自动换行而状态列、操作列保持原来的单行省略互不干扰。这套模板我用了大半年基本没出过幺蛾子。5.2 如果项目用的是layui-vue这些方法还能直接搬吗很多新项目已经切到layui-vue或者Vue3生态的table组件了CSS类名虽然有历史兼容但内部实现已经组件化。vue版表格的换行处理方式更现代化通常直接在列配置里控制ellipsis和tooltip相关属性不需要也不应该像jQuery版那样去暴力覆盖CSS。比如列配置里可以设置ellipsis: false让内容自动换行这类属性才是vue版的正道。如果你还在jQuery版layui上那本文这套方案是直接可用的如果已经vue化先去读官方文档的表格列配置别把老CSS硬扒过来反而容易冲突。5.3 换行没生效时先按这三个方向排查最后聊几个调试时经常遇到的坑照着检查很快能定位。第一查优先级。layui自带样式是.layui-table-cell你的覆盖如果写在全局样式表靠前的位置后面又被别的库或业务样式覆盖了自然不生效。排查时先用浏览器开发者工具选中单元格看看最终生效的white-space到底是哪个选择器给的。第二查固定层。主体表格换行了固定列还是截断别急着加!important先确认你是不是漏写.layui-table-fixed那一层。第三查改造后的缓存。layui表格在初始化时会计算一些布局参数如果你在页面运行时改CSS某些计算好的行高和单元格布局不会自动重新计算看起来像改了没生效。调试时改完CSS后强制刷新页面或者重新渲染表格再判断效果。还有一个经常被问到的细节换行后的表格内容复制到Excel时为什么还是挤在一行因为CSS换行是视觉换行文本内部并没有真实的换行符复制出去自然是一整行。如果需要复制到Excel时保留换行得在渲染数据时手动给文本加换行符或者在templet里处理数据源。这个和本文的视觉换行是两码事别混为一谈。我现在写了新表格第一件事就是先想清楚哪些列改换行、哪些列必须单行截断想明白了再动手配样式。毕竟要不要换行本质上是产品信息层级的问题想清楚了再调CSS才不会一遍遍反复改。
返回列表