1.写在前面

两个多周的时间没有写文章了,手好痒好痒,趁着公司在装修,从上周末到本周都在家办公,同时公司的项目并不紧急,于是抽着时间梳理了一下CSS中关于行高line-height的理解,今天发布出来,大家准备好了吗?

2.基本概念

2.1行高的定义与图解

行高,顾名思义指的就是一行文字的高度。按照定义来解释,就是两行文字之间基线之间的距离。那么问题来了,什么是基线呢?大家回想下我们刚开始学习汉语拼音的时候,使用四线格本子的四条线,其中倒数第二条线就是基线,如果你说,抱歉,我已经全部还给老师了,没有任何印象。呵呵,别急呢,我已经给大家准备好了,请看下面的这副图,其中,a、c、e、x、z等字母的底边线(倒数第二根线)就是我们说的基线。

了解完基线的定义后,我们接着来聊行高line-height。上面我们说过,行高就是两条基线的之间的距离,如下图所示。

大家是不是已经了,大家耐着性子仔细看下,其实挺好理解的:

  • 两条红线之间的距离就是行高(line-height)
  • 上一行的底线和下一行的顶线之间的距离就是行距,业界的共识是:行距=行高-em-box(暂时理解为font-size的大小),因此,用CSS语言来解释行距就是: 行距=line-height-font-size。
  • 同一行顶线和底线之间的距离就是font-size
  • 行距的一半就是半行距

结合上面图和文字描述,其实可以很容易搞清楚行高、行距、半行距、font-size的意思。大家一定要弄清楚这些定义,因为,下文中的内容和这些定义有关。

2.2 内容区、行内框、行框、包含框

所谓一图胜千言:

内容区:内容区域可以近似理解为FireFox/IE浏览器下文本选中带背景的区域,在上图中,深灰色背景区域就是内容区域。

行内框:每一个行内元素都会生成一个行内框,高度等于font-size,当我们设置line-height的时候,行内框的高度保持不变,改变的是行距的高度。

行框:指本行的一个虚拟的矩形框,由本行中的行内框组成。当有多行内容的时候,每一行都有自己的的一个行框。

包含框: 包裹着上述三种box的box,晕了,直接看图吧,上面黄颜色的框就是包含框。

3.深入理解line-height

3.1 line-height的各类属性值

line-height的默认值是normal,同时还支持数值、百分比值、长度值、继承。请看下面的表格:

描述
normal 默认。设置合理的行间距。
number 设置数字,此数字会与当前的字体尺寸相乘来设置行间距,即number为当前font-size的倍数。
length 设置固定的行间距。
% 基于当前字体尺寸的百分比行间距。
inherit 规定应该从父元素继承 line-height 属性的值。
  • normal

大家在使用line-height的时候,设置为该值很少,为什么呢?因为normal是一个与font-family有着密切联系的变量值。例如:

div{
line-height: normal;
font-family: 'microsoft yahei';
}

div{
line-height: normal;
font-family: 'simsun';
}

这两段代码在不同浏览器中测试数据如下:

字体 Chrome Firefox IE
微软雅黑 1.32 1.321 1.32
宋体 1.141 1.142 1.141

从上面的表格中可以看到,指定字体后,在不同浏览器中line-height的解析值基本是一样的。然而,不同的浏览器使用的默认字体不一样,并且不同的操作系统使用的默认字体也是不一样的。因此,我们在实际开发的时候,都需要对行高line-height进行重置操作。

  • inherit

    字面意思是继承,即继承父元素line-height的值,父元素是多少,当前节点的line-height就是多少,如果当前节点的子节点不设置任何的line-height,子节点的line-height也是这个值。

  • length

    也就是带单位的值,比如line-height: 21pxline-height: 1.5em等。如果当前的font-size为14px,则line-height计算后的值为1.5*14px=21px

  • number

    例如,line-height: 1.5,最终的计算值是和当前的font-size相乘后的值,比如font-size为14px,则line-height计算值是1.5*14px=21px

  • %

    例如,当前font-size为16px,line-height为120%,则计算后的行高为16*120%=19.2px

不知道大家发现没有,line-height:1.5line-height: 1.5em以及line-height: 150%这三种用法计算的结果 是一样的,最终计算的行高都是根据font-size来计算的。是不是它们可以相互替代呢?其实不然,实际上,line-height:1.5和另外两个的继承细节有些区别,我们直接看例子吧。

body{
font-size: 14px;
line-height: 1.5;
}
body{
font-size: 16px;
line-height: 150%;
}
body{
font-size: 14px;
line-height: 1.5em;
}

对于<body>元素而言,上面三种方式计算后的的行高都是21px,但是,如果body下还有子元素,例如:

<body>
<h3>这是标题</h3>
<p>这是内容</p>
</body>
h3, p{
margin: 0;
}
h3{
font-size: 32px;
}
p{
font-size: 20px;
}

最终结果是line-height: 150%line-height: 1.5em的最终表现是两行文字重叠到了一起,如下图:

而设置了line-height:1.5的最终表现是两行文字没有重叠,排版良好,效果如下图:

设置line-height: 150%line-height: 1.5em后,子元素继承的是计算后的值,即21px,而不是继承150%和1.5em,所以<h3><p>的行高都是21px,而<h3>的font-size是32px,则根据上面的公式计算出来的半行距是-5.5px,因此,两行文字发生了重叠。

不同属性下的line-height最终的计算方式比较如下。

设置方式 line-height 计算后的line-height 子元素继承的line-height
inherit 父元素的line-height值 不用计算 父元素的line-height值
length 20px 不用计算 20px
% 150% 自身font-size (14px) * 150% = 21px 继承父元素计算后的line-height值 21px,而不是150%
normal 假如为1.2 自身font-size (16px) * 1.2 = 19.2px 继承1.2,line-height = 自身font-size(32px) * 1.2 = 38.4px
纯数字 1.5 自身font-size (14px) * 1.5 = 21px 继承1.5,line-height = 自身font-size(32px) * 1.5 = 48px

