CSS offset属性咋玩,怎么让元素沿着路径丝滑移动?

2,971字
13–19 分钟
in

想把一个小红点绕着按钮转圈圈,或者让提示文字贴在模块边缘跑起来?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或固定宽,不然旋转后可能超出容器。