美文网首页程序员Web前端之路
CSS垂直定位属性:vertical-align

CSS垂直定位属性:vertical-align

作者: Lxylona | 来源:发表于2018-01-18 23:06 被阅读140次

参考文章:
Vertical-Align: All You Need To Know

MDN:vertical-align

张鑫旭:字母’x’在CSS世界中的角色和故事

张鑫旭:我对CSS vertical-align的一些理解与认识

张鑫旭:CSS深入理解vertical-align和line-height的基友关系

张鑫旭:CSS vertical-align的深入理解(二)之text-top篇

一 概览

本文从微观层面讲述vertical-align的工作原理,工作环境。并整理了用vertical-align实现文本和图片居中的方法。

二 涉及内容概念

1. 顶线,中线,基线,底线
分别对应英文作业本的四条线:

图1-四条线
基线最为重要,行内元素就躺在这条线上。且行内元素默认基线和父元素(行框)基线对齐。

中线的定义为:中线位于基线的上方,与基线的距离为小写字母x高度的一半(即0.5ex),而ex同font-size相关,大部分浏览器认为1ex = 0.5em(em同样也是相对单位,不是绝对单位),因此会将基线以上1/4em处作为中线来对齐。

2. 内容区
顶线和底线包裹的区域。

内容区由字体大小和字数决定,跟行高半毛钱关系没有

给一个没有设置行高的行内元素设置背景,可以看到其内容区:


图2-内容区

3. 行高
简单讲就是行内元素所占的高度。

学术点就是内容区加上以内容区为中心上下对称扩展的空白区域,也就是上下行基线之间的距离。

4. 行距(行间距)
上一行的底线和下一行的顶线之间的距离。

也就是:(上一行行高-内容区高度)/2+(下一行行高-内容区高度)/2

5. 行内框(inline-box)
用例子来说明:

<p class="two-p">
        <span class="two-span span1">我有自己的行内框</span>
        <span class="two-span span2">我也有自己的行内框</span>
        <span class="two-span span3">我也有自己的行内框</span>
</p>
图3-行内框和行框

虽然三段话在同一行内,但是它们各有各的一块“区域” —— 一个长方体,将他们各自包裹起来,这些长方体在行内不一定对齐。

这些长方体就是行内框。

每个行内元素有自己的行内框。

文本行内框高度=行高=内容区+行距

图片行内框=内容区+padding+border+margin (也就是它自己的盒子模型)


图4-没有加内外边距的图片的行内框
.img{
    margin: 10px;
    padding:10px;
}
图5-加上内外边距之后图片的行内框

6. 行框(line-box)
图3中的行框就是灰色背景的那块区域。

可见,行框的任务就是包裹同一行行中的行内框,方便页面的渲染。

可以想象成一个大的快递箱,这个快递箱把很多大小不一的小快递箱包裹起来。那么这些大快递箱可以很整齐地摆放,而不是一对小快递箱随意堆在一起。

行框的高度由行内框最高点和最低点决定。

图4-行内框和行框

7. 包含框
一个个行框组成了包含框。

三 vertical-align的值

top:元素顶部(行内框)和行框顶部对齐
bottom:元素底部和行框底部对齐

baseline:默认值,元素基线和行框(父元素)基线对齐
sub:下标
super:上标
text-top:元素行内框顶部和行框(父元素)文本(不是图片或其他)的顶部对齐,这里的文本应该指的是行框中没有添加任何样式的匿名文本(自己实验得出,如有误请指正)
因为这个属性用的比较少,所以这里就没有整理了,感兴趣的同学可以自己看一下张鑫旭的另一篇文章:CSS vertical-align的深入理解(二)之text-top篇
text-bottom:元素底部和父元素文本的底部对齐,这里文本同上
middle:元素的中垂点和父元素的基线向上半个“x”距离的那根线对齐,垂直居中的中流砥柱
<length>:具体高度,比如10px
<percentage>:百分比,相对基线偏移行高的百分比。比如,行高100px,偏移10%,即相对基线向上偏移10px

四 行框的基线怎么确定

1. 主要知识点:

  1. 行内元素基线对齐是和父元素也就是行框的基线对齐。
  2. 行框的基线会为了满足布局,行高最小化等需求而改变位置。
  3. 可以通过匿名行内元素“x”来确定父元素基线位置。

2. 详细内容:

正如每个行内元素自己的基线,行框也有自己的基线。

行框的基线由所有行内元素的基线来确定。

