此文章是 解剖CSS佈局原理 的續集,以前那篇文章講的都是理論,本文章講具體的實例,根據本身對佈局的理解與開發經驗分爲如下幾類。css
由於PC端和移動端佈局差別較大,因此我將兩端佈局分開講,本文章將針對PC端的佈局進行講解,如下代碼只寫關鍵代碼。若是你發現你寫了關鍵打代碼還達不到效果,請檢查是否寫了不應寫的樣式。html
爲了提升網頁性能,考慮到repaint/reflow,表格元素儘可能少用,有其餘選擇的狀況儘可能用其餘佈局。segmentfault
<div id="container"> <div class="box"></div> </div>
方法一:app
.box { width: 300px; margin: 0 auto; }
比較經常使用的方法ide
方法二:佈局
#container { position: relative; } .box { width: 100px; position: absolute; left: 0; right: 0; margin: 0 auto; }
此方法適用於定位時的居中方式性能
方法一:flex
.box { display: table; margin: 0 auto; }
缺點:設置爲表格元素,內部元素的佈局有可能收到影響flexbox
方法二:spa
#container { position: relative; } .box { position: absolute; left: 50%; transform: translateX(-50%); }
缺點:要用到 transform
,兼容性較差
方法三:
#container { display: table-cell; // 這屬性在這可加可不加 text-align: center; } .box { display: inline-block; }
缺點:須要涉及到父類的樣式
<div id="container"> <div class="box"></div> </div>
方法一:
#container { position: relative; } .box { height: 50px; position: absolute; top: 0; bottom: 0; margin: auto 0; }
缺點:要用到定位,脫離文檔流
方法二:
#container { height: 400px; line-height: 400px; } .box { display: inline-block; height: 50px; vertical-align: middle; }
注意,父容器設置了行高,子類要記得重置行高
方法一:
#container { position: relative; } .box { position: absolute; top: 50%; transform: translateY(-50%); }
缺點:要用到 transform
,兼容性較差
方法二:
#container { display: table-cell; verticle-align: middle; }
缺點:由父類控制是否居中
<div id="container"> <span>1</span> <span>2</span> <span>3</span> </div>
#container { width: 200px; height: 100px; background: #ccc; text-align: center; } span { display: inline-block; background: #9fc; }
<div id="container"> <p>1</p> <p>2</p> <p>3</p> </div>
#container { height: 200px; display: table-cell; vertical-align: middle; }
<div id="container"> <div class="box box1"></div> <div class="box box2"></div> <div class="box box3"></div> </div>
#container { display: table; table-layout: fixed; } .box { display: table-cell; }
<div id="container"> <div class="left"></div> <div class="right"></div> </div>
左列定寬:
.left { float: left; width: 100px; } .right { margin-left: 100px; }
右列定寬:
#container { padding-right: 100px; overflow: hidden; } .left { float: left; width: 100%; } .right { position: relative; float: left; width: 100px; right: -100px; margin-left: -100px; }
#container { display: table; table-layout: fixed; } .left, .right { display: table-cell; } .right { width: 100px; }
須要定寬的那列設置寬度
右列自適應:
<div id="container"> <div class="left"></div> <div class="right"></div> </div>
.left { float: left; } .right { overflow: auto; }
左列自適應:
<div id="container"> <div class="right"></div> <div class="left"></div> </div>
.left { overflow: auto; } .right { float: right; }
方法一:
<div id="container"> <div class="left">定寬</div> <div class="center">自適應</div> <div class="right">定寬</div> </div>
.left, .right { position: absolute; top: 0; } .left { left: 0; width: 150px; } .center { margin: 0 80px 0 150px; } .right { right: 0; width: 80px; }
方法二:聖盃佈局
<div id="container"> <div class="left">定寬</div> <div class="center">自適應</div> <div class="right">定寬</div> </div>
#container { padding: 0 8px 0 150; } .left, .center, .right { position: relative; float: left; } .left { width: 150px; left: -150px; margin-right: -100%; } .center { width: 100%; height: 200px; } .right { width: 80px; right: -80px; margin-left: -80px; }
方法三:雙飛翼佈局
<div id="container"> <div class="wrap"> <div class="center">自適應</div> </div> <div class="left">定寬</div> <div class="right">定寬</div> </div>
.left, .wrap, .right { float: left; } .left { width: 150px; margin-left: -100%; } .wrap { width: 100%; } .center { margin: 0 80px 0 150px; } .right { width: 80px; margin-left: -80px; }
<div id="container"> <div class="left">定寬</div> <div class="center">自適應</div> <div class="right">定寬</div> </div>
#container { width: 100%; display: table; } .left, .right, .center { display: table-cell; } .left { width: 150px; } .right { width: 80px; }
<div class="article"> <img src="../img/icon.png">隨着HTML的成長,爲了知足頁面設計者的要求,HTML添加了不少顯示功能。可是隨着這些功能的增長,HTML變的愈來愈雜亂,並且HTML頁面也愈來愈臃腫。因而CSS便誕生了。 </div>
img { float: left; }
<ul class="list"> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> </ul>
方法一:用浮動
.list { width: 500px; height: 260px; } .list li { float: left; width: 100px; height: 100px; margin-left: 20px; margin-top: 20px; background: #c9f; }
經過 margin
來達到等距效果,根據父容器寬高和子類寬高與個數,算出 margin-left
和 margin-top
的值
方法二:用內聯塊
.list { width: 500px; height: 260px; font-size: 0; } .list li { display: inline-block; width: 100px; height: 100px; margin-left: 20px; margin-top: 20px; background: #c9f; }
用內聯塊的話,若是子類有文本,要記得設置 font-size
在上一個例子下去除邊界間距
.list { width: 460px; height: 220px; } .list li { float: left; width: 100px; height: 100px; margin-left: 20px; margin-top: 20px; background: #c9f; } .list li:nth-of-type(4n+1) { margin-left: 0 } .list li:nth-of-type(-n+4) { margin-top: 0 }
若要兼容IE8,則在對應的標籤上加類名,單獨處理
如上圖,所謂的瀑布流佈局就是一系列盒子或圖片的等寬不等高佈局。
真正的瀑布流佈局是這樣:
網上有人說用多列浮動佈局、用CSS3佈局、用flexbox,其實實現的都是假的瀑布流,都有可能出現三列的高度差別較大的狀況,真正的瀑布流是三列高度相差不大的。如下的瀑布流的具體實現
html
<div class="list"> <img src="../img/1.jpg" class="img1"> <img src="../img/2.jpg" class="img2"> <img src="../img/3.jpg" class="img3"> <img src="../img/4.jpg" class="img4"> <img src="../img/5.jpg" class="img5"> <img src="../img/6.jpg" class="img6"> <img src="../img/7.jpg" class="img7"> <img src="../img/8.jpg" class="img8"> <img src="../img/9.jpg" class="img9"> </div>
css
.list { position: relative; width: 600px; } .list img { position: absolute; }
js
document.addEventListener('DOMContentLoaded', function () { var listDOM = document.querySelector('.list'); var imgsDOM = listDOM.querySelectorAll('img'); waterfallFlowLayout(listDOM, imgsDOM, 3); }) /** * 瀑布流佈局 * * @param {DOM object} listDOM 存放圖片列表的容器DOM * @param {DOM object} imgsDOM 圖片DOM * @param {number} colsCount 列數 */ function waterfallFlowLayout (listDOM, imgsDOM, colsCount) { colsCount = colsCount || 3; // 默認3列 var currHeightArr = []; // 存放當前每列的總高度 var imgWidth = listDOM.offsetWidth / colsCount // 遍歷全部圖片DOM元素 for (var i = 0; i < imgsDOM.length; i++) { var imgDOM = imgsDOM[i]; imgDOM.style.width = imgWidth + 'px'; // 設置各個圖片的寬度 // 若是是第一行的就直接存高度,並設置top和left if (i < colsCount) { currHeightArr.push(imgDOM.offsetHeight); imgDOM.style.left = (i % colsCount) * imgWidth + 'px'; imgDOM.style.top = 0; } // 不然 else { var minNum = Math.min.apply(Math, currHeightArr); // 獲取最小值 var index = currHeightArr.indexOf(minNum); // 獲取最小值的下標 // 根據最小值下標獲得對應的DOM,獲取它的left賦給當前的left imgDOM.style.left = imgsDOM[index].offsetLeft + 'px'; imgDOM.style.top = minNum + 'px'; // 使用最小值做爲當前的top // 更新每列的總高度 currHeightArr[index] += imgDOM.offsetHeight; } } }
<div class="head">頭部</div> <div class="sidebar">側邊導航</div> <div class="main">主體內容</div> <div class="foot">底部</div>
.head, .foot, .sidebar, .main { position: absolute; } .head { top: 0; left: 0; right: 0; height: 80px; } .foot { bottom: 0; left: 0; right: 0; height: 60px; } .sidebar { top: 80px; bottom: 60px; left: 0; width: 100px; } .main { top: 80px; bottom: 60px; left: 100px; right: 0; }