mcpField
L
loading-states-and-perceived-performance

loading-states-and-perceived-performance

github.com/dembrandt设计与 UI174887 次安装1 周前更新
代码仓库

关于 loading-states-and-perceived-performance

一项关于加载状态与感知性能的设计技能,面向设计师和开发者,涵盖加载提示选择、内容优先级,以及无法缩短的等待如何处理。

主要功能

  1. 01按等待时长选择加载提示
  2. 02使用匹配布局的骨架屏
  3. 03优先加载内容并延后无关数据
  4. 04预取可预测的后续步骤
  5. 05采用可回滚的乐观更新
  6. 06区分慢请求与长时任务

适用场景

  1. 01设计按钮操作和数据获取的反馈
  2. 02规划仪表板和页面的分阶段加载
  3. 03改善上传和导出期间的响应感

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/dembrandt/dembrandt-skills --skill loading-states-and-perceived-performance

安装后在 Claude Code 中输入/loading-states-and-perceived-performance确认已加载。

详细介绍

加载状态与感知性能

如果用户了解自己在等 什么,以及进度 如何,等待就没那么难以忍受。感知性能是一种设计方法,旨在让系统感觉起来比实际更快。


选择合适的加载状态

等待时长最佳模式适用场景
较短(< 1s)行内微调器 / 加载器按钮操作、小幅更新、快速获取数据
中等(1s – 3s)骨架屏卡片、列表、仪表板、个人资料页
较长(> 3s)确定进度条文件上传、复杂导出、繁重处理
全页错落入场 / 动画分区应用初次加载、主视觉区域、沉浸式过渡

简单场景:微调器和加载器

对于布局不会显著变化的小型独立操作,请使用微调器。

  • 按钮微调器: 替换按钮文本,或显示在文本旁边。按钮应进入 disabled 状态,以防止重复提交。
  • 微型加载器: 用于行内更新(例如保存单个字段)的 16–24px 小圆圈。
  • 动画提示: “弹簧式”旋转(缓入缓出)比匀速线性旋转更显精致。
