最近处理了一个字体图标没有在容器中垂直居中的样式问题。本来觉得,只是 css 写的不正确,实际却并无那么简单。
一番波折后,最终发现,是由于一处小细节,挖出了个大坑。
在处理问题的整个过程当中,一方面复习了相关的 css 基础知识;另外一方面,对于问题缘由的推理方法上,也给了我一些新的启示,故特此记录下来。css
同事小 w 请教了我一个样式问题:他写的页面上,一处本该垂直居中的字体图标,变成了与容器顶部对齐,不知道是哪里 css 写的不对,
如图所示(因为事故现场已不存在,此处为模拟还原的场景): html
<div class='wrapper'> <div class='inner'> <i class="far fa-check-circle"></i> </div> </div> 复制代码
css 以下:浏览器
.outer { height: 60px; line-height: 60px; text-align: center; color: white; background-color: gray; } .inner { display: inline-block; font-size: 26px; line-height: 1; } 复制代码
能够看到,html 结构很简单,分为三部分,即外部容器.outer
,内部容器.inner
,以及字体图标自己。
外部容器将height
于line-height
同设为 60px,是经典的垂直居中的方法,然而,结果却并无实现居中。
问题出在哪里了呢?
那么就先从垂直居中的原理来分析一下吧。markdown
咱们常常说,“让height
等于line-height
能够实现垂直居中”。其实,这个说法自己,是有很多问题的。
首先,对于一个容器和一个内联元素来讲,并不须要同时设置height
和line-height
,只要给容器设置line-height
,就能够“垂直居中”了,以下图: app
<div class='wrapper'> <span class='text'>中文文本</span> </div> 复制代码
.wrapper { margin-bottom: 20px; line-height: 100px; color: white; background-color: gray; text-align: center; } 复制代码
不须要设height
很好理解,由于line-height
也能够将容器高度撑开,此时的height
的值为auto
,自动计算成了line-height
的值。
之因此会有“让height
等于line-height
”的说法,是由于最先这种作法是基于高度已经固定的容器,要使得其中的文本垂直居中,就须要设置容器的line-height
等于高度。(因此也能够直接去掉高度,改成设置line-height
)
但这里还有个问题,其实文本并无真正的“垂直居中”,确切的说,是文本的“内容区域”居中了。若是给文本设置背景色,就能够看出其内容区域: 字体
display: inline-block
的元素来讲,是不存在的。以下图:
<div class='wrapper'> <span class='cube'></span> </div> 复制代码
.wrapper { margin-bottom: 20px; line-height: 100px; color: white; background-color: gray; text-align: center; } .cube { display: inline-block; width: 50px; height: 50px; background-color: white; } 复制代码
对于display: inline-block
的元素,要使其垂直居中,咱们一般会在元素上添加vertical-align: middle
使其垂直居中,如图: ui
.wrapper { margin-bottom: 20px; line-height: 100px; color: white; background-color: gray; text-align: center; } .cube { display: inline-block; width: 50px; height: 50px; background-color: white; vertical-align: middle; } 复制代码
这是什么原理呢?
参考 w3c 对于vertical-align
的定义,当设置为middle
时:spa
Align the vertical midpoint of the box with the baseline of the parent box plus half the x-height of the parent.翻译
翻译过来,就是说,vertical-align: middle
的元素,会和父元素所用字体的 baseline 高度加上 x-height 的一半对齐,而这个值,其实就是小写字母 x 的中线的高度,如图: 设计
vertical-align
,即
vertical-align: baseline
时,为何元素会偏高:
vertical-align: baseline
的定义:
Align the baseline of the box with the baseline of the parent box. If the box does not have a baseline, align the bottom margin edge with the parent's baseline.
因此,元素块的底部,与 baseline 对齐,也就是字母 x 默认所处位置的那条线:
完成了以上的分析,再回头看最开始的问题,发现,做为内容器做为display: inline-block
元素,没有添加vertical-align
属性,因而咱们加上它试试:
.wrapper { height: 60px; line-height: 60px; text-align: center; color: white; background-color: gray; } .inner { display: inline-block; font-size: 26px; line-height: 1; vertical-align: middle; } 复制代码
发现并无用。难道是由于只有一个字体图标,没有一个参照物的缘由?(以前的中文字符不止一个字)
带着这种设想,在字体图标旁,添加一个字符试试,以下:
The minimum height consists of a minimum height above the baseline and a minimum depth below it, exactly as if each line box starts with a zero-width inline box with the element's font and line height properties. We call that imaginary box a "strut." (The name is inspired by TeX.).
以及在vertical-align
段落中写道:
The following values only have meaning with respect to a parent inline element, or to the strut of a parent block container element.
简而言之,当只有一个字符时,浏览器会在文本前,设置一个 0 宽度的隐藏字符,做为对齐的参考。因此说,并不须要去手写一个字符来对齐。
这下,我凌乱了。。。
冷静一下后,继续开始分析。发现,不一样页面上,html 结构和 css 是彻底一致的,但为何实际样式会不同呢?
再根据以上的理论分析,发现没有居中的缘由,极可能是浏览器没有提供这样一个strut
,做为参考。而这,并不符合 w3c 定义的规范。
想到这里,忽然意识到了什么,在对比一下页面,发现了惟一一处不一样点:
<!DOCTYPE html>
,这下问题终于解决了。
首先,对于垂直居中问题,利用line-height
未必能实现,这个须要根据具体状况来分析,而分析的依据,正是 w3c 中的基本定义。因而可知,对于基础概念,不该当只停留在会用的阶段,仍是须要完整的阅读一遍,理解透彻; 其次,对于排查问题,除告终合理论依据外,尝试作对比是一个很好的方式。经过对比,一步步排除不相关缘由,最后就能挖出问题所在; 最后,在排查的过程当中,决不能无凭无据预设条件。由于在此次,纠结了好久的一个缘由,正是由于没有考虑到,页面的标准自己存在问题,而把时间花在寻找使用方式上是否是还存在未知错误。直到后来,一步步排除了以后,才锁定到了最终缘由。