首頁 >web前端 >css教學 >css中vertical-align屬性實例詳解

css中vertical-align屬性實例詳解

零下一度
零下一度原創
2017-04-21 09:27:442707瀏覽

本篇文章主要介紹了深入理解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有一段相關資訊如下:

 


&#39;vertical-align&#39;
Value:      baseline | sub | super | top | text-top | middle | bottom | text-bottom | <percentage> | <length> | inherit
Initial:      baseline
Applies to:      inline-level and &#39;table-cell&#39; elements
Inherited:      no
Percentages:      refer to the &#39;line-height&#39; 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:a1f02c36ba31691bcfe87b2722de723b,45a2772a6b6107b401db3c9b82c049c2,8e99a69fbe029cd4e2b854e244eab143,18927a4a116227032472475afa6638ef,未知元素 

inline-block:d5fd7aea971a85678ba271703566ebfd(IE8+),bb9345e55eb71822850ff156dfde57c8d5fbe0f7ffe03799e41c6754dca5aa28....

#'table-cell '元素

table-cell:b6c5a531a458a2e790c1fd6421739d1c

所以預設情況下,圖片,按鈕,文字和儲存格都可以用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下邊界,但是父盒子的下標位置太不好理解。 。 。首先需要了解下標這個概念,我們可以透過b96cac025db4031319c29e1eb68f19d6標籤為文字加上下標,將45a2772a6b6107b401db3c9b82c049c2中的內容修改為Ggb96cac025db4031319c29e1eb68f19d6Gg270ea406e83044e5b95e23270c35ff95,就會有以下效果。

這裡就是將元素的margin-bottom下邊界和下標的baseline對齊。

6、super

將元素盒子的baseline升高,到適當的父盒子的上標位置。

與sub對應,super提升到上標內容的baseline處,先透過2cdea26b4c3988e37d674b56660962a7標籤建立上標。

 

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中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn