1. 程式人生 > >巧用margin/padding的百分比值實現高度自適應(多用於佔位,避免閃爍)

巧用margin/padding的百分比值實現高度自適應(多用於佔位,避免閃爍)

一個基礎卻又容易混淆的css知識點

本文依賴於一個基礎卻又容易混淆的css知識點:當margin/padding取形式為百分比的值時,無論是left/right,還是top/bottom,都是以父元素的width為參照物的!
也許你會說,left/right以父元素的width為參照物好理解,但是top/bottom為什麼也是以父元素的width為參照物的呢?網上眾說紛紜,關鍵還是看W3C的規範

Note that in a horizontal flow, percentages on ‘margin-top’ and ‘margin-bottom’ are relative to the width of the containing block, not the height (and in vertical flow, ‘margin-left’ and ‘margin-right’ are relative to the height, not the width).

Note that percentages on ‘padding-top’ and ‘padding-bottom’ are relative to the width of the containing block, not the height (at least in a horizontal flow; in a vertical flow they are relative to the height).

權威一出,記住就好,科科。

高度自適應佔位

假設有這麼個場景:

如上圖所示,有這麼一種用來放圖片的容器,圖片都是正方形(為了方便舉例用正方形,實際上只要固定長寬比例即可)。
在PC端好辦,容器的寬高都寫死是多少px,這樣即使圖片載入不出來容器都不會變型。但是在移動端,由於各機型解析度相差太大,寫死px是絕對不可能的,終究還得靠百分比來實現自適應:

  1. 容器寬度設個50%吧,這樣一行放倆容器,各佔螢幕寬度一半,沒問題。

  2. 圖片寬度設個100%取容器的寬度,沒問題。

  3. 容器高度沒法設定啊,因為容器寬高的參照物不一樣,而且需求是高度與寬度一致,所以無法通過為容器高度設定百分比來達成,那就只能靠內容高度撐開了。

  4. 容器的內容高度就是圖片的高度,若圖片是正方形,則圖片高度與圖片寬度一致,也即與容器寬度一致,看起來沒問題是吧?實際上,在瀏覽器把圖片加載出來以前,圖片的高度是零,那可就沒辦法把容器撐開了,如下圖所示:

這樣一來,即使圖片載入速度很快,容器在圖片載入前後都會有一個變型的過程,也就是俗稱的“閃爍”,而如果圖片載入不出來,整體佈局就更是難看了。
現在問題已經出來了,就是如何做到不靠圖片本身就能把容器的高度撐開。

設定容器的padding-bottom/top

使用margin/padding的百分比值來解決自適應高度的關鍵在於:容器margin/padding的百分比參照物是父元素的寬度,而容器的width的百分比參照物也是父元素的寬度,倆屬性參照物一致,那麼想要把這倆屬性的值統一起來就很簡單了。
優化方案是這樣的:給容器設定padding-top/padding-bottom跟width一致的值(百分比)。

#container { width: 50%; //父元素寬度的一半 background-color: red; //僅為了方便演示 } .placeholder { padding-top: 50%; //與width: 50%;的值保持一致,也就是相當於父元素寬度的一半。 } <div id="container" class="placeholder"></div>

結果,容器的視覺效果如下:

容器的盒子模型如下:

從盒子模型可以看出,雖然容器的內容高度為0,但由於有了跟內容寬度一致的padding,因此整體視覺效果上像是被撐開了。此方案瀏覽器相容性很不錯,唯一的缺陷是無法給容器設定max-height屬性了,因為max-height只能限制內容高度,而不能限制padding(我原以為設定box-sizing: border-box;可以讓max-height限制padding,不過親測無效,明白的朋友麻煩告知一下原因)。

給子元素/偽元素設定margin/padding撐開容器

從上面的方案看出max-height失效的原因是容器的高度本來就是padding撐的,而內容高度為0,max-height無法起作用。那想要優化這一點,唯一的方法就是利用內容高度來撐開而非padding,這個方案跟消除浮動所用的方案非常相似:給容器新增一個子元素/偽元素,並把子元素/偽元素的margin/padding設為100%,使其實際高度相當於容器的寬度,如此一來,便能把容器的高度撐至與寬度一致了。由於新增子元素與HTML語義化相悖,因此更推薦使用偽元素(:after)來實現此方案。

#container { width: 50%; position: relative; background-color: red; overflow: hidden; //需要觸發BFC消除margin摺疊的問題 } .placeholder:after { content: ''; display: block; margin-top: 100%; //margin 百分比相對父元素寬度計算 } <div id="container" class="placeholder"></div>

此時視覺效果上與上一方案無異,重點來看看此時容器的盒子模型:

可以看出,此時容器的內容高度與內容寬度一致,媽媽再也不用擔心我無法通過max-height來限制容器高度了。
另外,使用margin的話需要考慮margin摺疊的問題(參考),padding則無此煩惱。

容器內部如何新增內容

上述方案只提及如何不依賴容器內容來撐開容器,那麼,在撐開容器後,如何給容器新增內容(圖片、文字等)呢?
答案很簡單,那就是利用position: absolute;

#container { width: 50%; position: relative; background-color: red; overflow: hidden; //需要觸發BFC消除margin摺疊的問題 } .placeholder:after { content: ''; display: block; margin-top: 100%; //margin 百分比相對父元素寬度計算 } img { position: absolute; top: 0; width: 100%; } <div id="container" class="placeholder"> <img src="http://img.arrayhuang.cn/product/miya-1060079/multiple/[email protected]_415w_415h_1c_0i_1o_1x.jpg" /> </div>

效果如下:

後補

寬高不一致的自適應怎麼做?

有朋友可能會問,上面提到的都是寬度與高度一致的情況,如果不一致那怎麼辦呢?其實自適應的重點在於,元素的寬高必須維持一個固定的比例,比如說寬高一致比例就是1:1,寬是高的兩倍那就是2:1,只要這個比例是明確而且固定的,那麼只需要相應地修改margin/padding的百分比值即可適應不同的寬高比例。

還有其它的寬高自適應方案嗎?

當然有,比如說css3新推出的長度單位vw,就是以螢幕寬度為參照物的,只要給元素的width和height都用上vw單位,那width跟height就可以輕易設成一樣的了,不過既然是css3,瀏覽器相容性肯定成問題:

總結

自適應的精髓在於寬度,margin/padding設定百分比彌補了元素高度無法自適應地與元素寬度保持一致的缺陷。

例子:

<div style="width:600px; position:relative; padding-bottom:600px; height:0;">
    <img src="http://ubmcmm.baidustatic.com/media/v1/0f000nYQae6t2iCMjPksts.png" style="width:100%; height:100%; position:absolute;" />
</div>

相關推薦

margin/padding百分比值實現高度適應用於佔位避免閃爍

一個基礎卻又容易混淆的css知識點 本文依賴於一個基礎卻又容易混淆的css知識點:當margin/padding取形式為百分比的值時,無論是left/right,還是top/bottom,都是以父元素的width為參照物的! 也許你會說,left/right以父元素的w

textarea如何實現高度適應不出現滾動條

今天需要些一個回覆評論的頁面,設計師給的初始介面就是一個只有一行的框。然後當時就想這個互動該怎麼實現比較好,然後想起了新浪微博的做法:點選評論,預設顯示一行,當輸入的文字超過一行或者輸入Enter時,輸入框的高度會隨著改變,直到輸入完畢。頓時覺得這個細節做得挺不錯的,可以效仿下。下面分享2種實現text

CSS完美實現iframe高度適應支持跨域

真的 高度 org lns nal aid .org bsp 方法 Iframe的強大功能偶就不多說了,它不但被開發人員經常運用,而且黑客們也常常使用它,總之用過的人知道它的強大之處,但是Iframe有個致命的“BUG”就是iframe的高度無法自動適應,這一點讓很多人都頭

div模擬textarea文本域輕松實現高度適應

