如何在 CSS 中制作“拉开窗帘”效果

Avatar of Silvestar Bistrović
Silvestar Bistrović

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

“拉开窗帘”是我对一种效果的称呼,这种效果在滚动时背景颜色从深色变为浅色,而顶部的內容在粘性定位时也从浅色变为深色。

这是一个我在 真实项目 中使用该效果的示例

想知道它是如何实现的吗? 我将带您深入了解幕后,并向您展示如何仅使用 HTML 和 CSS 来实现它。

让我们从 HTML 开始

我们正在制作的是一种简化的“拉开窗帘”效果,如下所示

Showing the raise the curtains effect from dark blue to wheat.
背景和文本在滚动经过元素时都会更改颜色。

为了清晰起见,我将内容保持简单,但我们可以用三个元素来构建它

<div class="curtain">
  <div class="invert">
    <h2>Section title</h2>
  </div>
</div>

首先,我们需要一个用于窗帘的容器,我们将赋予它一个 .curtain 类。然后,在 .curtain 内部,我们有一个 .invert 子元素,它将充当我们的“粘性”框。最后,我们在该框内放置内容——在本例中是一个普通的 <h2> 元素。

让我们设置一些 CSS 变量

有三个值我们事先需要知道。让我们将它们作为 CSS 变量,这样就可以轻松地将它们写入我们的样式,并在以后需要时轻松更改它们。

  • --minh – 容器的高度
  • --color1 – 浅色
  • --color2 – 深色
:root {
  --minh: 98vh;
  --color1: wheat;
  --color2: midnightblue;
}

开始绘制窗帘

接下来,我们可以使用以下技术定义我们的 .curtain 元素

  • 用于“分割”背景的 linear-gradient
  • 容器底部额外空间的 min-height

我们使用 ::after 伪元素在底部添加额外的空间。这样,我们的“粘性”内容在滚动经过 ::after 元素时实际上会粘在容器上。这是一种视觉效果。

.curtain {
  /** create the "split" background **/
  background-image: linear-gradient(to bottom, var(--color2) 50%, var(--color1) 50%);
}

/** add extra space to the bottom (need this for the "sticky" effect) **/
.curtain::after {
  content: "";
  display: block;
  min-height: var(--minh);
}

制作粘性内容

接下来,我们需要使我们的内容“粘性”,以便它在背景和文本交换颜色值时完美地位于容器内。事实上,我们已经为 .curtain 的子元素赋予了一个 .invert 类,我们可以将其用作粘性容器。

请稍等片刻——以下是它的运作方式

  • position: stickytop 定义粘性以及粘附的位置。
  • mix-blend-mode: difference<h2> 元素内内容的颜色与 .curtain 的背景渐变混合。
  • display: flex 将内容居中以进行展示。
  • min-height 定义容器的高度并允许底部有额外的空间。
  • color 设置 h2 标题的颜色。

现在将其放入 CSS 代码中!

.invert {
  /** make the content sticky **/
  position: sticky;
  top: 20px;

  /** blend the content with the contrast effect **/
  mix-blend-mode: difference;

  /** center the content **/
  display: flex;
  align-items: center;
  justify-content: center;
  
  /** set the minimum height of the section **/
  min-height: var(--minh);
}

h2 {
  /** set the color of the text **/
  color: var(--color1);
}

这里有很多内容,所以让我们逐一解释。

首先,我们有一个不言而喻的粘性定位和 flexbox,以帮助 居中内容。这里没有新的或特别棘手的东西。

内容的高度使用 CSS 变量设置,其值与 .curtain::after 伪元素的高度值相同。

mix-blend-mode: difference 声明将我们的内容与背景混合。difference 值很复杂,但您可以将其视为背景上反转的文本颜色。以下是来自 CSS-Tricks 年鉴的一个很好的演示,展示了不同的 mix-blend-mode

为了使混合效果生效,我们需要设置标题的颜色。在本例中,我们将浅色值 (wheat) 分配给 --color1 变量。

“拉开窗帘”演示

注意事项

在制定“拉开窗帘”效果的细节时,我遇到了一些问题。例如,如果您想在“粘性”内容中添加图像,请避免使用在颜色反转时看起来不好的图像。这是一个我制作了一个简单的 SVG 和透明 PNG 图像的快速演示,它看起来不错。

另一个注意事项:无法在特定子元素(如标题)上设置 mix-blend-mode: difference,同时避免对图像产生影响。我发现有几个原因导致它不起作用,首先是 position: sticky 会取消混合效果。

在容器上使用 transform: skewY 添加一点“倾斜”效果时也是如此。我怀疑其他属性与混合效果配合得不好,但我没有深入研究以找出是哪些属性。

这是一个不进行滚动的演示,它去除了有问题的属性

谢幕!

我很享受构建这个组件的过程,我总是喜欢用 HTML 和 CSS 就能完成一些事情,尤其是在它们在每个浏览器上都能流畅运行时。

您将用它做什么?您是否会采用不同的方法来实现类似的“拉开窗帘”效果?请在评论中告诉我!