height、line-height、font-size相同字体遮挡问题

核心一句话

即使 height = line-height = font-size,字体本身自带上下边距(字体的 ascent / descent,上升区、下降区),不是文字可视内容刚好塞满 font-size,所以依然可能顶部被切。

很多人误区:font-size = 文字图案高度。❌

font-size 只是字体设计的em正方形,不是字的可见笔画高度。

  1. 字体内部结构(根源)

每个字体文件内置:

• ascent:基线往上的最大高度

• descent:基线往下的最大高度

ascent + descent 经常 大于 font-size!

浏览器计算行盒默认逻辑(line-height:normal 时)就依赖这两个值。

哪怕你手动设置 line-height: 20px; font-size:20px; height:20px

• 行盒是20px

• 但字体字形的可视笔画顶部,会超出这个20px行盒的上边界

• 再加上容器高度也是20px → 顶部笔画就被裁掉(尤其带上升笔画:如"天、国"的顶部横,英文b/d/h)

不同字体差别巨大:思源黑体、微软雅黑、苹方的 ascent 值不一样,有的字体留白在上,有的在下。

  1. 基线居中的问题(单行文字)

line-height 的计算:

行高 = 上下半行距 + font-size

半行距 = (line-height - font-size) / 2

当 line-height === font-size → 半行距 = 0。

行盒高度等于font-size,没有额外上下留白。

但字体的可视图形,本身就会侵入到行盒边界外面:

• 部分字体的 ascent 很大,文字笔画顶到行盒上边甚至超出

• 容器高度等于行盒高度,overflow:hidden 时直接切掉超出的顶部

  1. 为什么有的字体没事、有的会挡?

举直观例子:

• 微软雅黑:ascent 偏大,容易顶部裁切

• 思源黑体常规:相对克制,不容易裁

这就是同一个css,换个字体就出现文字被切的经典坑!

  1. 还有一个叠加坑:box-sizing + 边框/padding

.box{

font-size:20px;

line-height:20px;

height:20px;

border:1px solid #000;

}

默认 content-box:height 是内容区20px,加上上下边框2px,内容区域被压缩,直接裁切文字。

很多人忘记边框,导致内容高度变小,文字顶部被挡。

  1. 解决方案(常用)

  2. 行高稍微大于字体大小,预留安全边距

    font-size:20px;

    line-height: 24px; /* 留一点点上下留白 */

    height:24px;

  3. 用 padding 代替固定 height 做垂直居中(推荐单行文字)

    font-size:20px;

    line-height:1.2;

    padding:4px 0;

    height:auto;

  4. 或者 vertical-align 调整基线,但是治标不治本

  5. 现代方案:flex 居中,摆脱 line-height 坑

    .box{

    display:flex;

    align-items:center;

    height:20px;

    }

    总结

height = line-height = font-size 只是css盒子层面相等;字体本身的字形绘制区域不一定被限制在font-size方框内,不同字体的 ascent 不同,部分字体顶部笔画会超出,overflow:hidden就会出现顶部遮挡。

一、基线 baseline

基线是字体排版的虚拟参考线,不是下划线。英文小写字母 x 的底部就是基线。

b ↑ ascent(上升区:基线往上)

o

x --------- baseline【基线】

g ↓ descent(下降区:基线往下,g/j/q 的尾巴)

• ascent:基线向上,字体能到达的最高点

• descent:基线向下,字体能到达的最低点

字体文件内置这两个值,和 CSS 的 font-size 相关,但不等于 font-size

重点:font-size 是字体的 EM 正方形尺寸,只是设计网格,不是字形可视高度。

很多字体 ascent + descent > font-size → 字形会伸出 EM 框外面,这就是裁切元凶。

二、line-height: normal 默认值

line-height: normal 不是固定数字!

计算公式:

line-height:normal ≈ font-size × 字体内置比例系数

系数写在字体文件里,不同字体不一样:

• 微软雅黑:系数大约 1.2

• 思源黑体:大约 1.1~1.2

• 宋体、一些英文字体可能 1.0~1.3

✅ 所以:

