前面的話
常常聽說聖杯布局和雙飛翼布局,以為是兩個很高級的語匯。但實際上,他們只是三欄式布局的兩種布局方法而已。本文將介紹三欄式布局的4種思路
float
【1】聖杯布局
聖杯布局使用float、負margin和relative,不需要添加額外標簽。.main元素設置padding,為兩側定寬元素留出位置。內容元素設置100%寬度,占據中間位置。而兩側定寬元素通過設置負margin和relative的偏移屬性配合,到達相應位置
缺點: 並沒有實現等高布局;使用了相對定位,擴展性不好
<style> body,p{margin: 0;} .top,.bottom{ height: 30px; } .middle{ padding: 0 120px; overflow: hidden; } .main{ width: 100%; float: left; } .left,.right{ float: left; width: 100px; position: relative; } .left{ margin-left: -100%; left: -120px; } .right{ margin-left: -100px; right: -120px; } </style>
<div class="parent" id="parent" style="background-color: lightgrey;"> <div class="top" style="background-color: lightblue;"> <p>top</p> </div> <div class="middle" style="background-color: pink;"> <div class="main" style="background-color: lightcoral;"> <p>main</p> <p>main</p> </div> <div class="left" style="background-color: orange;"> <p>left</p> </div> <div class="right" style="background-color: lightsalmon;"> <p>right</p> </div> </div> <div class="bottom" style="background-color: lightgreen;"> <p>bottom</p> </div> </div>
【2】雙飛翼布局
雙飛翼布局在聖杯布局的基礎上,通過為.main元素外添加一層div結構,不使用相對定位。在.main元素上設置margin。兩側的定寬列通過負margin來占據.main元素的margin區域
缺點: 並沒有實現等高布局,增加了html結構
<style> body,p{margin: 0;} .top,.bottom{height: 30px;} .middle{overflow: hidden;} .mainWrap{ width: 100%; float: left; } .main{margin: 0 120px;} .left,.right{ float: left; width: 100px; } .left{margin-left: -100%;} .right{margin-left: -100px;} </style>
<div class="parent" id="parent" style="background-color: lightgrey;"> <div class="top" style="background-color: lightblue;"> <p>top</p> </div> <div class="middle" style="background-color: pink;"> <div class="mainWrap"> <div class="main" style="background-color: lightcoral;"> <p>main</p> <p>main</p> </div> </div> <div class="left" style="background-color: orange;"> <p>left</p> </div> <div class="right" style="background-color: lightsalmon;"> <p>right</p> </div> </div> <div class="bottom" style="background-color: lightgreen;"> <p>bottom</p> </div> </div>
【3】float + box-sizing + background-clip
.main元素的border區域為兩側定寬列的所在區域,實現偽等高效果;設置.main的padding和background-clip來實現元素間隔。兩側元素通過負margin調整到.main元素的border區域
缺點: 兼容性不好
<style> body,p{margin: 0;} .top,.bottom{height: 30px;} .middle{overflow: hidden;} .main{ float: left; width: 100%; border-left: 100px solid lightgrey; border-right: 100px solid lightgrey; padding: 0 20px; background-clip: content-box; box-sizing: border-box; } .left,.right{ float: left; width: 100px; } .left{margin-left: -100%;} .right{margin-left: -100px;} </style>
<div class="parent" id="parent" style="background-color: lightgrey;"> <div class="top" style="background-color: lightblue;"> <p>top</p> </div> <div class="middle" style="background-color: pink;"> <div class="main" style="background-color: lightcoral;"> <p>main</p> <p>main</p> </div> <div class="left" > <p>left</p> </div> <div class="right" > <p>right</p> </div> </div> <div class="bottom" style="background-color: lightgreen;"> <p>bottom</p> </div> </div>
absolute
設置子元素的top:0;bottom:0;使得所有子元素的高度都和父元素的高度相同,實現等高效果
缺點: 需要為.middle元素設置高度,擴展性較差
<style> body,p{margin: 0;} .top,.bottom{height: 30px;} .middle{ position: relative; height: 40px; } .left,.right,.main{ position: absolute; top: 0; bottom: 0; } .left{width: 100px;} .right{ width: 100px; right: 0; } .main{ left: 120px; right: 120px; } </style>
<div class="parent" id="parent" style="background-color: lightgrey;"> <div class="top" style="background-color: lightblue;"> <p>top</p> </div> <div class="middle" style="background-color: pink;"> <div class="main" style="background-color: lightcoral;"> <p>main</p> <p>main</p> </div> <div class="left" style="background-color: lightseagreen;" > <p>left</p> </div> <div class="right" style="background-color: lightcyan;" > <p>right</p> </div> </div> <div class="bottom" style="background-color: lightgreen;"> <p>bottom</p> </div> </div>
flex
flex中的伸縮項目默認都拉伸為父元素的高度,可實現等高效果。通過改變伸縮項目的order,可以實現元素順序調換的效果
缺點: 兼容性不高
<style> body,p{margin: 0;} .top,.bottom{height: 30px;} .middle{display: flex;} .left,.right{width: 100px;} .right{order: 2;} .main{ order: 1; flex: 1; margin: 0 20px; } </style>
<div class="parent" id="parent" style="background-color: lightgrey;"> <div class="top" style="background-color: lightblue;"> <p>top</p> </div> <div class="middle" style="background-color: pink;"> <div class="main" style="background-color: lightcoral;"> <p>main</p> <p>main</p> </div> <div class="left" style="background-color: lightseagreen;" > <p>left</p> </div> <div class="right" style="background-color: lightcyan;" > <p>right</p> </div> </div> <div class="bottom" style="background-color: lightgreen;"> <p>bottom</p> </div> </div>
grid
<style> body,p{margin: 0;} .top,.bottom{height: 30px;} .middle{display:grid;grid-template-columns:100px 1fr 100px;grid-gap:20px;} .main{grid-area:1/2/2/3;} </style>
<div class="parent" id="parent" style="background-color: lightgrey;"> <div class="top" style="background-color: lightblue;"> <p>top</p> </div> <div class="middle" style="background-color: pink;"> <div class="main" style="background-color: lightcoral;"> <p>main</p> <p>main</p> </div> <div class="left" style="background-color: lightseagreen;" > <p>left</p> </div> <div class="right" style="background-color: lightcyan;" > <p>right</p> </div> </div> <div class="bottom" style="background-color: lightgreen;"> <p>bottom</p> </div> </div>
總結
由於限定了主要內容元素在html結構中位於前面,通過css樣式改變將其位置調換到中間的前提,所以思路並不是很多。float浮動流的元素可以通過負margin調換位置;absolute絕對定位流的元素可以通過偏移屬性調換位置;flex彈性盒模型可以通過order屬性調換位置;grid通過grid-area調換位置。而處於正常流中的元素除了使用relative外,使用負margin是無法調換位置的,所以table、inline-block等布局方式在此前提下不是很實用。