纯 CSS 实现骨架屏与 Loading 动画(从原理到实战案例)

392 阅读4分钟

前言

在日常开发中,页面加载体验一直是用户体验优化的重要一环。

  • 痛点 1:接口数据加载慢时,用户会看到一片空白,不知道系统是否卡死。
  • 痛点 2:简单的 loading... 文本提示太单调,不够友好。
  • 常见方案缺陷:使用第三方库(如 Ant Design、Element Plus)虽能快速引入骨架屏和加载动画,但会增加依赖、限制自定义能力。

因此,本文将带你用 纯 CSS 实现 骨架屏 + Loading 动画,不仅能解决「加载反馈」问题,还能灵活组合出多种效果。
👉 读完本文,你将收获:

  1. 理解骨架屏与 Loading 动画的实现原理
  2. 掌握纯 CSS 编写可复用的加载效果
  3. 学会在实际项目中组合使用,提升用户体验

recording.gif

在线demo:

基础概念解析

  1. 骨架屏(Skeleton)​​:

    • 模拟页面结构的灰色占位块
    • 通过渐变动画营造"流动感"
    • 适用于内容区块加载(如卡片、列表)
  2. 加载动画(Spinner)​​:

    • 旋转指示器,明确提示加载状态
    • 常用于局部或全局加载提示
    • 通过CSS动画实现无限旋转

方案核心需求

  1. 视觉连贯性​:保持页面结构稳定,避免布局跳动
  2. 状态明确性​:清晰传达加载状态
  3. 组合灵活性​:支持单独或组合使用
  4. 性能优化​:纯CSS实现,零JS依赖

核心实现模块

步骤1:骨架屏实现原理

骨架屏通过线性渐变背景+位移动画模拟加载效果:

.skeleton {
  /* 创建灰度渐变:浅灰-中灰-浅灰 */
  background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
  
  /* 设置200%宽度,为动画留出移动空间 */
  background-size: 200% 100%;
  
  /* 无限循环的位移动画 */
  animation: loading 1.5s infinite;
}

@keyframes loading {
  0% {
    /* 从右侧开始 */
    background-position: 200% 0;
  }
  100% {
    /* 移动到左侧 */
    background-position: -200% 0;
  }
}

关键点解析​:

  • background-size: 200% 100%创建两倍宽度的背景,使渐变可以左右移动
  • 动画通过改变background-position实现"流动"效果
  • 灰度渐变模拟内容加载的视觉暗示

步骤2:加载动画实现原理

使用伪元素创建旋转指示器:

.spin::after {
  content: ""; /* 必须的伪元素内容 */
  position: absolute;
  left: 50%;
  top: 50%;
  
  /* 尺寸和形状 */
  width: 24px;
  height: 24px;
  border: 3px solid rgba(255, 255, 255, 0.3); /* 底环 */
  border-top: 3px solid #fff; /* 高亮顶部 */
  border-radius: 50%; /* 圆形 */
  
  /* 旋转动画 */
  animation: spin-relative 1s linear infinite;
}

@keyframes spin-relative {
  0% {
    /* 保持居中同时旋转 */
    transform: translate(-50%, -50%) rotate(0deg);
  }
  100% {
    transform: translate(-50%, -50%) rotate(360deg);
  }
}

关键点解析​:

  • ::after伪元素避免污染DOM结构
  • transform: translate(-50%, -50%)实现绝对居中
  • 边框差异着色创建"缺口"效果
  • 旋转动画使用linear保持匀速

步骤3:组合应用技巧

通过类名组合实现效果叠加:

<!-- 单独骨架屏 -->
<div class="card skeleton"></div>

<!-- 单独加载动画 -->
<div class="card spin"></div>

<!-- 组合效果 -->
<div class="card skeleton spin"></div>

实现原理​:

  • CSS类名独立设计,互不影响
  • 骨架屏处理背景动画
  • 加载动画通过伪元素覆盖在内容上方
  • 组合时自动叠加效果

效果/使用演示模块

场景1:纯骨架屏效果

<div class="card skeleton">
  <p>内容加载中...</p>
</div>

效果​:灰色渐变背景从左向右流动,保持卡片形状,适合内容区块加载

场景2:纯加载动画

<div class="card spin">
  <p>数据请求中...</p>
</div>

效果​:卡片中心显示旋转指示器,明确提示加载状态

场景3:组合效果(推荐)

<div class="card skeleton spin">
  <p>加载用户信息...</p>
</div>

效果​:

  1. 骨架屏保持布局结构
  2. 中心旋转动画提供明确反馈
  3. 两者叠加创造层次感

验证方式​:

  1. 在浏览器中运行代码
  2. 观察动画是否流畅无卡顿
  3. 调整窗口大小验证响应式表现
  4. 检查控制台无任何JS错误

扩展方向

  1. 动态骨架屏​:

    • 根据内容结构生成不同形状的骨架
    • 实现思路:使用CSS变量控制高度
    .skeleton-item {
      height: var(--item-height);
    }
    
  2. 进度指示加载​:

    • 结合加载进度调整动画
    • 实现思路:通过JS动态修改CSS变量
    element.style.setProperty('--progress', `${percent}%`);
    

总结与互动模块

本文核心要点​:

  1. 骨架屏通过渐变背景动画保持布局结构
  2. 加载动画使用伪元素+旋转提供明确反馈
  3. 组合方案兼顾视觉稳定性和状态提示
  4. 纯CSS实现零依赖,性能优异