很久沒寫博客了,恰好今天跨年夜沒約到什麼妹子,在家宅着不如寫點東西好了。html
昨天晚上,給公司年會作一個移動端的投票頁面,遇到一個UI優化的問題:ide
· 正文內容少於一屏時,投票提交按鈕固定顯示在頁面底部(如圖一)
· 正文內容多於一屏時,投票提交按鈕,跟隨內容,流式顯示在內容下面(如圖二)
附圖:測試
之前作一些管理後臺的時候,底部的版權信息聲明就是這樣的UI需求,實現思路大概就是:
底部按鈕,須要一直顯示在底部,能夠給body設個最小100%高度,而後用絕對定位把按鈕顯示在body底邊靠上一點的位置,這樣內容少的時候,100%的高度起做用,按鈕會顯示在底部,內容多的時候,內容會把body的高度撐出一屏出現滾動條,而按鈕是基於body絕對定位,因此能夠跟着滾動條走,一直在內容的底部顯示。優化
關鍵代碼就是這樣:ui
html結構: html>body>.wrap+.bottom-bar html { height: 100%; } body { min-height: 100%; position:relative; } .bottom-bar { position: absolute; bottom: 0px; }
本覺得輕車熟路,5-10分鐘搞定的事情,由於一個bfc的問題,我硬生生調了大半夜,如今記錄一下。spa
按照剛纔的寫法,內容恰好一屏的時候,提交按鈕會擋住文檔底部的部份內容,因此這裏還須要給body設置一個下邊距,值要等於bottom-bar的height。
這個時候問題出來了:
body下的子元素的magin-top和margin-bottom值會影響到body的渲染,進而影響到基於body作相對定位的bottom-bar。調試
調試一番以後,總結了兩點特徵,就是塊級元素&默認狀況下&垂直方向的渲染規則:
· 子元素的margin,會影響父元素的UI渲染,父元素不會被子元素的margin想固然地撐開,就是說渲染上,子元素的margin做用在了父元素上
· 父元素的margin會被子元素的覆蓋掉,若是父元素magin值比較小的話,表現就是父元素的margin被子元素的吃掉了code
此時,不禁得想起來CSS2裏面很是彎彎繞的一個概念,BFC。orm
注:若是BFC小測試 這道題能瞬間答對的話,下面的BFC描述能夠直接跳過了。htm
以前對BFC模式下margin會摺疊的理解僅限於兄弟節點之間,沒有意識到父子之間也有這類狀況。實話說,多數中文的BFC技術文章裏講的,都是在闡述本身的理解或者抄來抄去,有些講的模棱兩可的,恐怕做者本身都沒有搞清楚。
先貼一下mdn和w3的文檔供你們參考下:
https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Block_formatting_context
https://www.w3.org/TR/CSS21/visuren.html#block-formatting
https://www.w3.org/TR/CSS21/visuren.html#block-level
備註:
· 仔細看看w3的介紹,我相信block containers/block boxes/Block-level elements/block-level box這幾個詞必定會讓你看得想要放棄治療的,哈哈!
· 另,以上英文文檔看得比較費勁的,能夠再參考另外一位同仁對BFC解釋的文章:BFC 神奇背後的原理
再次複習了一下BFC的概念以後,我嘗試着總結一下我對這個東西的理解:
1. Block formatting context,是一個上下文環境(能夠理解爲js裏的做用域),這個環境中的元素,遵照塊級元素的渲染規則。好比:
· 從上到下排布,各佔一行
· 垂直方向的margin值,會在相鄰節點(兄弟或父子)之間被摺疊
· 自身高度不會被子節點的margin撐大
· 自身高度不會被浮動子節點撐開
2. 一個默認的html文檔流中,只有一個上下文環境
3. 若是須要打破1中所述規則,須要建立一個新的上下文(establish new block formatting contexts for their contents),方法是:
· 適用於父子/兄弟
float:left/right、position:absolute、display:非block
· 僅適用於父子
overflow:非visible
新年快要到了,很少說了,結合以上需求和對BFC的再次理解,直接貼代碼:
html結構: html>body>.wrap+.bottom-bar * { padding: 0; margin: 0; } html { height: 100%; overflow: auto; } body { position: relative; overflow: auto; min-height: 100%; } .wrap { overflow: auto;/*爲了防止子元素對body產生影響,這裏須要專門開闢一個新上下文*/ margin-bottom: 40px;/*這裏也能夠加到body去,body{box-sizing: border-box;padding-bottom:40px;}*/ } .bottom-bar { position: absolute; bottom: 0px; height: 40px; width: 100%; }