在这篇文章中,我们将使用 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-columns
和grid-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>
结果!

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

您可能对我在本文中使用的方法有一些疑问。让我尝试解决这些问题。
使用 CSS 遮罩而不是 CSS 混合模式怎么样?
对于那些熟悉 CSS 遮罩 的人来说——使用mask-image
或clip-path
——它可以作为混合模式的替代方案。
我更喜欢混合模式,因为它比 遮罩 和 裁剪 具有 更好的浏览器支持。例如,WebKit 浏览器不支持 CSS mask-image
属性中的 SVG <mask>
引用,并且它们也对clip-path
值提供了部分支持,特别是 Safari。
选择混合模式的另一个原因是,可以使用网格创建简单的白色结构,而无需创建图片(无论是 SVG 还是其他格式)。
话虽如此,我完全支持 CSS 混合模式,我已将其用于 击穿文本、文本碎片效果……现在还有这个。我几乎完全投入其中。
为什么您对象限使用网格?
当然,演示中所需的白色框可以通过其他方式创建,但网格使事情变得更容易。例如,我们本可以依赖 flexbox。使用适合您的方法。
为什么在网格象限元素上使用 data 属性使其变为白色?
我在编码演示时没有过多考虑就使用了它——我想这样打字更快。后来我考虑将其更改为类,但保留了原样,因为这样 HTML 看起来更整洁……至少对我来说是这样。 :)
multiply 是唯一适用于此示例的混合模式吗?
不是。如果您已经了解混合模式,那么您可能也知道可以使用screen
、darken
或lighten
来获得类似的效果。(screen
和lighten
都需要黑色网格单元格而不是白色。)
多么有趣的设计!这里还有另一种方法:https://codepen.io/SirMorland/pen/KKKzoEm。我只使用了一张图片,但为上层和下层设置了单独的边框。它可能不适用于所有用例,但我认为它可能更有效率,因为它不使用混合模式。
当我看到标题上的图片时,我的第一个想法。
这是一个极好的解决方案,很棒的工作
在简单的情况下,您可以使用一个
div
,但很难对整个组件进行z-index
定位我首选的解决方案。非常感谢!
我只是稍微调整了一下,以恢复 img 标签,并且只有一种思考角度旋转的方式。对我来说似乎更容易。^^
此外,z-index 似乎在跨浏览器中是多余的……在不使用 z-index 时,有人看到问题了吗?
不错的效果,好文章! :)
您可能在这里过度复杂化了——至少对于这个特定的效果来说,我认为是这样。
尽管您的方法可能会解决其他(更复杂)的问题,但您只需利用一些伪元素:https://codepen.io/dannievinther/pen/jOOqKmJ
我认为标记和 css 更简洁了 :)
感谢您的文章——它很有见地
我同意这更简洁,但是如果您开始添加阴影(如这里的示例),伪元素将无法工作。
这真的很聪明。感谢分享.. :)
好文章!MS Edge 在使用属性选择器时存在一些问题。这些问题在 2017 年 8 月被报告,但截至今天,这些问题仍然存在。
在本例中,我认为您不会看到任何问题。我注意到在使用数据属性使用 JS 针对元素时出现问题。
https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/13348719/
这是一个非常有见地的教程!我一定会将此方法保存到未来的项目中。
我自己在 CodePen 中尝试了一下,发现边框可以旋转到 +/-64 度而没有任何问题。但是,将其推到 65 度或更高,边框将与具有 data-white 属性的辅助网格象限相交,从而使其明显地覆盖了所有内容。
为什么不直接在Photoshop里做呢?
任何东西都可以这么说。这样做并没有错,或者用代码写出来,尽管代码可能更有效率。此外,能够做到这一点非常酷而且很有趣。
太棒了,但我仍然不明白..你能提供一些基础知识吗,以及我可以下载的视频。我刚开始学习HTML。
太酷了
我太喜欢你的网站了!暂时就这些了
不错的文章!我在一个更“简单”(但不同的)版本中分叉了你的笔:https://codepen.io/guizmath/pen/mddRLvg
非常酷的效果。我正在努力理解混合模式的使用,但这是一件好事 :)
我的想法是用一些z-index技巧来使用伪元素:https://codepen.io/mrwweb/pen/dyyvMRL?editors=1100
我真的很想看看我是否可以使用element() 函数,但由于某种原因我无法使其工作(在 Firefox 中添加前缀)。以后再回来看看。
感谢您告诉我一个我之前不知道的不错的 CSS 属性,但是…为什么我们要如此复杂化事情?我个人会通过仅仅使用象限的绝对定位和 background-position 属性 + z-index 来实现此效果。
我创建了一个新的示例,保留了图像元素以及相关的语义和可访问性属性,使用自定义属性和伪元素。