CSS 渲染机制 · 票券缺口
9×16px
缺口尺寸
8px
圆角半径
1px
边框对缝
2
伪元素
0
额外 DOM
票券上那种"被咬掉一块"的缺口,页面上其实没有半张图,DOM 也没被真剪过。它靠的是两件小事:层叠顺序和 1px 对齐。
说人话:缺口不是剪出来的,是盖出来的。放一块和背景同色的矩形,压在卡片边框上,那一小段边框就被"擦"掉了。
Ticket Cutout
示例票券卡片
1px 边框 + 9px × 16px 同色伪元素遮罩
当前 overflow: visible —— 伪元素延伸到 Border Box 外缘,同色覆盖形成干净的半圆缺口。
缺口是盖出来的
::before / ::after 是 CSS 2.1 的生成内容,在布局树里是宿主的子节点,绘制天然晚于宿主自己的背景和边框。所以给卡片 position: relative,再让伪元素绝对定位、涂成父容器底色,它就会盖住那一小段边框——看起来像凹进去一块。
记住一句:这是 cover,不是 mask。缺口处没透明,只是被一块同色矩形挡住。换句话说,你看到的"缺口",本质是一块色块,只是它和背景长成一个颜色,骗过了眼睛。
三个小坑
- 1
border-left: none比border-left-width: 0干净。规范说border-style: none时,即使宽度不为 0,Paint 阶段也不画任何像素。 - 2
overflow: hidden不能留。它建立裁切上下文,把子元素(含伪元素)限制在 Padding Box 内。卡片有 1px 边框,伪元素得伸到 Border Box 外缘才盖得住它;一开裁切,那 1px 被切掉,缺口两边会残留竖线。 - 3同色要跟父容器一致,不是跟卡片一致。卡片白、底灰,伪元素就得涂灰,涂错一秒穿帮。
所以这效果天生和 overflow: hidden 互斥。要缺口,就得放弃裁切,改成手动对齐 border-radius。
像素账
.ticket-card {
position: relative;
border: 1px solid #3b82f6;
border-radius: 12px;
}
.ticket-card::before {
content: '';
position: absolute;
top: 50%;
left: -1px;
width: 9px; /* 8px 半径 + 1px 边框 */
height: 16px; /* 2 × 8px */
margin-top: -8px;
border-radius: 0 8px 8px 0;
background: #f2f5f7;
}三笔账背下来就行:
- 宽度 = 半径 + 1px,多出的 1px 专门用来盖卡片边框;
- 高度 = 2 × 半径;
- 起点 = -1px,让左边缘贴住 Border Box 外缘。
border-radius: 0 8px 8px 0 让右上、右下各取 8px,加起来正好等于 16px 高,两段圆弧在中点相切,自然长出标准半圆,不用写任何路径。要左右两个缺口,就再写一个 ::after,半径镜像成 8px 0 0 8px,left: -1px 换成 right: -1px。
十来行 CSS 而已。难的不是代码,是背后的规范:生成内容的绘制顺序、border-style 的解析优先级、裁切上下文的边界。读完就明白,这效果一点不玄学。
本文属于 AI 实用主义流派 的第 52 篇肉身实战。
发表评论
分享你的想法和反馈