Web 排版中的 vertical-align

如果你对 Web 排版中的 vertical-align 一直捉摸不透,那么这篇文章可能便是你一直想要寻找的资料了。

基本概念

image_1bafbonhdkmunvt10s2a232b61g.png-23.9kB

浏览器中的大小写字母、中文混排

基线与行高

基线:baseline
行高:line-height

为了表述的方便,我们首先回到小时候看看曾经使用过的拼音线格:
image_1bafau0ji1nb01oea1h1012icqks13.png-329.5kB

从上图我们基本就能明确基线与行高两个概念了:

  1. 基线:多数字母排列的基准线
  2. 段落中连续行的基线间的垂直距离称为行高(Line Height)或行距(Leading)

思考与扩展:当我们没有指定确定的行高时,浏览器给予行内元素的行高是多少?

  1. 没有确定行高时,其 line-height 的值默认为 normal
  2. 对于没有使用行内元素包裹的文字(如:<div>abc</div>),浏览器在底层的处理相当于为这些文字包上一层行内元素(相当于 <div><span>abc</span></div>
  3. 浏览器为行内元素设置的默认行高 normal 取值随着字体大小、字体类型的变化而变化

x-height

x 这个字母在排版中具有不俗的地位,下面来看看如何个不俗法。

image_1bafc7uglqo61ote1j521flct511t.png-30kB

x-height 指的便是小写字母 x 字母的实际物理高度。为什么会选择 x 呢,可能是因为其良好的对称性、上下边缘平整才成为这个天选之子吧。

这里为什么会莫名其妙地说起 x-height 这个概念呢?在前端有什么用呢?

请继续往下阅读吧,可以预告一下:x-height 与我们今天的主角 vertical-align 有联系。

小写字母的“下沉”

首先上一段代码:
image_1bafdkra71u6dotkkub17l8cpt2a.png-33.3kB

看看实际效果:
image_1bafdn8011bb71ogq1eaecdo1o0a34.png-31.3kB

然后我们来局部放大小写字母部分,通过对角线找到 行盒 的垂直中线(图中竖直方向中间的红线),与 x 的中心位置进行对比便能发现:行盒垂直方向的中线高于小写的 x 的中心点
image_1bafdmmadvrc19dqur71927q732n.png-142.9kB

这个情况,可以形象地记忆为小写字母的 下沉

文本排版参考线

image_1bafetjs27d11udtiu94c11o279.png-30.4kB

一图看懂

进阶

关于网页中的图片

图片做为网页中特殊的行内元素,但是图片又不是文字,为了更好阐述下文图文混排的知识,根据经验我做出如下阐述:

  1. 图片的 baselinebottom 可以认为位置相同,都是图片的底边位置
  2. 图片的 top 可以认为是图片的上边位置
  3. 图片不是文本,所以我们可以认为图片没有所谓的 text-toptext-bottomsubsup 概念

莫名出现的空白

源码:
image_1bafhcotm12m338av3o15cj1nul13.png-25.9kB

效果:
image_1bafhd8nsmj31vj71mcdjkjc831g.png-12.6kB

嗯,出现了莫名的空白,其实这也是我们经常遇到的问题,这个空白出现的原因是什么呢?

想通这个问题很简单,你只要先假设图片的相邻处有文字,思考图片文字的对齐方案,单后再把文字去掉就能想通了。

值得注意的是这个空白只有在标准模式下渲染才会出现,在接近标准模式(HTML 4.0)、怪异模式(HTML 3.0、IE5-)下渲染不会有。

那么我们如何消除这个空白呢?

  1. 外层块盒设置 font-size: 0
  2. 外层块盒 line-height 设置得足够小(在 Chrome 下设置要小于 12px)

合成行盒的各排版参考线

合成行盒就是类似下面这种情况,简单点说便是图片文字混排的情况

1
2
3
4
5
<span>
<span>XYZ</span>
<img src="xxx">
<span></span>
</span>

经过测试,我们能得到以下结果:合成行盒各排版参考线情况
image_1bafi8hrat54ob91c9l1fch14br9.png-110.1kB

修正:图中的 x-height 应为 x-height

总结的几个原则:

  1. 大部分排版参考线只由这里面字体最小的那部分确定
  2. 大图能决定合成行盒的 top

vertical-align 详解

请认认真真地咀嚼下面的结论,遇到具体情境时再结合上文的手段进行分析,你就能得出正确的对齐手段。

baseline:把当前盒的基线与父盒的基线对齐。如果该盒没有基线(如图片),就将底部外边距的边界和父盒的基线对齐
sub:把当前盒的基线降低到合适的位置作为父盒的下标(该值不影响该元素文本的字体大小)
super:把当前盒的基线提升到合适的位置作为父盒的上标(该值不影响该元素文本的字体大小)
text-top:把当前盒的 top 和**父盒的内容区的 top(即父盒的 text-top)对齐
text-bottom:把当前盒的 bottom 和
父盒的内容区的 bottom (即父盒的 text-bottom)对齐
middle:把当前盒的垂直中心和父盒的基线加上父盒的半 x-height 对齐
top:把当前盒的 top 与
行盒的 top(父盒下合成行盒的 top)对齐
bottom:把当前盒的 bottom 与
行盒的 bottom(父盒下合成行盒的 bottom)**对齐
<percentage>:把当前盒提升(正值)或者降低(负值)这个距离,百分比是相对元素自身 line-height 计算。当值为 0% 时等同于 baseline。
<length>:把当前盒提升(正值)或者降低(负值)这个距离。当值为 0 时等同于 baseline。(CSS2)


附录

一个用于测试的简单的、经典的页面:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<!DOCTYPE html>
<html lang="zh-cmn-Hans">
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no,width=device-width,shrink-to-fit=no">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name="renderer" content="webkit">
<title>vertical-align demo</title>
</head>
<body>
<!--
几个可以尝试的扩展练习:
1. 尝试先将图片确定为某个 vertical-align 值,再来变更两个 span 的 vertical-align 值,查看效果,分析原理
2. 尝试随意地为两个 span 和一个 img 分配 vertical-align 值,查看效果,分析原理
3. 如果 span 内文字多行会怎么样?
-->
<div style="background-color:#E5EDFF;"><span style="background-color:#fff;font-size: 40px;">ZXXXxx</span><img src="https://dummyimage.com/300x200/000/fff" style="width: 300px; height: 200px;"><span style="background-color:#fff; font-size: 23px;">zxxf</span></div>
<hr>
<!--
可以尝试的扩展练习:为最外层 div 内的各个元素随机设置 vertical-align,查看效果,分析原理
-->
<div><span style="background-color: #ccc">zxxxf</span><div style="background-color:#E5EDFF; display: inline-block"><span style="background-color:#fff; font-size: 40px;">ZXXXxx</span><img src="https://dummyimage.com/300x200/000/fff" style="width: 300px; height: 200px;"><span style="background-color:#fff; font-size: 23px;">zxxf</span></div></div>
</body>
</html>
FuChee wechat
扫一扫,关注我