《CSS世界》笔记三:内联元素与对齐
上一篇:《CSS世界》笔记二:盒模型四大家族
下一篇:《CSS世界》笔记四:流的保护与破坏
写在前面
在页面布局中,内联元素的垂直对齐是比较常见和基础的布局需求,但是我们往往会因为垂直对齐中的1px,2px而头疼不已。在这一篇博客(《css世界》第五章)中,张大大从深层次解释了垂直对齐的原理,并为内联元素的垂直对齐提供了最佳实践。
一、基本概念
(1)基线(baseline):字母 x 的下边缘(线)就是基线
(2)x-height:小写字母 x 的高度,术语描述就是基线和等分线(mean line)(也称作中线,midline)之间的距离
ascender height: 上行线高度 cap height: 大写字母高度 median: 中线 descender height: 下行线高度
(3)middle线:vertical-align:middle;
中middle指的是基线往上1/2 x-height高度(近似垂直居中)
(4)单位ex:CSS中的一个相对单位,指的是小写字母 x 的高度
用法:不受字体和字号影响的内联元素的垂直居中对齐效果
.icon-arrow { display: inline-block; width: 20px; height: 1ex; background: url(arrow.png) no-repeat center; }
二、行高line-height
对于非替换元素的纯内联元素,其可视高度完全由 line-height 决定,通俗的说,纯内联元素的可视高度不受padding、margin、border 属性的影响(这个我们在上一篇博客也有说明)
2.1 行距
一个公式:行距 = line-height - font-size
上下行距分配规则:当行距为偶数时,上下行距平分;当行距为基数时,上边距向上取整,下边距向下取整;因为绝大多数字体都是偏下的
2.2 line-height实现居中
误区:并非是line-height=height
实现了单行文本的居中,line-height单独作用即可实现
<div class="box"> <div class="content">基于行高实现的...</div> </div> /* 近似居中对齐 */ .box { width: 280px; line-height: 120px; background-color: #f0f3f9; margin: auto; } .content { display: inline-block; line-height: 20px; margin: 0 20px; text-align: left; vertical-align: middle; } /* 绝对居中 */ .box { font-size: 0; } .box .content { font-size: initial; }
原理:
近似居中:.box
行高为120,.content
行高为20,“幽灵空白节点”在.content
前撑起了整个内容区域
绝对居中:在上面的基础上,由于middle(基线往上1/2 x-height高度)为近似居中,由于x-height受到font-size的影响,font-size为0时可理解为绝对居中
2.3 line-height的属性值
line-height 的默认值是 normal,还支持数值、百分比值以及长度值
默认值normal在不同字体下的解析不同,因此在实际开发中一般会重置line-height
重点:
假设 font-size = 14px;
数值:line-height: 1.5; ==> line-height 计算值是 1.5*14px=21px
百分比值:line-height: 150%; ==> line-height 计算值是 150%*14px=21px
长度值:line-height:21px
乍一看,似乎 line-height:1.5、line-height:150%和 line-height:1.5em 这3种用法是一模一样的,最终的行高大小都是和 font-size计算值,但是,实际上,line-height:1.5和另外两个有一点儿不同,那就是继承细节有所差别。如果使用数值作为 line-height 的属性值,那么所有的子元素继承的都是这个值;但是,如果使用百分比值或者长度值作为属性值,那么所有 的子元素继承的是最终的计算值
最佳实践:基本上各大站点都是使用数值作为全局的 line-height 值
三、vertical-align属性(重点)
vertical-align 作用的前提条件是:只能应用于内联元素以及display值为table-cell的元素,注意,浮动和绝对定位会让元素块状化也会使vertical-align失效
3.1 属性值
四类属性值:
- 线类,如 baseline(默认值)、top、middle、bottom;
- 文本类,如 text-top、text-bottom;
- 上标下标类,如 sub、super;
- 数值百分比类,如 20px、2em、20%等;
根据计算值的不同,相对于基线往上或往下偏移,到底是往上还是往下取决于vertical-align
的计算值是正值还是负值,如果是负值,往下偏移,如果是正值,往上偏移
vertical-align:baseline 等同于 vertical-align:0
vertical-align的百分比:margin 和 padding 是相对于宽度计算的,line-height 是相对于 font-size 计算的,而这里的 vertical-align 属性的百分比值则是相对于 line-height 的计算值计算的
3.2 vertical-align相关问题及解决
(1)案例一:任意一个块级元素,里面若有图片,则块级元素高度基本上都要比图片的高度高
<div class="box"> <img src="mm1.jpg"> </div> .box { border: 1px solid #ccc; } .box > img { height: 96px; }
原因:间隙产生的三大元凶就是“幽灵空白节点”、line-height
和vertical-align
属性;图片前放置小写的x,会发现图片的基线是元素底部,与“幽灵空白节点”的基线(小写x下边缘)对齐;
解决方法:
- 图片块状化:可以一口气干掉“幽灵空白节点”、
line-height
和vertical-align
line-height:0;
font-size: 0;
- 干掉基线对齐:
vertical-align
的值为top、middle、bottom
中的任意一个都是可以的
(2)案例二:使用text-align: justify;
实现文字两端对齐
text-align: justify;
多用于文字排版,有一个非常重要的特性:不会对最后一行两端对齐,因此单行文本时若要对齐需要人为换行
补充text-align: justify;
的用法案例:
<div class="form"> <label for="name">姓名</label><input id="name" type="text"><br> <label for="tel">联系方式</label><input id="tel" type="text"> </div> $font-size: 14px; $line-height: 1.5; .form { background-color: #eee; width: $font-size * 5 + 150px; } label { display: inline-block; text-align: justify; width: $font-size * 5; height: $font-size * $line-height; overflow: hidden; vertical-align: bottom; margin-right: 10px; } label:after { content: ''; width: 100%; display: inline-block; }
(3)案例三:使用text-align: justify;
实现列表两端对齐
为了让最后一行也两端对齐,需要使用占位元素实现换行
<div class="box"> <img src="1.jpg" width="96"> <img src="1.jpg" width="96"> <img src="1.jpg" width="96"> <img src="1.jpg" width="96"> <i class="justify-fix"></i> <i class="justify-fix"></i> <i class="justify-fix"></i> </div> .box { text-align: justify; } .justify-fix { display: inline-block; width: 96px; }
此时,元素底部有很大的间隙。产生的原因无非是vertical-align,因此我们会设置line-height:0;
,但是并没有真正解决问题,为什么?
一个 inline-block 元素,如果里面没有内联元素,或者overflow
不是visible
,则该元素的基线就是其 margin 底边缘;否则其基线就是元素里面最后一行内联元素的基线。
<span class="dib-baseline"></span> <span class="dib-baseline">x-baseline</span> .dib-baseline { display: inline-block; width: 150px; height: 150px; border: 1px solid #cad5eb; background-color: #f0f3f9; }
实际展示如下图所示:
最终解决:
- font-size: 0;
- line-height: 0; 且在占位元素中添加空格
<i class="justify-fix"> </i>
四、扩展案例
4.1 基于20px图标对齐最佳实践
一个 inline-block 元素,如果里面没有内联元素,或者 overflow 不是 visible, 则该元素的基线就是其 margin 底边缘;否则其基线就是元素里面最后一行内联元素的基线。
基于上面的理论,有下面几个要点:
- 图标高度和当前行高都是 20px
- 图标标签里面永远有字符,可以借助:before 或:after 伪元素生成一个空格字符轻松搞定
- 图标 CSS 不使用 overflow:hidden 保证基线为里面字符的基线,但是要让里面潜在的字符不可见
.icon { display: inline-block; width: 20px; height: 20px; background: url(sprite.png) no-repeat center; white-space: nowrap; letter-spacing: -1em; text-indent: -999em; } .icon:before { content: '\3000'; }
4.2 无兼容的水平垂直居中弹框
利用之前提到的绝对居中的知识vertical-align:middle; font-size:0;
<div class="container"> <div class="dialog"></dialog> </div> .container { position: fixed; top: 0; right: 0; bottom: 0; left: 0; background-color: rgba(0,0,0,.5); text-align: center; font-size: 0; white-space: nowrap; overflow: auto; } .container:after { content: ''; display: inline-block; height: 100%; vertical-align: middle; } .dialog { display: inline-block; vertical-align: middle; text-align: left; font-size: 14px; white-space: normal; }
五、总结
- 内联元素各种线 & 行高计算及分配规则;
- 利用line-height如何实现多文本居中 & line-height 各属性值区别
- vertical-align取值对垂直对齐的影响及解决方式
- justify 实现文字两端对齐和列表两端对齐
上一篇:《CSS世界》笔记二:盒模型四大家族
下一篇:《CSS世界》笔记四:流的保护与破坏