body post HR word-wrap overflow out 模擬 target get <style> .textarea{ width:400px; min-height:20px; max-height:300p

css實現高度適應正方形

spl splay code gin tle margin content div hidden <!DOCTYPE html> <html> <head> <title></title> </hea

CSS完美實現iframe高度適應支援跨域

Iframe的強大功能偶就不多說了,它不但被開發人員經常運用,而且黑客們也常常使用它,總之用過的人知道它的強大之處,但是Iframe有個致命的“BUG”就是iframe的高度無法自動適應,這一點讓很多人都頭疼萬分。百度或是谷歌一下,確實很多解決方法,但嘗試一下,會發現問題很多:瀏覽器相容性差,不能自

jquery之div模擬textarea文字域輕鬆實現高度適應

<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> <style type="tex

Android動態設定GridView的高度固定column實現高度適應

動態設定GridView的高度,固定column,根據gridview中的item個數設定高度: 呼叫以下方法:     [java]  view plain copy print ?

vue環境下基於contenteditable實現高度適應行文字域div模擬

1、在web應用中,常用的多行文字輸入<textarea>,滿足了我們絕大部分的需求,唯一不足之處就是文字高度不能隨內容自適應,如果需要高度自適應需要通過js指令碼實現 2、div有天然的高度自適應,在加上個contenteditable屬性,就可以變成一個文字內容自適應的多行文字輸

textarea如何實現高度適應

轉自:http://www.xuanfengge.com/textarea-on-how-to-achieve-a-high-degree-of-adaptive.html 今天需要些一個回覆評論的頁面,設計師給的初始介面就是一個只有一行的框。然後當時就想這

Android GridView之新增分隔線動態設定高度實現高度適應並解決第一個item不顯示的問題

最近做一個專案時遇到一點問題,在這裡分享一下解決思路。 首先看效果圖: 這裡的需求是實現介面中的六個圖示,博主後來和同事討論過這個問題,用 GridView 實現費時費力好嘛,同事認為做6個 Button 就 好了,可能博主就愛鑽牛角尖吧,一開始認為怎麼辦只要還有辦法那就

iOS自動佈局實現Cell和Tableview高度適應SDAutoLayout

SDAutoLayout 一行程式碼搞定自動佈局!致力於做最簡單易用的Autolayout庫。The most easy way for autolayout.    ☆新增:cell高度自適應 + label文字自適應☆ >>>>

動態設定GridView的高度固定column實現高度適應

動態設定GridView的高度,固定column,根據gridview中的item個數設定高度: 呼叫以下方法: public static void setListViewHeightBased

textarea高度適應可設置最大高度

換行 hid fun utf-8 cti html logs type att <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8">

UItableView Cell 高度適應--隨著個label內容變化適應

1.cell .h檔案 // WorkReportCell.h // GOSProject // // Created by on 2017/5/11. // Copyright © 2017年 All rights reserved. // #import

基於javascript實現圖片懶載入用於pc端與h5

這篇文章主要介紹了javascript實現圖片懶載入的方法及思路,在實際開發中有時我們需要用懶載入,也就是延遲載入圖片的方式,來提高網站的親和力,需要的朋友可以參考下。 一、定義   圖片延遲載入也稱為懶載入,延遲載入圖片或符合某些條件時才載入某些圖片,通常用於圖片比

關於ViewPager高度適應隨著頁面高度改變Viewpager的高度

重寫Viewpager public class MyViewPager extends ViewPager { private int current; private int viewHeight = 0; private b

關於ViewPager高度適應隨著pager頁的高度改變Viewpager的高度

第一個,看程式碼(對照上面程式碼)activityScdetailsBottomVp.setOnPageChangeListener(new ViewPager.OnPageChangeListener() { @Override public void onP

popopWindow 實現頂部篩選選單頂部不變底部陰暗思路記錄

先上效果:需要解決的問題:1.popopWindow 位置(此處為toolbar正下方)2.頂部不變,底部陰暗3.popopWindow 根據item個數適配高度,並設定最大height一、popopWindow 位置首先第一點,傳入的parent為toolbar。下面的lo

冗余圖層實現元件中心點與註冊點的合一

巧用冗余圖層實現元件中心點與註冊點的合一在Flash中,創建的每個元件都有一個註冊點和一個中心點。這兩個點都可以用於定位和作用參照點使用,其中,中心點還是元件旋轉的參照點。在元件進行以自身中心點旋轉時,中心點的位置就決定了元件堂堂正正的旋轉,還是歪歪扭扭的旋轉。文字的描述不如直接使用實例來得詳細,下面就通過一