如何用CSS Mask实现带顶部撕裂效果的仿纸张样式
解决CSS Mask实现顶部+底部撕裂纸张效果的问题
问题描述
我尝试用CSS Mask实现撕裂/横线纸张效果,目前底部效果正常,但无法给顶部添加撕裂遮罩。以下是我最初的尝试代码:
mask-image: linear-gradient(white, white), url("https://www.isorauschen.at/ripped-paper.svg"), url("https://www.isorauschen.at/ripped-paper-mirrored.svg"); mask-position: bottom, top; mask-repeat: repeat-x, repeat-x; mask-size: 400px auto, 400px auto;
选择CSS Mask是因为它能同时裁剪背景和内部线条,希望找到更优的实现方案。
当前完整代码示例
CSS代码
*, *::after, *::before { box-sizing: border-box; } .lined-paper{ color: black; display: inline-block; line-height: calc(1.5rem + 2px); margin: 30px calc(1em + 5px) 0 calc(1em + 5px); position: relative; width: 400px; } .lined-paper-background{ background: repeating-linear-gradient(#FBFCF8, #FBFCF8 1.5rem, #9198e5 calc(1.5rem + 1px), #9198e5 calc(1.5rem + 2px)); background-color: #FBFCF8; height: 100%; left: 0; mask-composite: exclude; mask-composite: xor; mask-image: linear-gradient(white, white), url("https://www.isorauschen.at/ripped-paper.svg"); mask-position: bottom; mask-repeat: repeat-x; mask-size: 400px auto; position: absolute; top: 0; width: 100%; } .lined-paper-title { align-items: end; background-color: #FBFCF8; display: flex; height: calc((1.5rem + 2px) * 3 - 2px); margin-bottom: calc(1.5rem + 4px); overflow: hidden; padding: calc(1.5rem + 2px) 3em 0 4.5em; position: relative; max-width: 100%; } .lined-paper-title::after, .lined-paper-title::before { border-right: 1px solid pink; content: ""; display: block; height: 100%; left: 0; position: absolute; top: 0; width: 4em; } .lined-paper-title::before{ border-left: 1px solid pink; border-right: none; left: auto; right: 0; width: 2em; } .lined-paper-title span{ font-size: 1.5em; font-weight: bold; max-height: calc((1.5rem + 2px) * 2 - 2px); } .lined-paper-text { padding: 0 3rem 4rem 4.5rem; position: relative; } .lined-paper .masking-tape::after, .lined-paper .masking-tape::before{ background: rgba(255, 255, 245, 0.6); box-shadow: 0 1px 3px rgba(0, 0, 0, 0.4); content: ""; display: block; height: 30px; margin: auto; position: absolute; width: 100px; z-index: 3; } .lined-paper .masking-tape::before{ left: -1em; top: calc(-1em - 5px); transform: rotate(-9deg); } .lined-paper .masking-tape::after{ right: -1em; top: calc(-1em - 2px); transform: rotate(4deg); } .correction-margin-left, .correction-margin-right{ border-right: 1px solid pink; display: block; height: 100%; left: 0; position: absolute; top: 0; width: 4em; } .correction-margin-right{ border-left: 1px solid pink; border-right: none; left: auto; right: 0; width: 2em; z-index: 1; } .correction-margin-left::after, .correction-margin-left::before{ background-color: white; border-radius: 50%; box-shadow: 0 0 3px rgba(0, 0, 0, 0.5) inset; content: ""; display: block; height: 20px; left: 50%; position: absolute; top: 20%; transform: translateX(-50%); width: 20px; } .correction-margin-left::before{ bottom: 20%; top: auto; }
HTML代码
<div class="lined-paper"> <div class="lined-paper-background"> <div class="correction-margin-left"></div> <div class="correction-margin-right"></div> </div> <div class="masking-tape"></div> <div class="lined-paper-title"> <span>Lorem Ipsum Lorem Ipsum</span> </div> <div class="lined-paper-text"> Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. </div> </div>
解决方案
问题根源在于mask系列属性数量不匹配,以及mask-composite的逻辑错误。调整以下两点即可实现顶部+底部撕裂效果:
- 统一mask属性数量:每个
mask-image必须对应一个mask-position、mask-repeat和mask-size,数量完全一致。 - 修正遮罩复合逻辑:使用
mask-composite: add让多个遮罩叠加生效,避免互相抵消。
修改后的.lined-paper-background样式:
.lined-paper-background{ background: repeating-linear-gradient(#FBFCF8, #FBFCF8 1.5rem, #9198e5 calc(1.5rem + 1px), #9198e5 calc(1.5rem + 2px)); background-color: #FBFCF8; height: 100%; left: 0; mask-composite: add; mask-image: linear-gradient(white, white), url("https://www.isorauschen.at/ripped-paper.svg"), url("https://www.isorauschen.at/ripped-paper-mirrored.svg"); mask-position: center, bottom, top; mask-repeat: no-repeat, repeat-x, repeat-x; mask-size: 100% 100%, 400px auto, 400px auto; position: absolute; top: 0; width: 100%; }
关键说明
mask-composite: add:让所有遮罩区域叠加显示,不会互相抵消,这是顶部撕裂效果显示的核心。- 三个
mask-image分别对应:全屏白色渐变(保留主体内容)、底部撕裂图、顶部撕裂图,每个都匹配对应的位置和重复规则。 mask-repeat设置:全屏渐变不重复,撕裂图横向重复铺满容器宽度。
修改后即可同时实现顶部和底部的纸张撕裂效果,且保留CSS Mask能同时裁剪背景和内部元素的优势。
内容的提问来源于stack exchange,提问作者Alexander Galler
相关产品推荐
相关产品推荐

