将一个元素编织在另一个元素之上和之下

Avatar of Preethi
Preethi

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

在这篇文章中,我们将使用 CSS 超能力来创建一个视觉效果,其中两个元素重叠并交织在一起。这种设计的灵感来自于我短暂的灵性探索,最终我来到了 圣经项目网站。他们制作了非常酷的动画,我的意思是,**非常**酷的动画。

然而,我的注意力从灵性转向了网页设计,因为我不断地注意到这些进出边框的插图。

圣经项目网站的截图。

我想知道是否可以用纯 CSS 创建类似的效果……谢天谢地,这是可能的!

查看 CodePen 上 Preethi Sam (@rpsthecoder) 编写的
使用 CSS 设计的上下边框

CodePen 上。

我们在这项技术中使用的主要 CSS 标准是 CSS 混合模式CSS Grid

首先,我们从**一张图片和一个位于图片前面的旋转框架**开始。

<div class="design">
  <img src="bird-photo.jpg">
  <div class="rotated-border"></div>
</div>
.design {
  position: relative;
  height: 300px;
  width: 300px;
}

.design > * {
  position: absolute;
  height: 100%;
  width: 100%;
}

.rotated-border {
  box-sizing: border-box;
  border: 15px #eb311f solid;
  transform: rotate(45deg);
  box-shadow: 0 0 10px #eb311f, inset 0 0 20px #eb311f;
}

红色框架是使用border创建的。它的box-sizing设置为将边框大小包含在框的尺寸中,以便框架在旋转后以图片为中心。否则,框架将大于图片并被拉向右下角。

然后,我们选择图片的一对相对角,并将其象限与之前相同图片的副本中相应的区域**叠加**。这会隐藏那些角上的红色框架。

我们基本上需要制作一个如下所示的图片裁剪部分,放在红色框架的上面。

可见的两个象限将位于.rotated-border元素的顶部。

那么,我们如何修改图片,使其只有两个象限可见呢?CSS 混合模式!在这种情况下,我们将使用multiply值。这通过去除图片中的白色来增加元素的透明度,从而显示元素后面的内容。

Chris 有一个很好的演示,展示了如何在使用 multiply 混合模式的图片中显示红色背景。

查看 CodePen 上 Chris Coyier (@chriscoyier) 编写的
背景混合

CodePen 上。

好的,不错,但是那些象限呢?**我们用白色网格单元格覆盖我们想要隐藏的象限,这些单元格会导致图片在这些特定区域完全穿透,并在源代码中在其顶部放一个鸟类图片的副本。**

<div id="design">
    <img src="bird-photo.jpg">
    <div class="rotated-border"></div>

    <div class="blend">
      <!-- Copy of the same image -->
      <img src="bird-photo.jpg">
      <div class="grid">
        <!-- Quadrant 1: Top Left -->
        <div></div>
        <!-- Quadrant 2: Top Right -->
        <div data-white></div>
        <!-- Quadrant 3: Bottom Left -->
        <div data-white></div>
        <!-- Quadrant 4: Bottom Right -->
        <div></div>
      </div>
    </div>

</div>
.blend > * {
  position: absolute;
  height: 100%;
  width: 100%;
}

/* Establishes our grid */
.grid {
  display: grid;
  grid: repeat(2, 1fr) / repeat(2, 1fr);
}

/* Adds white to quadrants with this attribute */
[data-white]{
  background-color: white;
}

结果是一个二乘二的网格,其右上和左下象限填充白色,同时与.blend内部的图片组合在一起。

对于那些刚接触 CSS Grid 的人来说,我们正在做的是添加一个新的.grid元素,当我们声明display: grid;时,它将成为一个“网格”元素。然后我们使用grid属性(它是grid-template-columnsgrid-template-rows组合在一起的简写)来创建两个等间距的行和列。我们基本上是在说:“嘿,网格,在你自己内部重复两个相等的列和两个相等的行,形成四个盒子。”

图片的副本和一个带有白色单元格的网格,位于红色边框的顶部。

现在,我们使用mix-blend-mode属性将 multiply 混合模式应用于.blend

.blend { mix-blend-mode: multiply; }

结果

如您所见,混合模式会影响所有四个象限,而不仅仅是我们想要穿透的两个象限。这意味着我们可以看到所有四个象限,从而显示出所有旋转的红色框。

我们想要恢复在左上和右下象限中丢失的白色,以便它们隐藏在其背后的红色旋转框。让我们添加一个第二个网格,这次位于源代码中.blend的顶部。

<div id="design">
  <img src="bird-photo.jpg">
  <div class="rotated-border"></div>
    
  <!-- A second grid  -->
  <!-- This time, we're adding white to the image quandrants where we want to hide the red frame  -->
  <div class="grid">
    <!-- Quadrant 1: Top Left -->
    <div data-white></div>
    <!-- Quadrant 2: Top Right -->
    <div></div>
    <!-- Quadrant 3: Bottom Left -->
    <div></div>
    <!-- Quadrant 4: Bottom Right -->
    <div data-white></div>
  </div>

  <div class="blend">
    <img src="bird-photo.jpg">
    <div class="grid">
      <!-- Quadrant 1: Top Left -->
      <div></div>
      <!-- Quadrant 2: Top Right -->
      <div data-white></div>
      <!-- Quadrant 3: Bottom Left -->
      <div data-white></div>
      <!-- Quadrant 4: Bottom Right -->
      <div></div>
    </div>
  </div>

</div>

结果!

总结一下,浏览器渲染我们演示中的元素如下所示
​​

  1. ​​最底层是鸟类图片(在下图中用最左边的灰色形状表示)
  2. ​​然后是一个旋转的红色框架
  3. ​​在其顶部是一个网格,其中左上和右下角为白色单元格(在最终结果中我们不想看到红色框架的角)
  4. ​​接着是之前鸟类图片的副本和一个带有右上和左下角白色单元格的网格(在最终结果中我们想看到红色框架的角)——两者组合在一起并应用混合模式 multiply。

您可能对我在本文中使用的方法有一些疑问。让我尝试解决这些问题。

使用 CSS 遮罩而不是 CSS 混合模式怎么样?

对于那些熟悉 CSS 遮罩 的人来说——使用mask-imageclip-path——它可以作为混合模式的替代方案。

我更喜欢混合模式,因为它比 遮罩裁剪 具有 更好的浏览器支持。例如,WebKit 浏览器不支持 CSS mask-image属性中的 SVG <mask>引用,并且它们也对clip-path值提供了部分支持,特别是 Safari。

选择混合模式的另一个原因是,可以使用网格创建简单的白色结构,而无需创建图片(无论是 SVG 还是其他格式)。

话虽如此,我完全支持 CSS 混合模式,我已将其用于 击穿文本文本碎片效果……现在还有这个。我几乎完全投入其中。

为什么您对象限使用网格?

当然,演示中所需的白色框可以通过其他方式创建,但网格使事情变得更容易。例如,我们本可以依赖 flexbox。使用适合您的方法。

为什么在网格象限元素上使用 data 属性使其变为白色?

我在编码演示时没有过多考虑就使用了它——我想这样打字更快。后来我考虑将其更改为类,但保留了原样,因为这样 HTML 看起来更整洁……至少对我来说是这样。 :)

multiply 是唯一适用于此示例的混合模式吗?

不是。如果您已经了解混合模式,那么您可能也知道可以使用screendarkenlighten来获得类似的效果。(screenlighten都需要黑色网格单元格而不是白色。)