CSS transform scale 缩小字体位置偏移解决方法
场景
为了实现小于 12px 的字体,我们常常会使用 transform: scale(0.8) 去缩小字体, 但是我们在缩小字体的同时会发现字体的位置出现了偏移
解决方法
设置 transform-origin: left top,保证被缩小的文字左上角不动,其位置就不会变化了
.small-text {
/* Chrome 中文最小 12px,直接写 10px 会被强制放大回 12px */
font-size: 10px;
display: inline-block;
transform: scale(0.8);
/* 关键:把缩放基点从中心挪到左上角 */
transform-origin: left top;
}
为什么会偏移
transform-origin 的默认值是 50% 50%,也就是元素的几何中心。缩放是以这个点为不动点做的,所以元素的四条边会同时向中心收缩:左边界右移、上边界下移。视觉上就是文字往右下方缩了进去,看着像「位置偏了」。
改成 left top 之后不动点变成元素左上角,缩放只往右下方向收,左上角的坐标保持不变,文字的起始位置就和缩放前对齐了。如果文字是右对齐的排版,对应地应该用 transform-origin: right top。
transform-origin 接受关键字(left / center / right / top / bottom)、百分比和长度值,两个值分别是水平和垂直方向,第三个可选值是 Z 轴(只对 3D 变换有意义)。left top 等价于 0 0 或 0% 0%。
transform 对行内元素无效
这是配套的一个坑:transform 只作用于「可变换元素」,纯行内元素(如没设置 display 的 <span>)不在其列,写了 scale 完全没反应。所以上面示例里加了 display: inline-block。用 block、flex、table-cell 也行,按布局需要选。
缩放不影响布局尺寸
这是我踩过更隐蔽的一个坑:transform 属于合成阶段的视觉变换,不参与布局计算。也就是说一个 100px 宽的元素 scale(0.8) 之后,视觉上占 80px,但它在文档流里依然占着 100px 的位置,后面的元素不会跟上来。
表现出来就是缩小的文字右侧/下方多出一块空白。要消掉的话有几个办法:
/* 办法一:反向补偿宽高,让盒子的布局尺寸等于视觉尺寸 */
.small-text {
font-size: 10px;
display: inline-block;
transform: scale(0.8);
transform-origin: left top;
/* 原本 100px 的内容,缩放后视觉 80px,用 margin 收掉多余的 20px */
margin-right: -20px;
}
/* 办法二:用 zoom 代替 scale,zoom 会参与布局 */
.small-text {
font-size: 10px;
zoom: 0.8;
}
zoom 曾经是 IE 的私有属性,但现在已经进了 CSS Viewport 规范,Chrome / Safari / Firefox(Firefox 126+)都支持。它和 scale 的核心区别就是会重新触发布局,所以不存在留空白的问题,也不需要 transform-origin。代价是性能不如 transform(后者可以走 GPU 合成,不触发重排),做动画时不要用 zoom。静态的小字号场景用 zoom 反而更省事。
缩小后字体发虚
scale 缩小文字有时会看到字形边缘模糊,因为浏览器是先按 10px 栅格化文字、再对位图做缩放,不是按 8px 重新栅格化。解决思路是反过来做:给一个更大的字号再缩小,让栅格化的原始尺寸更大,缩放后信息量足够。
.small-text {
/* 24px 栅格化再缩到 1/3,等效 8px,字形比 10px→8px 清晰 */
font-size: 24px;
display: inline-block;
transform: scale(0.3333);
transform-origin: left top;
}
其他实现小字号的路子
现在做这件事我未必首选 scale:
- 改用
-apple-system、Helvetica等英文字体:12px下限只对中文字体生效,纯数字和英文用西文字体可以直接写10px。 svg里的<text>:SVG 内部不受最小字号限制,font-size="8"直接生效。-webkit-text-size-adjust: none:这个属性在桌面版 Chrome 上早就失效了(Chrome 27 之后移除了桌面端支持),只在部分移动端浏览器有用,别指望它。
选哪个看场景。做移动端设计稿还原、大量小字号标注时我倾向 zoom,写起来最短且不用管布局补偿;做动画或者需要精确控制变换的场合还是 transform: scale 配 transform-origin。

还没有留言,来发表第一条吧~