本篇文章主要介紹了深入理解css中vertical-align屬性 ,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟著小編過來看看吧
一、為什麼要寫這篇文章
今天看到一個問題:
兩個p 都設定display:inline-block,正常顯示;但是在第二個p中加一個區塊級元素或內聯元素,顯示就變了個樣,為什麼?
<meta charset="utf-8"/> <style> p{ width: 100px; height: 100px; border:1px solid red; display: inline-block; } .align{ /* vertical-align: top;*/ } </style> <body> <p> </p> <p class="align">为什么?</p> </body>
解決方案就是給第二個p加上:vertical-align:top。
關於vertical-align和基準我知道一點,但是這個問題我沒能答出,所以學習總結分享一下。
二、vertical-align幹什麼的?
w3c有一段相關資訊如下:
'vertical-align' Value: baseline | sub | super | top | text-top | middle | bottom | text-bottom | <percentage> | <length> | inherit Initial: baseline Applies to: inline-level and 'table-cell' elements Inherited: no Percentages: refer to the 'line-height' of the element itself Media: visual Computed value: for <percentage> and <length> the absolute length, otherwise as specified
可以看到vertical-align影響inline- level元素和table-cell元素垂直方向上的佈局。根據MDN描述,vertical-align對::first-letter和::first-line同樣適用。
適用於:
inline水平的元素
inline:,,,< em>,未知元素
inline-block:(IE8+),
#'table-cell '元素
table-cell:
所以預設情況下,圖片,按鈕,文字和儲存格都可以用vertical-align屬性。
取值:
程式碼如下:
vertical-align: baseline|length|percentage|sub|super|top|middle|bottom|text-top|text- bottom|initial|inherit;
三、baseline
1、字母'x'與baseline
# 字母x的下緣(線)就是基線。不是字母s之類下面有尾巴的字母
#基線甚至衍生出了:
1.“alphabetic” baseline: “字母”基線– 英文
2."hanging" baseline: “懸掛”基線– 印度文
#3.“ideographic” baseline: “表意”基線– 中文
#2、baseline的確定規則
1、inline-table元素的baseline是它的table第一行的baseline。
2、父元素【line box】的baseline是最後一個inline box 的baseline。
3、inline-block元素的baseline確定規則
規則1:inline-block元素,如果內部有line box,則inline-block元素的baseline就是最後一個作為內容存在的元素[inline box]的baseline,而這個元素的baseline的確定就要根據它自身來定了。
規則2:inline-block元素,如果其內部沒有line box或它的overflow屬性不是visible,那麼baseline將是這個inline-block元素的底margin邊界。
3、範例:inline-block範例
#上圖描述:
上圖從左到右都是line-block元素,紅線代表margin-box的邊界,藍線代表baseline;黃色為border,綠色為padding,藍色為content。
左邊元素包含沒有脫離正常流的內容c,中間元素除了沒有脫離正常流的內容c外還增加了overflow:hidden,右邊元素沒有內容,但是內容區有寬高。
分析圖中各種情況inline-block元素的baseline:
#上圖左圖,inline-block元素有處於正常流的內容,依照規則1 ,所以inline-block的baseline就是最後一個作為內容存在的元素的baseline,也就是內容c的baseline,而c的baseline根據自身定,就是圖中藍色。
上圖中圖,inline-block元素overflow:hidden不為visible,根據規則2,該inline-block元素baseline就是inline-block元素的margin-box的下邊界了,即圖中藍線。
上圖右圖,inline-block元素沒有內容,依照規則2,所以其baseline為margin-box的下邊界,即藍線。
4、範例:baseline決定規則範例
範例:
<style type="text/css"> .ctn-block{ display: block; background-color: #bbb; line-height: 200px; font-size: 50px; } .ctn-block .child1{ display: inline-block; width: 100px; height: 100px; margin:10px 0; vertical-align: baseline; background-color: aliceblue; } </style> <p class="ctn-block"> <p class="child1"></p> <span>Gg</span> </p>
分析:
父元素.ctn-block的base-line是Gg的baseline,
inline-block元素因為沒有內部line box,也沒有設定overflow:visible,所以其baseline為底margin邊界。
四、vertical-align基於baseline的不同取值
#1、baseline
##將子元素盒子的baseline與父盒子的baseline對齊。2、middle
#將元素盒子的垂直中點與父盒子的baseline加上父盒子的x-height的一半位置對齊這裡元素盒子的垂直中點容易確定,父盒子的baseline也好確定,但是x-height要進行計算得到,這個x-height就是字母x的高度。3、text-top
將盒子的頂端(margin-top邊界)與父盒子的文字區域頂端對齊審查盒子看到margin-top的頂端。 審查文本,看到藍色區域的上邊界就是文本區域頂端。 最終效果是盒子的頂端與父盒子文字區域頂端對齊。4、text-bottom
將盒子的底端(margin-bottom邊界) 與父盒子的文字區域底端對齊和text-top類似,不過將子元素的margin-bottom和文字區域的下邊界對齊。5、sub
將子元素盒子的baseline降低,到適當的父盒子的下標位置子元素的baseline已經確定了,就是margin-bottom下邊界,但是父盒子的下標位置太不好理解。 。 。首先需要了解下標這個概念,我們可以透過標籤為文字加上下標,將中的內容修改為GgGg,就會有以下效果。 這裡就是將元素的margin-bottom下邊界和下標的baseline對齊。
6、super
將元素盒子的baseline升高,到適當的父盒子的上標位置。 與sub對應,super提升到上標內容的baseline處,先透過標籤建立上標。
7、percentage
#:升高(正值)或降低(負值)子元素盒子,具體的升高/降低數值由父盒子的line-height的值乘以百分比計算得出。如果百分比為0%,就和vertical-align:baseline一樣。 這個是相當好理解的,就相當於子元素盒子的baseline升高或降低,具體數值為百分比乘以父盒子的line-height。 本例中,父盒子的line-height為200px,所以設定25%,元素應該會上移50px。 並不是很直觀,給它加上一個transform: translate(0, 50px);【相對下移50px】,它又移到那個熟悉的位置了。8、length
#升高(正值)或降低(負值)子元素盒子。值為升高/降低的距離,如果為0,和vertical-align:baseline一樣。 以我們最常用的px為單位,設定vertical-align:50px,效果就和上面百分比為25%(200px*25%=50px)一樣了,不做例子了。五、vertical-align基於line box的不同取值
當vertical-align設定為top和bottom時,其就不是依照baseline進行定位了,而是根據line box進行定位。子元素盒的頂部和底部也就是其上下margin外邊界。1、top
將子元素盒子的頂部和其所在的line box頂部對齊由於vertical-align:top將會讓子元素盒子頂部與line box頂部對齊,而如果line box高度小於子元素高度,line box將會被撐開。我們先用一個較高的元素撐開line box,然後再看看效果:
可以看到,big子元素撑开了line box,而child1的margin-top外边界紧贴在line box的顶端。
2、bottom
将子元素盒子的底部和其所在的line box底部对齐
和top类似,由于big用于撑开line box,可以不必修改其vertical-align的值,仅修改child1为vertical-align:bottom,效果:
六、inline元素下方可能会有一点空隙
例子:尝试将li元素在垂直方向上进行对齐的话,这个现象非常常见
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <style type="text/css"> ul{ background-color: bisque; } .box { display: inline-block; width: 100px; height: 100px; background-color: aliceblue; /* vertical-align: middle;*/ } </style> </head> <body> <ul> <li class="box"></li> <li class="box"></li> <li class="box"></li> </ul> </body> </html>
1、垂直空隙
因为li元素默认vertical-align:baseline,而baseline的下方会给字母的一部分留出空间,因此会产生一个空隙,要产生理想的效果,解决方案就是改变line box的baseline位置,比如将这些li设置为vertical-align:middle。【tip:加一个x效果更明显】
2、水平空隙
li元素的水平空隙是因为换行引起的,这个换行会变成一个空白,这个空白会被解析为DOM中的文本节点。比如像下面酱紫的代码。
<ul> <li class="box"></li><li class="box"></li> <li class="box"></li> </ul>
效果如下:因为前2个li之间没有空白,而2和3个li之间有空白。
但是上面的代码可读性太差,也不美观,一般这样写
<ul> <li class="box"></li><!-- 注释去空格 --><li class="box"></li> <li class="box"></li> </ul>
我们用一个注释节点代替空白(文本节点),而注释节点渲染的时候是不渲染的。了解更多DOM中的节点类型,可看我的另一篇文章《DOM》。
七、vertical-align:middle让元素下移而不居中的问题分析
1、问题
现在有三个inline-box块,高度分别为100px,200px,300px,想让高度为100px的块垂直居中,于是写出了如下代码:
<style type="text/css"> .ctn-block{ background-color: #bbb; } .ctn-block .child { display: inline-block; width: 100px; background-color: aliceblue; } .ctn-block .child-1 { height: 100px; /* vertical-align: middle;*/ } .ctn-block .child-2 { height: 200px; } .ctn-block .child-3 { height: 300px; } </style> <p class="ctn-block"> <p class="child child-1"></p> <p class="child child-2"></p> <p class="child child-3"></p> </p>
给中间p加上vertical-align:middle,效果变为上图二的样子——child-1元素下移了,但是却没有居中。
2、原因
从上面可以指定,vertical-align:middle的定位方式是:将子元素盒子的垂直中点与父盒子的baseline加上父盒子的x-height的一半位置对齐。
子元素盒子的中点很好算,而父盒子的baseline加上父盒子的x-height一半位置又是什么呢?
首先计算父盒子的baseline:三个子元素的baseline走在一条直线上,就是child-2和child-3的底部。
然后加上父盒子的x-height:由于chrome下默认font-size是16px,而font-family:sans-serif,所以x-height的一半大概是3-4px,综上,按照如下方式对齐:
3、 解决方案
一种方式是将最高的元素设为vertical-align:middle。
然后将想要居中的也设定为vertical-align:middle,其他的根据需要设定vertical-align:top/bottom。
原理有点抽象:
首先明确一点:最高元素设定为vertical-align:middle后,这个元素对于line box来说,baseline就是其中线。
其他元素设置vertical-align:top/bottom后,它们不影响line box的baseline,所以再将需要设定垂直居中的元素也设定为vertical-align:middle,它们的baseline必然在最高元素的baseline之上,所以会会被强制下移,进行居中。
.ctn-block .child-1 { height: 100px; vertical-align: middle; } .ctn-block .child-2 { height: 200px; vertical-align:top; } .ctn-block .child-3 { height: 300px; vertical-align: middle; }
4、衍生的一种可行的垂直居中方案
为父元素设定一个伪元素::after,其高度为父元素的高度,display:inline-block,将其设定为vertical-align:middle即可撑开line box,同时line box的baseline为父元素高度一半的位置。然后设定子元素vertical-align:middle,即可实现居中。
考虑兼容性的话,这里需要使用一些hack,由于IE8不支持::after伪元素,所以需要一个span来替代。而display:inline-block亦需要hack。
八、其他应用
ico和文字对齐
<style type="text/css"> .pop-viphead-nologinbox { width:500px; } .pop-viphead-nologin-icon { display:inline-block; width: 14px; height: 14px; background: url("images/not_login_tip_ico.png") no-repeat; } .pop-viphead-nologin-txt { display: inline-block; color: #333; font-size: 12px; margin-left:2px; } .pop-viphead-nologin-btn { display: inline-block; margin-left: 3px; } .pop-viphead-nologin-btn a { display: block; width: 76px; height: 25px; line-height: 25px; color: #fff; text-align: center; background-color: #00adee; border-radius: 1px; font-size: 12px; } </style> <p class="pop-viphead-nologinbox"> <p class="pop-viphead-nologin-icon"></p> <span class="pop-viphead-nologin-txt">您还没有登录哦!</span> <p class="pop-viphead-nologin-btn"><a href="javascript:;" j-delegate="login">立即登录</a></p> </p>
我想让左边ico和文字,按钮都对齐。
.pop-viphead-nologin-icon,.pop-viphead-nologin-txt,.pop-viphead-nologin-btn{ vertical-align: middle; }
以上是css中vertical-align屬性實例詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!