行框的基线位置不是固定不变的,是会改变的。

行框需要其基线来满足一些需求,比如,垂直对齐,使行高最小化等等。当它遇到这些需求的时候,就会调整基线的位置。

举个例子,现在有三个行内元素:

<div class="one">
    <span class="icon taller"></span>
    <span class="icon shorter"></span>
    xxx
</div>
图5-行框的基线

行框的基线相对于匿名行内元素“x”的最低点是不对的,它永远和“x”元素的最底点对齐。

现在,给长条的绿色长方形加上一个样式:vertical-align:middle

图7-长条形垂直居中后行框的基线
讲道理,我们设置了长条形的样式,应该是长条形下移而不是另外两个行内元素上升呀。

如果从微观来看,长条形撑起了行框的高度。行框内已经没有任何空间给它移动了。可以理解为行高总是尽可能的小。

上面也说过,行框的基线会为了满足一些需求而移动。

所以行框就把基线往上移,移到长条形的中垂线再向上1/2个“x”的距离。(1/2“x”的距离下面会讲到)这样子行高就不会增大。

如果长条形不变,短条形设置vertical-align:middle

图8-短条形垂直居中后行框的基线

移动的就是短条形而不是其他两个行内元素了。因为这样做行高的增加是最小的。

所以为什么有时候想要让某一个元素行内居中,改变的是其他行内元素的位置呢?有答案了。

五 莫名的空隙

1. inline-block元素底部的空隙

比如,在一个div中放入一张图片,会发现图片的底部和div的底部不是贴合的,有一个空隙:


图9-图片底部有空隙

同样地,写网页导航的时候,设置每个li的样式为display:inline-block,这时候会发现,导航的下面也有一条空隙:

图10-导航条底部也有空隙

这条空隙其实是行内元素基线和底线之间的空隙。

想要去掉这条空隙,要么把基线移走,要么直接让它消失。

比如,元素设置样式:display:block:变成非行内元素,基线就不复存在了:

图11-图片设置为块元素

又比如,元素设置样式:vertical-align:middle/text-top/text-bottom/bottom,将父元素的基线往上移:

图12-设置元素的vertical-align为middle

再比如,在元素内写入文本,让父元素的基线上移:


图13-元素内写入文本让父元素基线上移

六 用vertical-align实现垂直居中

1. 图片(inline-block元素)居中

只需把父元素的行高设置为想要的高度,再给图片添加样式vertical-align:middle即可。

<div class="container" style="line-height:200px;">
    <img src="../static/images/img1.jpg" style="vertical-align:middle;">
</div>
图14-图片居中
需要注意的是这里的“居中”并不是严格意义上的居中,这里的“居中”是:图片的中垂线和父元素基线向上1/2个“x”字母的高度对齐。

2. 单行文本居中

<div style="line-height:200px;">
    <p >xxx</p> 
</div>
图15-单行文本居中

3. 多行文本居中

把多行文本当成图片处理(对内可以设置宽高,对外是内联元素)

<div class="three">
      <p class="three-p">
          <span class="three-one">third</span><br>
          <span class="three-two">third</span><br>
          <span class="three-two">third</span>
      </p>
</div>
<style>
    .three{
        line-height: 200px;
    }
    .three-p{
        display: inline-block;
        line-height:1.4em;
        vertical-align: middle;
    }
</style>
图16-多行文本居中

七 直通地心的大坑:vertical-align:middle 失效

有一次进行测试的时候,发现vertical-align:middle失效了!代码如下:

<html>
    <head>
    </head>
    <body>
        <div class="container" style="line-height:200px;">
            <img src="../static/images/img1.jpg" style="vertical-align:middle;">
        </div>
    </body>
</html>

什么?!!!代码完全没有问题啊?!!!!以前都是这样写的!!!!为什么不行了!!!

一个上午都在debug,就是找不到问题在哪里!

后来一哥们觉得,既然代码都是一样的,那就是标准的问题了。

于是,在文档前面加了一句<!DOCTYPE html>

居中了!!!!!

原来跟混杂模式还是标准模式有关!

所以使用这个属性一定要使用标准模式!

如果想要兼容旧浏览器,请加上一个空格来撑开行高:

<div class="container" style="line-height:200px;">
    <img src="../static/images/img1.jpg" style="vertical-align:middle;">&nbsp;
</div>

相关文章

网友评论

    本文标题:CSS垂直定位属性:vertical-align

    本文链接:https://www.haomeiwen.com/subject/qfhgoxtx.html