@keyframes spin {
  0%   { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}
.spinner {
  animation: spin 800ms cubic-bezier(0.4, 0, 0.2, 1) infinite;
}

骨架屏(微光 / 闪光)

骨架屏提供一个视觉占位符,模拟最终内容的布局。这可以减少“布局偏移”(CLS),并明确告知用户内容将出现的位置。

闪光效果

一道微妙的渐变在骨架元素上移动。

.skeleton {
  background: var(--color-grey-100);
  background-image: linear-gradient(
    90deg,
    rgba(255, 255, 255, 0) 0%,
    rgba(255, 255, 255, 0.5) 50%,
    rgba(255, 255, 255, 0) 100%
  );
  background-size: 200% 100%;
  animation: shimmer 1.5s infinite;
}

@keyframes shimmer {
  0%   { background-position: -200% 0; }
  100% { background-position: 200% 0; }
}
骨架屏规则
  • 形状要匹配: 如果最终内容是圆形头像,就使用圆形骨架屏。如果是两行标题,就使用宽度不同的两条横线。
  • 保持低调: 骨架屏应使用最浅的灰色(--color-grey-100 或 grey-50),不应吸引用户注意。
  • 渐显为真实内容: 数据到达后,让实际内容在骨架屏上方淡入(150–200ms),而不是突然切换。

完整动画分区

对于主要页面过渡或初次加载,请采用协调一致的动画策略。

错落入场(依次展开)

不要让整个页面同时出现,而是让各个分区依次播放动画。这样可以引导用户的视线从最重要的内容(主视觉区域)移向次要区域。

.section {
  opacity: 0;
  transform: translateY(10px);
  animation: slide-up 400ms ease-out forwards;
}
/* Stagger by index */
.section:nth-child(1) { animation-delay: 100ms; }
.section:nth-child(2) { animation-delay: 200ms; }
.section:nth-child(3) { animation-delay: 300ms; }

@keyframes slide-up {
  to { opacity: 1; transform: translateY(0); }
}
主视觉区域“绽放”

对于主视觉区域,可以使用更复杂的动画:

  1. 背景图片缓慢淡入。
  2. 标题略微过冲(弹簧效果)后滑入。
  3. CTA 按钮最后出现,并以利落的淡入或微妙的颜色过渡呈现。

按优先级加载,并预取后续内容

不要等到所有内容都准备好才开始显示。按照对用户的价值排序加载,让用户需要的内容先出现,其余内容随后补齐。这既能提升感知性能,也能提高代码效率:初始阶段获取和渲染的内容更少。

  • 首先,加载价值最高的内容——关键数据、主要记录、首屏可见的答案。准备就绪后立即渲染。
  • 然后,加载下一优先级的内容——次要面板、相关列表和首屏以下的分区随后逐步加载(骨架屏会占据其空间,避免页面偏移——参见上面的骨架屏部分)。
  • 只获取当前视图需要的数据。 对标签页、抽屉和屏幕外的分区,等用户打开时再加载数据,不要一次性加载整页所需的数据。

预取可预测的下一步——下一页、鼠标悬停行的详情、向导的下一步——在后台提前加载,让它们可以即时显示。不要推测性地加载所有内容;只在下一步显而易见时才这样做。

高级:乐观 UI

最快的 UI,就是完全不等待服务端响应的 UI。

  • 模式: 立即更新 UI,假定服务端调用会成功。如果失败,则回滚并显示错误。
  • 适用场景: 点赞帖子、切换开关、重命名文件夹、删除消息。
  • 优势: 为用户带来即时满足感,让应用感觉“快如闪电”。

为等待增添乐趣

加载体验不必平淡无奇。对于超过 2 秒的等待,可以考虑融入品牌个性和“乐趣”,让用户保持参与感。

符合品牌风格的微文案

用能体现品牌语气的措辞,替换通用的“加载中……”文本。

  • 技术风:“正在编译数据……”“正在与云端同步……”
  • 活泼风:“正在收集像素……”“正在为你的仪表板煮咖啡……”“马上就好!”
  • 专业风:“正在准备报告……”“正在核实详情……”
品牌动画(Lottie/SVG)

对于较重要的加载时刻(应用初次启动、复杂数据处理),可以用简洁且契合品牌的动画替代标准旋转图标。

  • 设计工具可以展示一支铅笔画出一条线。
  • 健身应用可以展示跳动的心脏或奔跑的图标。
  • 金融工具可以展示硬币堆叠或图表线向上移动。
渐进式讲述

如果等待时间一贯较长(3 秒以上),可以利用加载区域讲述一个小故事或提供有用信息:

  • 技巧提示:“你知道可以使用 Ctrl+K 进行搜索吗?”
  • **过程透明:**展示系统正在执行的操作:“正在检查数据库……” → “正在优化结果……” → “正在完成视图……”
视觉过渡(内容呈现)

从加载状态过渡到内容时,使用清晰利落的淡入效果(150ms),让内容呈现如同一份奖励。避免缩放即将显示的内容,因为这可能导致布局不稳定。

光标不是加载状态

光标用于提示可操作性:普通内容使用箭头,可执行操作的对象使用 pointer。光标从不表示进度。使用 cursor: wait 或 cursor: progress 会把状态提示放在用户不会关注的地方,既不说明正在加载什么,也不显示进度,而且指针一移动,提示就会消失。应在实际等待的元素或区域中显示进度:[[button-states]] 介绍了控件的相关做法,上文的骨架屏和进度模式则介绍了区域的相关做法。

加载状态无法做到什么

加载状态能让人更有耐心,但不能争取时间,也无法挽救注定会失败的请求。下面的阈值是长期确立的响应时间限制,并非新发现;后面要说的,是通常被忽略的推论。

  • 约 10 秒以内: 微调器或骨架屏可以承载等待。
  • 超过这个时间: 界面需要显示真实进度,并提供取消方式。不确定进度的动画不再传递信息,而是变成了装饰,掩盖着未知状况。
  • 超过约 30 秒: 无论界面上在播放什么动画,人们都会觉得应用卡住了,并开始重新加载或离开。

如果请求经常超出这些阈值,问题就出在请求本身。 如果请求即将触发后端超时,更丰富的指示器只会推迟用户注定会遇到的错误,同时掩盖产品已出故障这一事实,让团队无从察觉。微调器只是把故障出现的时间往后推,导致没人修复根因,而用户最终还是会放弃任务。

如果等待确实无法缩短,问题也不在请求本身。 大型导出、模型调用、视频转码:有些工作需要多少时间就是多少时间,再好的指示器也无法缩短等待。此时的解决方案是让用户不必盯着界面等待。接受任务,告知用户任务正在运行,让他们去做别的事,并在任务完成后通知他们,同时把结果放在他们能找到的地方。让一个人盯着进度条等两分钟,是一种选择,而这很少是他们会做出的选择。需要避免的是把无法缩短的等待当作性能问题,又把可以优化的等待视为理所当然;两者需要截然相反的应对方式,所以在设计等待体验之前,先判断自己面对的是哪一种。


审查清单

  • 加载状态是否适合预期等待时长(微调器还是骨架屏)?
  • 骨架屏是否符合即将加载内容的实际布局?
  • 骨架屏是否带有细微的闪烁动画,以提示“正在加载”?
  • 加载期间是否禁用了按钮,以防止重复操作?
  • 内容是否在骨架屏上方渐显(150–200ms),而不是突然出现?
  • 对于整页加载,是否采用了交错入场效果来引导视线?
  • 是否为所有加载动画遵循 prefers-reduced-motion 设置?
  • 在“乐观 UI”场景中,如果操作失败,是否有明确的回滚路径?
  • 内容是否按优先级加载(先加载价值最高的内容,其余内容随后逐步载入),并且只获取当前视图所需的内容,而不是一开始就全部加载?
  • 如果下一步可以预测,是否进行了预取,让操作感觉即时,同时避免投机性地加载所有内容?

常见反模式

反模式问题修复方法
阻塞整个应用的全局微调器用户非常沮丧,无法浏览其他区域使用上下文加载指示器或骨架屏
与最终布局不匹配的骨架屏数据到达时发生大幅布局偏移(CLS)精确匹配形状和尺寸
单个页面上出现太多微调器造成视觉噪声,让人觉得整个应用都坏了将多个加载状态归入一个容器骨架屏
速度快得离谱的骨架屏闪烁动画过快或对比度过高让闪烁缓慢(1.5s+)且非常细微

评论

支持 Markdown