1. 程式人生 > >用position:relative和float實現不定寬塊級元素的居中

用position:relative和float實現不定寬塊級元素的居中

前言

首先是個前端中非常基礎小白的話題,已經很清楚這個方法的前端大牛輕噴。我現在學習前端,對學習過程中進行的思考會作記錄,希望能幫到有需要的人。

關於不定寬塊級元素

塊級元素我們很清楚,預設佔據一行的元素,比如divul就是很典型的塊級元素。對於定寬的塊級元素居中,通過設定相應的marginauto即可,比如對寬度為500px的div元素:

div {
    width: 500px;
    margin: 20px auto;
}

這樣,該定寬元素就可以居中了。
問題在於不定寬,也就是我們沒有設定寬度,是不能通過以上方法來實現居中的。因為,不定寬的塊級元素,其整個內容(即border + padding + width)就需要佔據一整行,也就無法再通過margin:auto

來實現居中,因為auto了之後,margin也是0。

關於position:relative和float

position:relative可以讓元素相對於原來自身的位置進行偏移,通過設定topleft就可以進行偏移。
為了方便說明,我們先來寫兩個div元素:

<body>
<div id="parent">
    <div id="child">I am a child</div>
</div>
</body>

在設定topleft時還可以設定為百分比,這個百分比就是其父元素寬度的百分比,例如對一個不定寬的塊級元素div#child

進行以下設定,就可以讓其往前移動div#parent寬度的50%,在我們的例子裡,div#parentbody同寬。

div#child {
    position: relative;
    left: 50%;
}

注意這並不是居中!
居中是指其內容的中點正好位於頁面的中點,而以上只是將其左邊界移到了父元素容器的中點。

於是乎,如果div#parent進行50%的偏移,然後再讓div#child反向進行50%偏移,是不是就可以實現居中了呢?

其實不然,因為對該元素進行反向50%,即left:-50%;偏移的時候,偏移的距離是父元素的寬度的一半,如果父元素剛好和body也就是頁面的寬度一致,那相當於都是偏移頁面寬度的一半,一正一反,剛好抵消。而如果父元素有自己的寬度,那就更加不好預測了。

所以問題的關鍵是確定元素偏移的距離問題。
現在div#parent已經被移動到頁面的中點,我們期望的是:div#child設定了left:-50%之後,其偏移距離應該是自身內容的寬度的一半

注意:我們說元素的內容,說的是元素內可見的內容,比如這裡div#child的『I am a child』,如果有不嚴謹的地方,請各位指出哈

那麼怎麼實現呢?

讓我們理一下關係:
1. div#child的偏移距離是div#parent的寬度
2. div#child的偏移距離應該是其自身內容的寬度

所以只要div#parent的寬度和div#child內容的寬度一致不就行了?怎麼做到呢?

這時我們可以用float

浮動對於盒子模型元素的效果就是從文件流中移出來,這時高度和寬度也隨之塌縮到其所包含的子元素的寬度,比如做如下設定

div#parent {
    float: left;
}

div#parent的寬度就變成div#child的寬度

此外我們還會發現,body的高度變為0,因為其不再包含div#parent了,也就不包含任何元素。

這樣就達到我們的目的了,總的來說,實現div#child居中,只要進行如下設定

div#parent {
    float: left;
    position: relative;
    left: 50%;
}
div#child {
    position: relative;
    left: -50%
}

多說幾句

其實設定父元素的寬度與子元素相同,還有一種方法,那就是設定display:inline-block,可以用來代替float:left

div#parent {
    display:inline-block;
    position:relative;
    left:50%;
}
div#child {
    position:relative;
    left:-50%;
}

但是我發現,同樣是以行內元素形式排列的display:inline卻不能實現居中,觀察元素寬度發現,設定了display:inline後的div#parent寬度是子元素的寬度,但不是子元素內容的寬度,那麼子元素的寬度是多少?沒錯就是等於body的寬度,這是從上往下繼承的。

然而如果我把div#child也設定成display:inline,此時父子元素的寬度都是子元素的內容的寬度了,仍然不能居中,彷彿此時div#child設定的left:-50%不是針對div#parent

看到這句疑惑以及結合inline元素的寬高特性,大家應該就可以理解了,要知道,如果我們去設定行內元素的寬高,是不會起作用的,所以讓子元素去參照父元素的寬高偏移50%也是不會起作用的,因此子元素會繼續向上尋找,找到一個塊級元素,或者一個inline-block的元素,並以其寬高為百分比基準。而在本例中,那就是body

這是我個人得出的結論,沒有經過官方證實,但我覺得可以說明問題

所以,為父元素設定display:inline是不能實現居中的,而應該用display:inline-block