font-size:20px;

line-height:normal;

行高 ≈ 20px * 1.2 = 24px,不是20px!

误区:很多人以为 normal = 1,❌。line-height:1 是强制行高等于font-size,和normal完全两码事。

line-height:1 会把行盒压缩到EM框大小,最容易触发文字顶部/底部裁切。

行盒计算公式(line-height 固定数值时)

半行距 = (line-height − font-size) / 2

半行距会平分加到 font-size 的上下,构成行盒。

注意:半行距是加到字体EM框上下,不是加到字形上下。

当 line-height = font-size,半行距=0,没有额外留白。此时字体本身的 ascent 一旦超出 EM 框,直接溢出。

三、如何防止文字被遮挡(方案按推荐优先级排序)

✅ 方案1:抛弃 height + line-height 居中,改用 flex(最稳,推荐)

完全绕开基线、ascent、行高各种坑

.box {

height: 32px;

display: flex;

align-items: center;

overflow: visible; /* 不要hidden! */

}

flex 的 align-items:center 不是基于基线排版,不会被字体ascent差异影响。

✅ 方案2:不写固定height,用padding撑开(单行/多行都友好)

.box {

font-size:20px;

line-height:1.4;

padding:4px 8px;

height:auto; /* 高度自动由文字+padding决定 */

}

适合按钮、标签,完全杜绝裁切。

✅ 方案3:坚持使用固定height + line-height(老项目兼容)

不要 line-height = font-size!

预留安全余量:

.box{

font-size:20px;

line-height: 24px; /* 比font-size大一点,预留字体ascent溢出空间 /
height:24px;
overflow:visible; /
尽量不要overflow:hidden,万不得已才用 */

}

经验值:中文界面 line-height 一般取 1.2 ~ 1.4,避开 1.0。

✅ 方案4:必须 overflow:hidden 的场景(如裁切容器需求)

• line-height 适当放大,给上下预留安全边距

• 尽量测试目标字体(微软雅黑最容易顶部裁字)

• 可以微调 vertical-align 做临时偏移,但治标不治本

❌ 不推荐写法(极易裁切)

.box{

font-size:20px;

line-height:20px;

height:20px;

overflow:hidden;

}

line-height:20px 等价系数1,半行距0,只要字体ascent超出EM框,顶部直接被切掉。

四、一句话总结

  1. 基线:小写x底部,ascent向上、descent向下,字体字形本身可能超出font-size方框。

  2. line-height:normal:由字体内置系数 × font-size,不同字体不一样,不等于1。line-height:1 才是行高=font-size,风险最大。

  3. 防遮挡最优解:flex居中 / padding自适应高度;迫不得已固定高度时,line-height > font-size,避免 line-height=font-size + overflow:hidden

需要我写一段完整demo,对比 line-height:1 和 line-height:normal 同时看裁切效果吗?

相关推荐
字节渡客36 分钟前
接口参数偶尔丢失、乱码、解析失败,不是前端传参问题
前端
夏幻灵37 分钟前
前端八股:JavaScript 深拷贝详解:实现方式、递归原理与循环引用
开发语言·前端·javascript
humors22140 分钟前
AI模型的可为和不可为
人工智能·gpt·ai·大模型·豆包·deepseek
@#¥&~是乱码鱼啦44 分钟前
ArkWeb开发手记01|Web 组件 H5 加载与生命周期管理
前端
suaizai_44 分钟前
ComputerUse:让AI真正操控桌面系统
java·前端·javascript
CodeSheep1 小时前
朋友面试谈薪报价2w,HR非得压到1.9,还反问他:你就差这1000块钱?后来背调时问了他前同事十几个问题,对方最后直接挂了
前端·后端·程序员
IMPYLH1 小时前
HTML 的 <track> 元素
前端·html
涛涛ing1 小时前
35个组件,把GPU特效直接跑在真实DOM上:Canvas UI正在重新定义Web视觉
前端
乘风gg1 小时前
Spec Kit vs OpenSpec vs Superpowers:8 个 Skill 的落地实录与工程方法论
前端·ai编程·claude