如何在CSS中实现卡片元素上的Hole Punch(打孔)效果?
实现Card上的CSS打孔(Hole Punch)效果
我想在CSS里实现打孔效果,类似裁剪但能穿透上层元素。当背景铺满整个视口时能伪造出这个效果,但背景放在卡片(card)元素上时,一直没找到可行方案。
期望实现的效果示例
html { height: 100%; --backround: linear-gradient(15deg, red, blue); } body { background-image: var(--backround); background-repeat: no-repeat; background-size: contain; background-attachment: fixed; } article { display: block; background-color: white; width: fit-content; height: 505px; margin: auto; } h1 { display: block; box-sizing: content-box; position: static; background: var(--backround) fixed; color: transparent; text-transform: capitalize; width: 100%; background-clip: text; font-weight: bolder; }
<body> <main> <div class="card"> <article> <h1>01AAAAAAAAAAAAAAAAAAAAAAAAAA</h1> <h1>02AAAAAAAAAAAAAAAAAAAAAAAAAA</h1> <h1>03AAAAAAAAAAAAAAAAAAAAAAAAAA</h1> <h1>04AAAAAAAAAAAAAAAAAAAAAAAAAA</h1> <h1>05AAAAAAAAAAAAAAAAAAAAAAAAAA</h1> <h1>06AAAAAAAAAAAAAAAAAAAAAAAAAA</h1> <h1>07AAAAAAAAAAAAAAAAAAAAAAAAAA</h1> <h1>08AAAAAAAAAAAAAAAAAAAAAAAAAA</h1> <h1>09AAAAAAAAAAAAAAAAAAAAAAAAAA</h1> <h1>10AAAAAAAAAAAAAAAAAAAAAAAAAA</h1> <h1>11AAAAAAAAAAAAAAAAAAAAAAAAAA</h1> <h1>12AAAAAAAAAAAAAAAAAAAAAAAAAA</h1> </article> </div> </main> </body>
尝试后的问题效果
但在card上尝试时,只能得到如下效果,文本颜色和卡片背景明显错位,调整后错位更严重:
html { height: 100%; --backround: linear-gradient(15deg, red, blue); } .card { display: block; padding: 5em 10em; margin: 0 auto; width: fit-content; background-image: var(--backround); } article { display: block; background-color: white; width: fit-content; height: 505px; margin: auto; } h1 { display: block; box-sizing: content-box; position: static; background: var(--backround) fixed; color: transparent; background-clip: text; font-weight: bolder; }
<main> <div class="card"> <article> <h1>01AAAAAAAAAAAAAAAAAAAAAAAAAA</h1> <h1>02AAAAAAAAAAAAAAAAAAAAAAAAAA</h1> <h1>03AAAAAAAAAAAAAAAAAAAAAAAAAA</h1> <h1>04AAAAAAAAAAAAAAAAAAAAAAAAAA</h1> <h1>05AAAAAAAAAAAAAAAAAAAAAAAAAA</h1> <h1>06AAAAAAAAAAAAAAAAAAAAAAAAAA</h1> <h1>07AAAAAAAAAAAAAAAAAAAAAAAAAA</h1> <h1>08AAAAAAAAAAAAAAAAAAAAAAAAAA</h1> <h1>09AAAAAAAAAAAAAAAAAAAAAAAAAA</h1> <h1>10AAAAAAAAAAAAAAAAAAAAAAAAAA</h1> <h1>11AAAAAAAAAAAAAAAAAAAAAAAAAA</h1> <h1>12AAAAAAAAAAAAAAAAAAAAAAAAAA</h1> </article> </div> </main>
问题在于文本的fixed背景基于视口缩放,而非card容器。
解决方案
核心思路是让文本的背景与card的背景使用相同的坐标系统,去掉fixed定位,通过调整background-position抵消容器的内边距偏移,实现背景对齐:
修改后的CSS代码
html { height: 100%; --backround: linear-gradient(15deg, red, blue); } .card { display: block; padding: 5em 10em; margin: 0 auto; width: fit-content; background-image: var(--backround); background-size: cover; /* 确保背景铺满card容器 */ } article { display: block; background-color: white; width: fit-content; height: 505px; margin: auto; } h1 { display: block; box-sizing: content-box; background: var(--backround); /* 移除fixed,使用默认的scroll定位 */ color: transparent; background-clip: text; font-weight: bolder; background-size: cover; /* 和card背景保持一致的尺寸 */ /* 抵消card的padding偏移,让文本背景与card背景完全对齐 */ background-position: -10em -5em; }
关键说明
- 移除
h1的background-attachment: fixed,让背景跟随容器滚动,而非绑定视口。 - 给
.card和h1添加background-size: cover,保证渐变背景的尺寸一致。 - 通过
background-position: -10em -5em抵消.card的padding:5em 10em,让文本的渐变背景与card的渐变背景位置完全重合,实现“穿透”白色article的打孔效果。
如果后续调整card的padding值,只需要同步修改h1的background-position数值即可(水平偏移为负的左右padding,垂直偏移为负的上下padding)。
内容的提问来源于stack exchange,提问作者tbeest
相关产品推荐
相关产品推荐

