使用 CSS 重新创建 Facebook Messenger 渐变效果

Avatar of Stepan Bolotnikov
Stepan Bolotnikov

DigitalOcean 为您旅程的每个阶段提供云产品。 立即开始使用 $200 免费积分!

一个星期天的早上,我比平时早起了一些,因为手机不断地嗡嗡作响。 我伸手拿起手机,点击进入 Facebook Messenger,加入了聊天。 不久后,我的注意力从实际的对话转移到了包含对话的消息气泡的 funky 渐变效果上。 让我向您展示我的意思

这是 Messenger 的一项新功能,它允许您为聊天消息的背景选择渐变而不是纯色。 它目前在移动应用程序以及 Facebook 网站上可用,但尚未在 Messenger 网站上可用。 渐变显示为“固定”,因此聊天气泡在垂直滚动时会显示出不同的背景颜色。

我认为这看起来像是可以在 CSS 中完成的,所以… _挑战接受!_

让我们一起回顾一下我的思路,当我尝试重新创建它并解释用于使其工作的 CSS 功能时。 此外,我们将了解 Facebook _实际上_ 是如何实现它的(剧透警告:不是我那样做的),以及两种方法的比较。

动手实践

首先,让我们再看一下示例,看看我们到底要实现什么。

总的来说,我们有一个相当标准的消息布局:消息被划分为从上到下的气泡,我们的气泡在右边,聊天中的其他人气泡在左边。 左边的气泡都具有灰色背景颜色,但右边的气泡看起来好像共享相同的固定背景渐变。 基本上就是这些!

步骤 1:设置布局

这部分非常简单:让我们将消息排列在一个有序列表中,并应用一些基本 CSS 使其看起来更像一个实际的消息应用程序

<ol class="messages">
  <li class="ours">Hi, babe!</li>
  <li class="ours">I have something for you.</li>
  <li>What is it?</li>
  <li class="ours">Just a little something.</li>
  <li>Johnny, it’s beautiful. Thank you. Can I try it on now?</li>
  <li class="ours">Sure, it’s yours.</li>
  <li>Wait right here.</li>
  <li>I’ll try it on right now.</li>
</ol>

谈到将消息划分为左右两部分时,我的第一反应是使用浮动。 我们可以对左边的消息使用 float: left,对右边的消息使用 float: right,使它们粘贴到不同的边缘。 然后,我们将在每条消息上应用 clear: both 以使它们堆叠起来。 但是,有一种更现代的方法——Flexbox!

我们可以使用 Flexbox 通过 flex-direction: column 将列表项垂直堆叠,并告诉所有子项粘贴到左边缘(或“将 flex 子项的交叉开始边缘与行的交叉开始边缘对齐”,如果您更喜欢技术术语)。 然后,我们可以通过在它们上设置 align-self: flex-end 来覆盖单个 flex 项的 align-items 值。

什么,你是说你无法根据这个可视化代码? 好的,这就是它的样子

.messages {
  /* Flexbox-specific styles */
  display: flex;
  flex-direction: column;
  align-items: flex-start;

  /* General styling */
  font: 16px/1.3 sans-serif;
  height: 300px;
  list-style-type: none;
  margin: 0 auto;
  padding: 8px;
  overflow: auto;
  width: 200px;
}

/* Default styles for chat bubbles */
.messages li {
  background: #eee;
  border-radius: 8px;
  padding: 8px;
  margin: 2px 8px 2px 0;
}

/* Styles specific to our chat bubbles */
.messages li.ours {
  align-self: flex-end; /* Stick to the right side, please! */
  margin: 2px 0 2px 8px;
}

在这里和那里添加一些填充和颜色,这已经足够相似,可以继续进行有趣的步骤了。

步骤 2:让我们为事物着色!

