想把一个小红点绕着按钮转圈圈,或者让提示文字贴在模块边缘跑起来?CSS里有个叫offset的硬核属性,专门干这活儿。它能让元素沿着画好的路线走,比用margin和position瞎调靠谱多了。下面直接开整,看看咋用offset实现丝滑定位。
啥是offset
offset是个简写属性,背后藏了五个小兄弟:offset-path(路线形状)、offset-distance(走多远)、offset-position(起点)、offset-rotate(转不转)、offset-anchor(锚点在哪)。平常说的“沿着盒子边缘放个角标”,全靠offset-path配合参考盒来搞定。参考盒就是元素根据CSS盒模型(content-box、padding-box、border-box)算出来的尺寸范围,相当于给元素画了个“可以贴边行走的跑道”。
手把手搞个边缘贴牌
场景:做个文章卡片,右上角要贴个“新品”小标,并且小标要沿着卡片内边缘滑动。
方案一:用参考盒固定位置
<div class="card">
<div class="badge">新品</div>
<p>这衣服面料绝了,穿上像没穿一样</p>
</div>.card {
position: relative; /* 给offset元素当参照物 */
width: 300px;
padding: 20px;
border: 5px solid #f0f0f0;
background: white;
}
.badge {
offset: padding-box 100% 90deg / right top;
/* 解释:沿padding-box边缘,走完100%距离,旋转90度,锚点定在右上角 */
background: #ff6600;
color: white;
padding: 4px 8px;
border-radius: 12px;
font-size: 12px;
position: absolute; /* 脱离文档流,不挤占文字空间 */
}注意这里.card必须设position: relative或者contain: layout,不然.badge的绝对定位会跑偏到整个页面左上角。offset: padding-box意思是以内边距边界为路径,100%代表走完一整圈(实际上从左上角出发顺时针绕一圈),90deg让小标转正,/ right top把锚点定在小标自身的右上角,这样贴边才严丝合缝。如果发现小标跑到盒子外面去了,八成是忘了设position: absolute或者父级没给定位上下文。
方案二:动态滑入滑出(加动画)
想让小标从右边慢慢滑进来?注册个自定义属性配合过渡就行。
<div class="card2">
<div class="badge2">热卖</div>
<p>鼠标划过来瞅瞅,小标自己会动</p>
</div>@property --dis {
syntax: '<percentage>';
inherits: false;
initial-value: 0%;
}
.card2 {
position: relative;
width: 300px;
padding: 20px;
border: 2px solid #ccc;
}
.badge2 {
offset: padding-box var(--dis) 0deg / left center;
transition: --dis 0.3s ease;
background: #0077ff;
color: white;
padding: 6px 12px;
border-radius: 20px;
position: absolute;
--dis: 2%; /* 初始藏在左边几乎看不见 */
}
.card2:hover .badge2 {
--dis: 15%; /* 鼠标悬停时滑到15%位置,露出来 */
}这里@property注册了--dis变量,告诉浏览器这是个百分比值,可以过渡。offset里的var(--dis)控制沿padding-box走了多远,0deg不旋转,/ left center让锚点在小标自身左边中点,这样移动时不会乱晃。要是动画没反应,检查浏览器是否支持@property(Chrome/Edge 85+,Firefox目前偏科),或者试试直接用offset-distance但没法平滑过渡。
搞定多元素协同跑路
场景:一个图片卡片上,左上角显示日期,右下角显示“限量”,两个小标沿着各自轨道移动。
<div class="product">
<div class="date">2026-04-02</div>
<div class="tag">限量</div>
<img src="shoe.jpg" alt="潮鞋">
</div>.product {
position: relative;
width: 400px;
border: 1px solid #ddd;
padding: 10px;
}
.date {
offset: padding-box 5% 0deg / left top;
background: #333;
color: #fff;
padding: 4px 8px;
font-size: 12px;
position: absolute;
}
.tag {
offset: padding-box 95% 0deg / right bottom;
background: #e53935;
color: white;
padding: 6px 12px;
border-radius: 30px;
font-weight: bold;
position: absolute;
}注意百分比是沿着padding-box周长算的,0%在左上角起点,顺时针增加。5%差不多是左上角偏右一点,95%就接近右下角了。锚点left top让日期块的左上角对齐路径点,right bottom让限量块的右下角对齐路径点,这样两个小标不会互相挡道。如果发现日期块跑到了盒子内部而不是边缘,检查一下.product的padding是否够大,因为路径是基于padding-box的,内边距会把路径往里推。
拿捏文字绕边旋转
offset还能让文字沿着边框转圈,比如把“已售罄”斜着贴在封面右下角。
<div class="cover">
<span class="soldout">Sold Out</span>
<h3>限量球鞋</h3>
</div>.cover {
position: relative;
width: 260px;
height: 260px;
background: #f8f8f8;
border: 3px solid #aaa;
padding: 15px;
}
.soldout {
offset: border-box 85% -35deg / center bottom;
background: #c62828;
color: gold;
padding: 5px 12px;
font-weight: bold;
position: absolute;
font-size: 14px;
}border-box路径沿着边框外边缘走,85%让文字停在右下角附近,-35deg逆时针转35度,看起来像斜着贴上去的。锚点center bottom用文字底部中心对齐路径点,这样贴边时文字不会歪到框外。要是文字旋转后位置不对,试着调整百分比和旋转角度,比如改成92% -40deg微调。另外注意元素宽度用max-content或固定宽,不然旋转后可能超出容器。
