内容跳动(以及如何避免它)

Avatar of Brandon Smith
Brandon Smith 发布

DigitalOcean 为您旅程的每个阶段提供云产品。立即开始使用 200 美元的免费额度!

在网络上,没有什么比页面布局在您尝试查看或与之交互时意外地发生变化或移动更令人恼火的了。无论您是在尝试阅读一篇文章时它都在您面前晃动,还是尝试点击一个链接却发现另一个链接将其推开并带您到意外的地方,这总是令人沮丧的。

这种布局偏移在移动设备上尤其令人沮丧,因为足够大的变化可能会将所有熟悉的内容推离屏幕,导致访问者完全失去方向。我认为,在初始渲染后(无相关用户交互)更改页面布局可能是网站所能产生的最令人不愉快的用户体验。我惊讶地发现,即使是一些大型知名网站,在其他方面做得非常好,也会发生这种情况。好消息是,这是可以修复的。

幸运的是,现代浏览器在样式表加载完成后才会执行初始渲染,这意味着通过一些巧妙的 CSS,我们可以做很多事情来解决这个问题。

是什么导致布局偏移?

最常见的是,它是加载 Ajax 部分的结果。Ajax 是异步的,这意味着没有任何东西在等待它完成。但是,当它完成并且结果被放置到文档中时,它可能会导致重新布局并将其他元素推到周围。

这在广告中尤其常见,但可能发生在任何影响布局的内容上,这些内容在初始渲染后加载,包括图像甚至字体。

我在自己工作的网站上遇到了这个问题

我第一次遇到这个问题实际上不是因为广告或图像,而是因为我们自己的服务器渲染的模板。我当时在 Broadleaf Commerce 工作,在一个现有的管理界面上添加功能。我们不想使用 Angular 之类的东西重建整个界面,但我们确实希望某些内容能够在无需页面刷新即可更新。我们创建了绑定到服务器路由的 Ajax 容器,这些容器将重新渲染并只发送回页面的一部分。它工作得非常好,但在某些情况下,我们有多个这样的部分沿着页面向下排列,中间有静态标题。访问后几秒钟,标题(有时还有其他静态内容)都会向下跳动——正是我们试图避免的那种令人不快的布局偏移体验。

使用min-height修复

为了修复它,我使用浏览器的 DevTools 测量了结果内容的高度,并将其作为容器的min-height硬编码到 CSS 中。

假设此小部件是通过 Ajax 加载的。我们可以在这里测量它的尺寸,并在占位符元素上设置min-height: 363px

这意味着周围的布局开始处于或多或少最终的状态,唯一的变化是内容框的内部。我还为容器设置了背景颜色,以表明某个地方会出现内容。这些简单的添加使界面更加具体和可预测。有人可能会争论是否明智地将最小高度硬编码,因为它使布局与内容分离。这就是为什么我们使用min-height而不是height。如果内容最终使元素更高,它仍然可以这样做,这不太好,但比什么都不做要好一点。

这是一个示例,展示了它将是什么样子(重新运行以查看延迟的广告加载)

查看 CodePen 上 CSS-Tricks 团队的笔 避免内容跳动 (@css-tricks)。

另一个示例:第三方小部件

还有一次,我正在为一个客户网站工作,他们希望在他们的结账页面上使用 Braintree 即用型 UI (https://www.braintreepayments.com/products-and-features/drop-in-ui)。

这是一个很棒的小部件,但您会注意到,即使在 Braintree 自己的网站上,当小部件展开时,内容也会被四处推动。值得称赞的是,Braintree 通过平滑过渡来实现这一点,这有助于保持一定的连续性,但我所处理的页面仍然受益于具有min-height的包装器元素,从而防止结账按钮等基本元素意外移动。

使用过渡修复

使用平滑过渡可以使意外的内容更改不那么令人不快。

.ad-wrapper {
  height: 0;
  overflow: hidden;
  transition: height 0.66s ease-out;
}
.ad-wrapper.loaded {
  height: 100px;
}

查看 CodePen 上 CSS-Tricks 团队的笔 避免内容跳动 (@css-tricks)。

缺点是它们仅在您显式设置尺寸时才有效;min-属性和内容派生的布局更改不会过渡。尽管如此,在您具有不可预测大小的内容并且不介意使用 JavaScript 查询其大小并相应地平滑调整容器大小时,仍然可以使用过渡。

另一个示例:字体加载偏移

在一个不太常见的情况下,我曾经在一个客户网站上工作,该网站突出使用了横向压缩的字体。问题在于它必须加载,因此几秒钟后,几乎所有网站内容都会突然改变大小。它不像上面示例那样剧烈偏移,但由于它影响了页面上的几乎所有内容,因此它更像是一个视觉瑕疵。最后,我找到了这篇非常 棒的文章,它提供了一个冗长但有效的font-family语句,涵盖了所有主要平台的网络安全压缩字体。但在找到它之前,min-height再次成为我的朋友。

网络上的示例

The Verge(移动版)

我注意到在 The Verge

  1. 它们顶部的广告有时是小型横幅,有时是大型广告
  2. 他们似乎已经在为横幅大小的广告使用min-height技术

他们的广告 API 可能不会告诉他们广告的大小。如果确实如此,他们应该相应地采用min-height。如果这不可能,他们可能已经在使用纯 CSS 做了所有他们能做的事情。尽管如此,我仍然认为,从 UX 的角度来看,一个非常大的广告应该放在内容中的更下方,而不是在最顶部,而横幅更适合放在顶部。再说一遍,在用户访问主页时立即向他们显示一个几乎全屏的广告可能是利润丰厚的收入来源。

Kotaku(移动版)

值得注意的是,在 Kotaku 上,主页的最顶部没有广告,因此当您第一次访问它时不会出现跳动。但是,如果页面在已经向下滚动一段距离时加载(例如,在您阅读完文章后按下后退按钮时),则会因帖子流中散布的大型广告而导致一些巨大的、令人迷惑的跳动。它们似乎都是相同的大小,因此这将是一个简单的修复。

总结

在设计任何用户体验时,最重要的是要牢记预期行为。我们期望点击一段蓝色的、带下划线的文本会将我们带到另一个页面。如果它反而打开了一个模态框或什么也没做,那么我们就会遇到一个令人困惑和沮丧的用户体验。我们在当前页面上的导航也是如此。当我们看到一篇文章出现在我们面前时,我们期望它保持静止,除非我们滚动它。当我们看到一个链接或按钮时,我们期望它在我们触碰该位置时仍然存在。违反这些基本假设,轻则令人不快,重则令人沮丧甚至迷失方向。