关于渐变的初始想法实际上来自 Matthias Ott 的这条推文(Chris 在另一篇文章中重新创建了它

这里的关键线索是 mix-blend-mode,它是一个 CSS 属性,允许我们控制元素的内容如何与后面的内容混合。 它是一项已在 Photoshop 和其他类似工具中存在一段时间的功能,但对网络来说是相当新的。 有一个关于该属性的 年鉴条目,它解释了所有可能的值。

其中一个值为 screen:它获取背景和前景像素的值,反转它们,将它们相乘,然后再次反转它们。 这将产生一种比原始背景颜色更亮的顏色。

描述可能看起来有点令人困惑,但它本质上意味着,如果背景是单色的,则在背景为黑色的地方,将完全显示前景像素,而在背景为白色的地方,白色保持不变。

使用前景的 mix-blend-mode: screen;,我们将看到更多前景,因为背景更暗。

因此,为了达到我们的目的,背景将是聊天窗口本身,而前景将包含一个元素,该元素具有设置为背景的所需渐变,并放置在背景之上。 然后,我们将适当的混合模式应用于前景元素,并重新设置背景样式。 我们希望背景在我们要显示渐变的地方为黑色,而在其他地方为白色,因此我们将通过为气泡设置纯黑色背景和白色文字来设置它们样式。 哦,还要记住在前景元素中添加 pointer-events: none,以便用户可以与底层文本进行交互。

此时,我还稍微更改了原始 HTML。 整个聊天是在一个额外的容器中的一个包装器,允许渐变在聊天的可滚动部分上保持“固定”。

.messages-container:after {
  content: '';
  background: linear-gradient(rgb(255, 143, 178) 0%, rgb(167, 151, 255) 50%, rgb(0, 229, 255) 100%);
  position: absolute;
  left: 0;
  top: 0;
  height: 100%;
  width: 100%;
  mix-blend-mode: screen;
  pointer-events: none;
}

.messages li {
  background: black;
  color: white;
  /* rest of styles */
}

结果看起来像这样

应用于聊天气泡的渐变

步骤 3:将某些消息排除在渐变之外

现在,渐变正在文本气泡所在的地方显示! 但是,我们只希望它在_我们_的气泡上显示——即沿着右边缘的气泡。 如何实现这一目标的提示隐藏在 MDN 的 mix-blend-mode 属性描述

mix-blend-mode CSS 属性设置元素的内容应如何与元素的父元素的内容和元素的背景混合。

没错! 背景。 当然,该效果只考虑位于当前元素后面且具有较低堆叠顺序的 HTML 元素。 幸运的是,可以使用 z-index 属性轻松更改元素的堆叠顺序。 因此,我们所要做的就是让左边聊天气泡的 z-index 比前景元素的 z-index 更高,它们将被提升到前景元素之上,不受 mix-blend-mode 的影响! 然后,我们可以根据自己的意愿设置它们样式。

应用于聊天气泡的渐变。

让我们谈谈浏览器支持

在撰写本文时,mix-blend-mode 在 Internet Explorer 和 Edge 中完全不受支持。 在这些浏览器中,渐变被放置在整个聊天之上,其他人的气泡出现在渐变之上,这不是理想的解决方案。

这些浏览器支持数据来自 Caniuse,它包含更多详细信息。 数字表示浏览器从该版本开始支持该功能。

桌面

ChromeFirefoxIEEdgeSafari
413279TP

移动/平板

Android ChromeAndroid FirefoxAndroidiOS Safari
12712712718.0

因此,这就是我们在不支持的浏览器中获得的结果

不支持 mix-blend-mode 的浏览器如何呈现聊天。

幸运的是,所有支持 mix-blend-mode 的浏览器也支持 CSS 功能查询。 使用它们可以先为不支持的浏览器编写后备样式,然后为支持它们的浏览器包含花哨的效果。 这样,即使用户看不到完整的效果,他们仍然可以看到整个聊天并与之交互

为旧版浏览器简化的 UI,退回到纯青色背景颜色。

这是具有完整效果和后备样式的最终 Pen

查看 Pen
在 CSS 中使用 Facebook Messenger 式渐变颜色
by Stepan Bolotnikov (@Stopa)
CodePen 上。

现在让我们看看 Facebook 是如何做到的

事实证明,Facebook 的解决方案几乎与我们在这里讨论的内容相反。 他们不是将渐变放置在聊天之上并在其中打孔,而是将渐变作为固定背景图像应用于整个聊天。 聊天本身充满了许多带有白色背景和边框的空元素,除了渐变应该可见的地方。

Facebook Messenger React 应用程序渲染的最终 HTML 非常冗长且难以导航,因此我重新创建了一个简化的示例来说明它。 许多空 HTML 元素可以用伪元素代替。

查看 Pen
在 CSS 中使用 Facebook Messenger 式渐变颜色:Facebook 的方法
by Stepan Bolotnikov (@Stopa)
CodePen 上。

正如您所见,最终结果看起来类似于mix-blend-mode解决方案,但增加了少量额外的标记。此外,他们的方法为图像和表情符号等丰富内容提供了更大的灵活性。如果背景不是单色,mix-blend-mode方法实际上不起作用,而且我还没有找到一种方法将内部内容“提升”到渐变之上,或者以其他方式克服此限制。

由于此限制,在实际聊天应用程序中使用 Facebook 的方法更为明智。尽管如此,我们使用mix-blend-mode的解决方案展示了一种有趣的方式来使用现代网页设计中最不为人知的 CSS 属性之一,希望它能为您提供一些关于如何使用它的想法!