骨架屏必须在layui.js加载前用HTML+CSS实现,因layui.use执行时DOM已渲染完成;正确做法是在顶部插入fixed定位遮罩,通过layui.config({done})移除。

为什么直接在 layui.use 里加骨架屏会失效
因为 layui.use 执行时,DOM 已渲染完成、页面早已可见,此时插入骨架屏用户根本看不到——白屏期早就过去了。更糟的是,如果你等 layui.use(['table', 'layer']) 完再操作,可能连 loading 动画都只闪一下就消失,完全起不到过渡作用。
真正要覆盖的“白屏”,是浏览器解析 HTML 到 JS 开始执行之间的那几十毫秒。这个阶段 Layui 还没加载,layer.load() 根本调用不了,必须靠纯 HTML + CSS 提前占位。
- 错误做法:在
layui.use回调里用layer.load()或手动document.body.appendChild() - 正确时机:在
最顶部、layui.js加载前,就写好遮罩 DOM - 关键约束:遮罩必须用
position: fixed+z-index: 999999,否则会被后续内容顶开或截断
怎么用 1 行 CSS + 3 行 JS 实现不卡顿的骨架遮罩
核心不是做多炫的动画,而是让遮罩“稳住位置、及时退场”。下面这段代码能跑通所有 Layui 版本(2.5+),且不依赖任何模块:
<div id="loading-mask" style="position:fixed;top:0;left:0;width:100%;height:100%;background:#fff;z-index:999999;display:flex;align-items:center;justify-content:center;">
<i class="layui-icon layui-icon-loading layui-icon-spin" style="font-size:32px;color:#009688;"></i>
</div>
<p><!-- 其他内容 -->
<script src="layui/layui.js"></script><script>
layui.config({ done: () => document.getElementById('loading-mask').remove() });
</script></p>
layui.config({ done }) 是唯一安全的移除时机:它比 layui.use 更早触发,确保 Layui 基础环境已就绪,又不会晚到让用户看到白屏。
- 别用
window.onload或$(document).ready(),前者太慢,后者在 Layui 初始化前就执行,layui对象还不存在 - 遮罩里的图标用 Layui 自带的
layui-icon-loading,不用额外引入字体或 GIF - 如果项目用了自定义主题色,把
color:#009688换成你的主色即可
表格加载前怎么塞一行骨架而不被 table.render 清空
典型结构如下: 然后用 Layer 弹层的内容是动态加载的,但 推荐做法是:骨架用独立 DOM 占位,加载成功后只替换其子内容,保留外层容器结构: 对应的 CSS 骨架样式建议用伪元素 + 最易被忽略的一点:骨架屏的尺寸必须和最终内容严格一致。比如表单行高是 36px,骨架的 table.render() 默认会清空容器内部所有 DOM,你提前插进去的骨架元素会被直接删掉。所以骨架屏不能塞进 或
div#demo 里面,得和表格容器平级、共用一个父容器。<div class="table-wrapper">
<div id="skeleton-row" style="visibility:hidden;position:absolute;top:0;left:0;width:100%;z-index:10;">
<div class="skeleton-item" style="height:42px;margin:8px 0;"></div>
</div>
<table id="demo"></table>
</div>
before(Layui 2.8+)或手动控制显隐:
before: () => document.getElementById('skeleton-row').style.visibility = 'visible'
document.getElementById('skeleton-row').style.visibility = 'visible' 放在 table.render() 调用前,done 里设回 hidden
visibility: hidden 而非 display: none,避免重排影响表格尺寸同步弹层(
layer.open)里怎么让骨架和真实内容无缝切换success 回调触发时,骨架已经渲染完毕。这时候不能简单地 .html() 替换,否则会丢失原有样式或事件绑定。layer.open({
type: 1,
content: '<div id="form-skeleton" class="skeleton-form"></div>',
success: function(layero) {
// 先显示骨架(CSS 已控制)
$('#form-skeleton').addClass('loading');
// 请求真实表单
$.get('/user/form/123').done(html => {
$('#form-skeleton').removeClass('loading').html(html);
}).fail(() => {
layer.msg('加载失败', {icon: 2});
});
}
});
@keyframes 实现,轻量且不依赖 JS:
.skeleton-form 设固定高度、圆角、背景渐变background-position 平移模拟光效,时长控制在 1.4s 内prefers-reduced-motion: reduce 降级支持,避免对动画敏感用户造成不适height 就得设成 36px;否则加载完成后会跳动,反而放大等待焦虑。