所以,在实际开发中, 我们一般设置行高的值为 `纯数字是最推荐的方式,因为其会随着对应的 font-size 而缩放,排版效果良好。

3.2 line-height的"大值特性"

现在,请大家仔细阅读下面的代码:

<div class="box">
<span>这是内容...</span>
</div>
.box{
line-height: 50px;
}
.box span{
line-height: 10px;
}

.box{
line-height: 10px;
}
.box span{
line-height: 50px;
}

抛出问题:请问div的高度是多少?直接上正确答案:都是50px。请看图

感觉说不通啊,那么请看解释吧。

首先,我们要始终记着,内联元素前面有一个看不见的"幽灵空白节点",因此,上面的html代码可以等价为:

<div class="box">
幽灵空白节点<span>这是内容...</span>
</div>

所以,当.box元素设置line-height:50px的时候,"幽灵空白节点"高度为50px,而当.box元素设置line-height: 20px的时候,span元素的高度变成了50px,而又因为行框盒子是由高度最高的那个内联盒子决定的,所以.box元素的高度永远是最大的那个line-height的原因,根据张鑫旭老师的总结,这可以称为line-height的大值特性,不知道这样解释大家清楚了没有呢?

3.3 line-height与内联元素"垂直居中"

  • 行高让单行文字"垂直居中"

不知道你是否和我一样,在刚开始写CSS的时候,控制单行文字垂直居中的时候,设置line-heightheight的值一样就可以实现文字垂直居中的效果,即:

.title{
height: 50px;
line-height: 50px
}

其实,这里只需要保留line-height这个属性就可以了,完全没有任何必要设置height的大小。

<div style="height: 50px; background-color: #cd0000; color: #fff">
<span style="line-height: 50px">元素元素元素</span>
</div>

因此,流传比较广的"设置line-heightheight的值一样就可以实现文字垂直居中效果", 应该修改为:把line-height设置为您需要的box的大小可以实现单行文字的垂直居中

  • 行高让多行文字“垂直居中”

多行文字垂直居中效果需要借助line-height的好朋友的帮助才能实现,代码如下:

<div class="box">
<div class="content">基于行高是实现的多行文本垂直居中...我发现文字很短,于是随便写了一点文字凑个数..</div>
</div>
.box{
line-height: 120px;
background-color: #cd0000;
color: #fff;
}
.content{
display: inline-block;
line-height: 20px;
margin: 0 20px;
vertical-align: middle;
}

效果图如下所示:

实现的原理如下:

  1. 多行文字使用一个标签包裹,同时设置display: inline-block,保持了内联元素的特性,使元素具有单行效果,该设置使元素形成了一个非常关键的"行框盒子",而每一个行框盒子都会附带一个"幽灵空白节点"(宽度为0,但是表现和普通字符相同)。而我们设置了外层的line-height: 120px,因此,.content内容"幽灵空白节点"的line-height也将是120px;
  2. 内联元素默认是基线对齐的,通过设置vertical-align:middle可以实现我们想要的"垂直居中"效果。

3.4 真的是"垂直居中"吗

不知道大家有没有留意上文中的单行文本和多行文本的垂直居中都加了引号,难道还不是真正的垂直居中?没错,line-height实现的垂直居中效果只是近似的垂直居中。为什么是"近似"?我们拿一个例子说明问题:

<p>微软雅黑</p>
p{
font-size: 80px;
line-height: 120px;
background-color: #cd0000;
color: #fff;
font-family: "Microsoft YaHei";
}

在浏览器中(windows系统)的效果如下:

大家看到没有,这些文字的位置明显偏下。因为,有些字体的位置偏下,比如"微软雅黑",在平时我们使用的过程中,字体大小基本在16~18px之间,虽然下沉,但是也就是1px的偏差,我们的肉眼根本察觉不到。因此,使用line-height实现的"垂直居中"并不是绝对的垂直居中

同理,使用line-heightvertical-align实现的多行文本垂直居中也不是绝对的垂直居中,在上文中多行文本垂直居中的例子中,我们可以明显的看到字体位置偏下。

其实,不居中并不是line-height导致的,而是他的好基友vertical-align造成的,我们会在vertical-align文章中详细阐述,敬请期待。

4. 最后

关于line-height的介绍就到这里了,平时我们应该多思考,多总结,才会有新的体会。以后我的最新文章都会第一时间更新在公众号<前端Talkking>里面,欢迎大家关注。

以上就是本文的全部内容,感谢阅读,如果有表述不正确的地方,欢迎留言指正!

ps:这两天是一年一度的高考,想想自己的高考差不多过去了10年了,而现在自己好像没有什么成就,想想好惭愧,努力吧,少年!!!

参考


$$
遇见了,不妨关注下我的微信公众号「前端Talkking」
$$

【前端Talkking】CSS系列——CSS深入理解之line-height的更多相关文章

  1. 深入理解CSS系列(二):为什么height:100%不生效?

    对于height属性,如果父元素height为auto,只要子元素在文档流中(即position不等于fixed或者absolute),其百分比值完全就被忽略了.这是什么意思呢?首先来看个例子,比如, ...

  2. HTML+CSS系列:CSS选择器(标签、ID、类、通配符、后代、子元素、并集、伪类)

    一.标签选择器 <!DOCTYPE html> <html lang="en"> <head> <meta charset="U ...

  3. 2019前端面试系列——CSS面试题

    盒模型 /* 红色区域的大小是多少?200 - 20*2 - 20*2 = 120 */ .box { width: 200px; height: 200px; padding: 20px; marg ...

  4. 深入理解脚本化CSS系列第六篇——脚本化伪元素的6种方法

    × 目录 [1]动态样式 [2]CSS类[3]setAttribute()[4]CSSRule对象添加[5]空样式覆盖[6]CSSRule对象删除 前面的话 我们可以通过计算样式来读取伪元素的样式信息 ...

  5. (原)前端知识杂烩(css系列)

    更新于 20160217 1. css hack .pad{ padding:17px 0 0 17px; /* 普通写法 */ *padding:17px 0 0 17px; /* *为IE7 *+ ...

  6. 前端逼死强迫症系列之css

    一.编写css样式 1.ID选择器 由于ID唯一,所以也是写多遍. <head> <style> #i1{ background-color: #2459a2; height: ...

  7. Web 前端之HTML和CSS

    Web 前端之HTML和CSS HTML被称为超文本标记语言(Hyper Text Markup Language),它不是一种编程语言,而是一种标记语言,标记语言是一套标记标签,HTML使用标记标签 ...

  8. WEB前端性能优化:HTML,CSS,JS和服务器端优化

    对前端开发工程师来说,前端性能优化的重要性是不言而喻的,最为大家所知的是YSLOW的23条优化规则,在我的理解中,性能优化不纯粹是指用户访问网站的速度,也包括开发的效率,这里我总结下我理解中的WEB前 ...

  9. web前端面试试题总结---css篇

    CSS 介绍一下标准的CSS的盒子模型?低版本IE的盒子模型有什么不同的? (1)有两种, IE 盒子模型.W3C 盒子模型: (2)盒模型: 内容(content).填充(padding).边界(m ...

随机推荐

  1. MM32F0020 UART1中断接收

    目录: 1.MM32F0020简介 2.初始化MM32F0020 UART1和NVIC中断 3.编写MM32F0020 UART1中断接收函数 4.编写MM32F0020 UART1发送字节和ASCI ...

  2. Spring入门笔记简要

    总览:https://www.processon.com/view/link/605b14ab5653bb2225e6b0c5 一.Spring 1.概述 1.spring框架简介 ​ 为简化企业级开 ...

  3. laravel7 h-ui点改

    html: <td> @if($item->fang_status == 0) <span onclick="changeFangStatus(this,{{$ite ...

  4. think php 验证器及验证场景的使用

    1:在需要验证的模块名下建一个validate文件夹 ,文件夹下建议个验证的 名称   Goods.php 2:打开Goods.php <?php namespace app\api\valid ...

  5. PHP message:filesize(): stat failed for 错误

    PHP message:filesize(): stat failed for 错误 message:filesize(): stat failed for F:s2017\SinaImgUpload ...

  6. CSAPP CH7链接的应用:静动态库制作与神奇的库打桩机制

    目录 创建静态库 创建动态库 库打桩机制 编译时打桩: 链接时打桩 运行时打桩 运行时打桩的printf与malloc循环调用debug 使用LD_PRELOAD对任意可执行程序调用运行时打桩 总结 ...

  7. 常见的Socket网络异常场景分析

    原创:打码日记(微信公众号ID:codelogs),欢迎分享,转载请保留出处. 简介 在目前微服务的背景下,网络异常越来越常见了,而有一些网络异常非常模糊,理解什么情况下会导致什么异常,还是有一定难度 ...

  8. ENVI提取水系并进行生态敏感性分析

    4 具体步骤 4.1 DEM数据拼接 (1)打开ENVI软件,选择[File][Open],添加文件夹DEM数据中的影像,操作如图4.1.1所示,结果如图4.1.2. 图4.1.1 添加DEM数据影像 ...

  9. 【面经】MyBatis常见面试问题

    1.什么是 MyBatis? 答:MyBatis 是一个可以自定义 SQL.存储过程和高级映射的持久层框架. 2.讲下 MyBatis 的缓存 答:MyBatis 的缓存分为一级缓存和二级缓存,一级缓 ...

  10. 在Windows 10 上安装使用binwalk

    Windows 10 推出的WSL 功能可以协助我们直接使用binwalk 分析Windows 内的文件 文章更新时间:2020年3月11日 一.WSL 准备 1.打开控制面板→程序和功能→启动或关闭 ...