这个效果就像是文件夹里塞了张纸,纸边儿露出一小截;又或者钱包里插着信用卡,卡片冒个尖儿出来方便瞅一眼是哪张卡。在CSS里,这玩意儿叫“slit”(缝隙效果)。说白了,就是制造一个假开口,让底下的元素从开口处探出个头来,看着贼自然。
缝隙效果靠两个东西配合:一个假阴影(不是
box-shadow那种),一个遮挡层。阴影用模糊的渐变矩形做出立体感,遮挡层盖住阴影的一半,再往左一挪,视觉上就形成了开口。整个过程可以用Grid或Flexbox来堆叠元素,代码不复杂,但细节拿捏到位才像那么回事儿。
阴影咋造
一般新手可能直接甩个box-shadow完事,但那玩意儿太死板。真正能动态适配、还能做动画的阴影,得自己动手搓出来。
搞一个细长竖条矩形,背景弄成渐变:中间深、两边浅。然后给它加一层blur()滤镜,模糊后中间区域自然就暗下去,边缘过渡柔和,看起来就像真实的缝隙暗影。
<div class="slit-shadow"></div>.slit-shadow {
width: 60px;
height: 100%;
background: linear-gradient(90deg, rgba(0,0,0,0) 0%, rgba(0,0,0,0.6) 50%, rgba(0,0,0,0) 100%);
filter: blur(8px);
}实际操作时,这个阴影的宽度得看具体设计,一般20-80px就够。blur()值太大阴影会糊成一团,太小又显得生硬,建议从6px开始调。而且这个阴影元素必须单独占一层,方便后面被遮盖。
遮盖设计
遮盖就是盖住阴影左边那一半的矩形,颜色必须跟整个容器的背景色一模一样。比如页面背景是#f5f5f5,那遮盖背景也得是#f5f5f5,这样盖上去才像是一体。
<div class="slit-cover"></div>.slit-cover {
width: 50%;
height: 100%;
background: inherit; /* 继承父级背景色,省事 */
}这里有个坑:background: inherit得保证父元素背景是纯色且显式定义过。如果父级背景是图片或者渐变,那遮盖就得用mask或者backdrop-filter来抠,操作更骚但原理一样。
叠放对齐
三个东西要叠在一块:最底下是真正的图片或内容,中间是阴影,最上面是遮盖。用CSS Grid一把梭,把所有子元素塞到同一个网格单元格里。
<main>
<img src="card.jpg" alt="卡片图片">
<div class="slit-shadow"></div>
<div class="slit-cover"></div>
</main>main {
display: grid;
place-items: center;
background: #fff; /* 背景色,遮盖会继承这个 */
}
main > * {
grid-area: 1 / 1; /* 全部堆在同一个格子 */
}现在所有元素完全重叠。接下来把遮盖往左平移,露出底下阴影和图片的一部分。
.slit-cover {
width: 50%;
transform: translateX(calc(-50% - 25px));
}这里25px就是阴影宽度的一半,平移量要刚好让阴影边缘露出来。平移太多会露出遮盖的边界穿帮,太少阴影不明显。建议用calc(-50% - 阴影宽度的一半)这个公式。
图片露头
图片或者其他要“露一截”的内容,本身就在最底层,不用额外处理。但是为了让露出的部分正好在缝隙中间,可以微调图片的位置,或者给阴影换个方向。
比如想让卡片从右边露出来,那就把阴影放到右侧,遮盖也改成从右边盖过来。代码稍微改改:
.slit-cover--right {
width: 50%;
transform: translateX(calc(50% + 25px));
}
.slit-shadow--right {
/* 阴影放在右侧 */
margin-left: auto;
}这波操作直接拿捏了缝隙效果的核心:阴影+遮盖+偏移,三件套缺一不可。
另一种路子:Flexbox平替
Grid能叠元素,Flexbox也能凑合干,不过得用负margin或者绝对定位。更直接的法子是直接用position: relative和position: absolute。
<div style="position: relative; background: #fff;">
<img src="card.jpg" style="display: block;">
<div class="shadow" style="position: absolute; top:0; left:0; width:60px; height:100%; ..."></div>
<div class="cover" style="position: absolute; top:0; left:0; width:50%; height:100%; background: inherit; transform: translateX(calc(-50% - 25px));"></div>
</div>绝对定位的坑在于父级必须有position: relative,而且阴影和遮盖的层级得用z-index手动调。哪个在上哪个在下?遮盖必须比阴影高,阴影比图片高。
| 方案 | 优点 | 缺点 |
|---|---|---|
| Grid叠层 | 代码干净,不用管层级 | 需要理解grid-area |
| 绝对定位 | 兼容性拉满 | z-index容易乱 |
玩出花活:曲线阴影和彩色缝隙
上面那个是直来直去的缝隙,要是想整个弯的阴影,比如像翻开书页那种弧线,可以把阴影的背景渐变改成径向渐变,或者用clip-path切个弧形。
.slit-shadow-curve {
background: radial-gradient(ellipse at center, rgba(0,0,0,0.5) 0%, rgba(0,0,0,0) 70%);
filter: blur(12px);
width: 80px;
}遮盖也得跟着切弧形,不然直边盖弧边会露馅。用clip-path: polygon()或者border-radius都能整活。注意阴影和遮盖的形状必须完全匹配,不然穿帮就是分分钟的事。
还有个骚操作:不用单独元素做阴影,直接用::before伪元素造阴影,::after做遮盖。这样HTML结构更干净,但伪元素没法同时继承父级背景色,需要手动指定。
.slit-container::before {
content: '';
position: absolute;
left: 0;
width: 60px;
height: 100%;
background: linear-gradient(...);
filter: blur(8px);
}
.slit-container::after {
content: '';
position: absolute;
left: 0;
width: 50%;
height: 100%;
background: #fff; /* 必须写死背景色 */
transform: translateX(calc(-50% - 25px));
}这种写法适合背景色固定不变的场景,如果背景是动态的或者主题可换,那还是用独立元素加background: inherit更稳。
