HTML+CSS宝典 CSS进阶[扩展] 参考线(下)
四、vertical-align属性
要了解 vertical-align 属性的各种预设值是什么含义,还有数值是什么含义,就需要了解一些知识点
什么知识点呢?
如果一个元素内的子元素出现行盒,那么该元素内部也会产生参考线。
决定参考线的有三个 css 属性
1. font-size 字体大小确定了,5条参考线之间的距离
2. font-family 字体确定了,参考线的相对距离就确定下来了
3. line-height 行高确定了,参考线最顶上那条线 和 最底下那条线都确定下来了
这个三个属性一旦确定,参考线就一定确定下来了
比如,p 元素里面包含一个 span 行盒,
<p> <span>M<span> </p>
span 元素有自己参考线,p 元素也有参考线,因为“只要一个元素里面出现了行盒,它就有参考线”
如果 p 元素里没有 span 元素,直接写一个字母 M,p 元素有没有参考线?
<p> M </p>
p 元素也有参考线,之前说过“文字一定在行盒里面”
现在知道为什么了,因为文字是按照参考线来排列的,
不在行盒里面就没有参考线,没有参考线就没法排列,
所以文字一定在行盒里面,于是文字会包裹一个匿名行盒,这也可以认为是 p 元素里面有行盒,因此 p 元素内部也会产生参考线。
这样 p 元素本身生成的参考线大小是多少呢?
1. 为来看清楚,设置 p 元素的字体大小为 32 像素
2. 设置 p 元素字体为 Arial,span 元素也是 Arial 字体了
3. 行高默认为 normal
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>vertical-align</title> <style> p{ background-color: red; font-size: 32px; font-family:arial; line-height:normal; } span{ font-size:200px; background-color:lightblue; line-height:normal; } </style> </head> <body> <p> M <span>M<span> <span style="font-size:5rem;color:yellow;">M<span> </p> </body> </html>
字体大小、字体类型、行高默认值都确定了,参考线就确定了
1. p 元素内部有参考线,
2. span 元素内部也有参考线,
出现了两个参考线
1、vertical-align 属性的预设值
两个参考线是怎么来排列的呢?
vertical-ailgn: baseline
默认情况是基线对齐,p 元素里也有一个字母M,还有二个 span 元素里面的M,三个M都是基线对齐
MMM
为什么会基线对齐?
1. 因为默认情况下,行盒 span 元素的 vertical-ailgn 属性的值是 baseline
2. baseline 表示该元素的基线与父元素的基线对齐
vertical-align 还有其它的对齐方法
vertical-align: super;
super 表示该元素的基线与父元素的上基线对齐
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>super</title> <style> p{ background-color: red; font-size: 32px; font-family:arial; line-height:normal; } span{ font-size:200px; background-color:lightblue; line-height:normal; } </style> </head> <body> <p> M <span style="vertical-align:super;">M</span> <!-- 这个span元素的基线,与父元素的上基线对齐 --> <span style="font-size:5rem;color:#fff;">M</span> </p> </body> </html>
1. 设置第二个span元素(中间的M)与父元素的上基线对齐,
2. 对第三个span元素没什么影响,它仍然与父元素的基线对齐
vertical-align: sub
sub 表示该元素的基线与父元素的下基线对齐
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>sub</title> <style> p{ background-color: red; font-size: 32px; font-family:arial; line-height:normal; } span{ font-size:200px; background-color:lightblue; line-height:normal; } </style> </head> <body> <p> M <span style="vertical-align:sub;">M</span><!-- 当前这个span元素的基线与父元素的下基线对齐 --> <span style="font-size:5rem;color:#fff;">M</span> </p> </body> </html>
第二个M与父元素的下基线对齐
vertical-align: text-top
text-top 表示该元素的 virtual-area 的顶边(就是加上行高的那条线),对齐父元素的 text-top(文本顶边)
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>text-top</title> <style> p{ background-color: red; font-size: 32px; font-family:arial; line-height:normal; } span{ font-size:200px; background-color:lightblue; line-height:normal; } </style> </head> <body> <p> M <span style="vertical-align:text-top;">M</span><!-- 当前这个span元素的virtual-area的顶边(加上行高那条线),对齐父元素的text-top(文本顶边) --> <span style="font-size:5rem;color:#fff;">M</span> </p> </body> </html>
1. 第二个M的顶边(加上行高)对齐父元素(第一个M)的文本顶边(父元素的第二条线)
2. 这样导致父元素(第一个M)的基线位置发生变化,父元素的基线位置发生变化,第三个M的位置也跟着变
这就是为什么会影响到其它元素
vertical-align: text-bottom
表示该元素的 virtual-area 的底边(加行高的边),对齐父元素的 text-bottom
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>text-bottom</title> <style> p{ background-color: red; font-size: 32px; font-family:arial; line-height:normal; } span{ font-size:200px; background-color:lightblue; line-height:normal; } </style> </head> <body> <p> M <span style="vertical-align:text-bottom;">M</span> <span style="font-size:5rem;color:#fff;">M</span> </p> </body> </html>
第二个M加上行高的底边,对齐父元素第一个M的底边
是加上行高之后的底边,如果给第二个父元素 M 的行高加高点,设置 line-height: 2 底边又变了
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>vertical-align:text-bottom</title> <style> p{ background-color: red; font-size: 32px; font-family:arial; line-height:normal; } span{ font-size:200px; background-color:lightblue; line-height:normal; } </style> </head> <body> <p> M <span style="vertical-align:text-bottom; line-height:2;">M</span> <span style="font-size:5rem;color:#fff;">M</span> </p> </body> </html>
第二个M元素是增加行高的底边,对齐第一个父元素字母M的倒数第二条线(text-bottom)
导致父元素(第一个M)的基线发生变化,父元素的基线发生变化,第三个元素M的位置也发生变化了
vertical-align: top
该元素的 virtual-area 的顶边,对齐父元素的顶边(父元素的顶边,指的是该行中的最高顶边)
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>top</title> <style> p{ background-color: red; font-size: 32px; font-family:arial; line-height:normal; } span{ font-size:200px; background-color:lightblue; line-height:normal; } </style> </head> <body> <p> M <span>M</span> <span style="font-size:5rem;color:#fff; vertical-align:top;">M</span> </p> </body> </html>
设置第二span元素(第三个M)
第三个M的最高顶边(加上行高之后的顶边),没有跟第二个M对齐,第三个M的顶边对齐父元素中最高的那条顶边
vertical-align: bottom
bottom 该元素的 virtual-area 的底边,对齐父元素的底边(该行中的最低边)
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>vertical-align:bottom</title> <style> p{ background-color: red; font-size: 32px; font-family:arial; line-height:normal; } span{ font-size:200px; background-color:lightblue; line-height:normal; } </style> </head> <body> <p> M <span>M</span> <span style="font-size:5rem;color:#fff; vertical-align:bottom;">M</span> </p> </body> </html>
还是设置第三个M
2、行框概念 line-box
行盒组合起来,可以形成多行,每一行的区域叫做"line-box"
意思是,一个元素里面可以出现很多行盒,比如 i元素、m元素、span元素、strong元素、还有文字(文字是匿名行盒)等,
这些行盒组合起来可以形成多行,形成多行之后每一行的区域叫做 line-box
Ps:
行盒的单词是 inline-box,
line-box 不好翻译,这里随便翻译一下把它叫做行框
line-box 行框是什么呢?
line-box 是一个区域,表示每一行都有一个 line-box
line-box 的顶边是该行内所有行盒最高顶边,底边是该行行盒的最低底边
比如页面上的三个元素
M MM
每个M都有自己的参考线,每个M都有一个顶边和底边,整个这一行的盒子生成一个 line-box
line-box 的顶边,就是这一行里最高的顶边
line-box 的底边,就是这一行里最底的底边
形成 line-box,就可以这样表述
vertical-align: top 该元素的 virtual-area 的顶边,对齐 line-box 的顶边
vertical-align: bottom 该元素的 virtual-area 的底边,对齐 line-box 的低边
实际上,一个元素实际占用高度(高度自动的时候),高度的计算是通过 line-box 计算
3、vertical-align 属性还可以取值为数值
数值:是相对于基线的偏移量,向上为正数,向下为负数
默认是基线对齐,设置后面两个M
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>vertical-align</title> <style> p{ background-color: red; font-size: 32px; font-family:arial; line-height:normal; } span{ font-size:200px; background-color:lightblue; line-height:normal; } </style> </head> <body> <p> M <span>M</span> <span style="font-size:5rem;color:#fff; vertical-align: 20px;">M</span> <span style="font-size:5rem;color:#fff; vertical-align: -5px;">M</span> </p> </body> </html>
如果设置第二个元素M
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>vertical-align</title> <style> p{ background-color: red; font-size: 32px; font-family:arial; line-height:normal; } span{ font-size:200px; background-color:lightblue; line-height:normal; } </style> </head> <body> <p> M <span style="vertical-align: -50px;">M</span> <!-- 设置第二个M --> <span style="font-size:5rem;color:#fff;">M</span> <span style="font-size:5rem;color:#fff;">M</span> </p> </body> </html>
第二个M它最高,所以它没法动了,整个 line-box 全靠它撑起了的
MMMM
只能相对对应其它元素,运动是相互的
下面 line-box 的情况就不一样了
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>vertical-align</title> <style> p{ background-color: red; font-size: 32px; font-family:arial; line-height:normal; } span{ font-size:200px; background-color:lightblue; line-height:normal; } </style> </head> <body> <p> M <span style="vertical-align: 70px;">M</span> <span style="font-size:5rem;color:#fff;">M</span> <span style="font-size:5rem;color:#fff;">M</span> </p> </body> </html>
line-box 的顶边是第二个大 M 的顶边,
line-box 的底边是后面两个 M 的底边
MMMM
4、vertical-align 取值为百分比
百分比,也是相对于基线的偏移量,但是百分百是相对于自身 virtual-area 的高度(算上行高的)
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>百分百取值</title> <style> p{ background-color: red; font-size: 32px; font-family:arial; line-height:normal; } span{ font-size:200px; background-color:lightblue; line-height:normal; } </style> </head> <body> <p> M <span>M</span> <span style="font-size:5rem;color:#fff;">M</span> </p> </body> </html>
设置第三个M
行高、字体大小都会影响它位置变化,这块比较复杂
5、什么情况下不生成行框 line-box?
line-box 是承载文字内容的必要条件,如果没有行框文字是没法显示的
以下情况不生成行框
1. 某元素内部没有任何行盒(不演示这种情况)
2. 某元素字体大小为0, font-size: 0 不生成行框
p 元素里面不生成行框,里面的文字 lorem 不会显示
<p style="font-size: 0;"> <span style="font-size: 2em;"> lorem. </span> </p>
行框确定了元素的自动高度,而 p 元素里面没有生成行框,它的高度就是0,因此里面不显示文字
给 p 元素设置高度 100 像素,里面还是不会显示文字
<p style="font-size:0; height:100px; background-color:red;"> <span style="font-size: 2em;"> lorem. </span> </p>
这就解释了行框是承载文字的必要条件,没有行框就不会显示
lorem.
但是这里有兼容问题,有些老 IE 浏览器又显示,所以恐怖的要死,
css里面最复杂的就是行盒,了解就行了
五、可替换元素和行块盒的基线
可替换元素 和 行块盒,排列的时候跟行盒一样排成一排,又涉及到参考线的影响。
可替换元素和行块盒的基线在哪?
可替换元素里面又不一样,图片跟 input 又不一样
1、图片的基线在哪?
图片的基线位置,位于图片的下外边距(下外边距就是计算 margin 的尺寸)
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>图片元素基线</title> </head> <body> <p style="font-size: 32px;"> <img style="width:100px;" src="http://www.ruyic.com/blog/uploads/image/201904/155591911913470.png" alt=""> 请联系我M </p> </body> </html>
1. 字母M的基线在字母的边缘
2. 中文字体的基线在字母M往上一些
3. 图片的基线在下外边距
字母M的基线、中文字体的基线、图片的基线是对齐的,在一条线上
请联系我M
给图片设置一个 margin 外边距
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>图片元素基线</title> </head> <body> <p style="font-size: 32px;"> <img style="width:100px;margin:20px;" src="http://www.ruyic.com/blog/uploads/image/201904/155591911913470.png" alt=""> 请联系我M </p> </body> </html>
还是图片的基线对齐
请联系我M
2、图片下面的白边问题
图片下面有红边
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>图片红边</title> <style> div{ background-color: red; font-size: 16px; } </style> </head> <body> <div> <img src="http://www.ruyic.com/blog/uploads/image/201904/155591911913470.png" alt=""> </div> </body> </html>
为什么图片下面有白边(红边)
因为
1. div 元素里面的子元素出现行盒,div元素内部会生成参考线,
2. div 参考线生成了,基线在图片下边沿的位置
3. 由于图片没有设置 margin,图片的下边沿就是基线,
4. 现在图片跟父元素的基线是对齐的,所以出现了红色的边
解决白边有两个方法
第一个:设置 div 父元素 font-size: 0,父元素就不生成任何行框
第二个:设置 img 元素为块盒 display:block,块盒不会使父元素生成参考线,没有参考线就不存着基线对齐
这里使用 vertical-align 属性不好解决,
设置 img 元素的 vertical-align: bottom 好像是解决了,但是这个问题没有根本上解决
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>图片红边</title> <style> div{ background-color: red; font-size: 16px; } </style> </head> <body> <div> <img style="vertical-align:bottom;" src="http://www.ruyic.com/blog/uploads/image/201904/155591911913470.png" alt=""> </div> </body> </html>
看起来没有红边了
如果图片尺寸特别小,宽度只有 10 像素,还会出现问题,最好的办法就是设置 img 元素为块盒
补充一下
vertical-align: midden
midden 表示该元素的中线(中线的意思是 content-area 的一半,垂直上的中间位置)与父元素的 X 字母高度一半的位置对齐
3、表单元素的基线
表单元素的基线在内容的底边
给 input 元素设置 margin 属性 20 像素是有效的,因为 input 是可替换元素
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>表单元素的基线</title> </head> <body> <p> <input type="checkbox" style="margin:20px;"> 请选择M </p> </body> </html>
input 元素 margin 底边没有和基线对齐,input 的基线和文字的基线对齐。因为 input 的基线和图片不一样
请选择M
4、行块盒基线又不一样了
行块盒分为很多种情况
第一种情况,
行块盒最后一行有 line-box 行框,用最后一行的基线作为整个行块盒的基线(我们很少会遇到这种情况)
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>行块盒</title> </head> <body> <p> <span style="width:50px; display:inline-block; border:1px solid; padding:20px;"> Lorem ipsum dolor sit amet </span> <span> M </span> </p> </body> </html>
行块盒与 M 的排列,最后一行的基线和 M 对齐
Lorem ipsum dolor sit amet M
第二种情况,
如果行块盒内部没有行盒,则使用下外边距作为基线
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>行块盒</title> </head> <body> <p> <span style="width:50px; height:50px; display:inline-block; border:1px solid; margin:20px"> </span> <span> M </span> </p> </body> </html>
没有文字的情况下,对齐方式又变了,再设置 margin,设置了 margin 就跟图片一样了
M
六、行盒的垂直对齐
多个行盒垂直方向上的对齐
1、怎么解决 文字 和 多选框没有对齐
给没有对齐的元素设置 vertical-align 属性,这里给 input 属性设置 vertical-align: middle
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>垂直对齐</title> <style> input[type="checkbox"]{ width: 30px; height: 30px; } </style> </head> <body> <p> <input type="checkbox" style="vertical-align: middle; "> <span>我同意</span> </p> </body> </html>
input 自己的位置变化了,导致与文字之间的相对位置也变化了,所以看上去是文字变化了
我同意
除了预设值还可以设置数值,调整到合适的位置
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>垂直对齐</title> <style> input[type="checkbox"]{ width: 30px; height: 30px; } </style> </head> <body> <p> <input type="checkbox" style="vertical-align:-9px; "> <span>我同意</span> </p> </body> </html>
我同意
2、文字和图片对齐怎么调整呢?
可以设置图片img元素,也可以设置span元素都可以,两行行盒任选一个调整
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>垂直对齐</title> <style> </style> </head> <body> <p> <img src="http://www.ruyic.com/blog/uploads/image/202202/164605771322963.png" alt=""> <span style="vertical-align: 17px;">请联系我</span> </p> </body> </html>
这里设置 span 元素 vertical-align 属性
请联系我
对比不设置的 vertical-align 属性的,图片的基线在下边缘,文字的基线和图片的基线对齐的效果
请联系我
3、关于图片底部白边
白边发生在图片的父元素是一个块盒,块盒的高度是自动的,图片底部和父元素之间会出现空白,父元素设置的字体越大白边越大
一般有两种解决办法
第一种:设置父元素字体大小为0 font-size: 0 ,副作用是父元素里有文字就看不见了
第二种:img元素设置为块盒 display: block ,最常见的就是这种方法