前言
面試高頻考點,之前就記了個比較有名的聖盃佈局,沒想到面試官問了我上下欄固定、中間自適應的佈局,措手不及。藉此彌補下CSS佈局方面的知識。
(以下程式碼我都在瀏覽器上跑過,基本能夠實現佈局要求。)
上下固定,中間自適應
在網上找了下關於上中下佈局的文章,發現資料很少,所以總結的不是很好,如果大家有更完整、更優美的辦法可以在評論區留言。
<div class="top-center-bottom">
<div class="top">top</div>
<div class="center">center</div>
<div class="bottom">bottom</div>
</div>
複製程式碼
position: absolute 定位
.top-center-bottom>div{
position:absolute;
}
.top{
top:0;
height:100px;
width:100%;
background:red;
}
.bottom{
bottom:0;
height:100px;
width:100%;
background:red;
}
.center{
bottom:100px;
top:100px;
width:100%;
overflow: auto;
background:green;
}
複製程式碼
overflow
屬性規定當內容溢位元素框時發生的事情。
overflow: auto;
如果內容被修剪,則瀏覽器會顯示滾動條以便檢視其餘的內容。overflow: hidden;
內容會被修剪,並且其餘內容是不可見的。
使用彈性盒子flex
.top-center-bottom{
display: flex;
height: 100%; /*要指定高度*/
flex-direction: column; /*佈局從上到下排列*/
}
.top,.bottom{
display: flex; /*這是為居中 文字的*/
justify-content: center; /*文字 水平居中*/
align-items: center; /*文字垂直居中*/
}
.top{
height: 100px;
background: #665aa4;
}
.center{
flex-grow: 1; /*不知道和 flex: 1 有啥區別*/
text-align: center;
background: #3dc95d;
}
.bottom{
height: 100px;
background: #fc430b;
}
複製程式碼
flex-direction:colum;
使整體佈局從上到下排列
flex-grow:1;
應用於main,使得main自動填充剩餘空間
flex-grow
的使用避免了當main內容過少時footer部分會被提升到頁面上方的問題(傳統方式上可能需要靠絕對定位來解決了~)
其他可做參考的寫法:
<div class="container">
<div class="flex-item">
<div style="height: 100px;line-height: 100px;">top</div>
</div>
<div class="flex-item">
<div style="height: 800px;color: #fff;">
<div class="center">center</div>
</div>
</div>
<div class="flex-item">
<div style="height: 100px;line-height: 100px;">bottom</div>
</div>
</div>
複製程式碼
html, body{
height:100%;
margin: 0;
padding: 0;
}
.container{
height: 100%;
display: flex;
flex-direction: column;
text-align: center;
}
.flex-item:nth-child(1), flex-item:nth-child(3){
flex-grow:0;
flex-shrink: 0;
background-color: #ababab;
}
.flex-item:nth-child(2){
flex-grow:1;
flex-shrink: 1;
background-color: #000;
overflow-y: auto;
}
.center{
position: fixed;
top: 50%;
left: 50%;
margin-top: -10px;
margin-left: -24px;
}
複製程式碼
flex
屬性是flex-grow, flex-shrink 和 flex-basis
的簡寫,預設值為0 1 auto
。 flex-basis
指定了 flex 元素在主軸方向上的初始大小。
該屬性有兩個快捷值:
auto (1 1 auto)
:元素會根據自身的寬度與高度來確定尺寸none (0 0 auto)
:元素會根據自身寬高來設定尺寸
table / grid
因為太多了我也記不住,記住前兩個常用的應該就可以了。
左右固定,中間自適應
絕對定位法
<div class="left">Left</div>
<div class="main">Main</div>
<div class="right">Right</div>
複製程式碼
<!--簡單的進行CSS reset-->
body,html{
height:100%;
padding: 0px;
margin:0px;
}
<!--左右絕對定位-->
.left,.right{
position: absolute;
top:0px;
background: red;
height:100%;
}
.left{
left:0;
width:100px;
}
.right{
right:0px;
width:200px;
}
<!--中間使用margin空出左右元素所佔據的空間-->
.main{
margin:0px 200px 0px 100px;
height:100%;
background: blue;
}
複製程式碼
缺點:如果中間欄含有最小寬度限制,或是含有寬度的內部元素,當瀏覽器寬度小到一定程度,會發生層重疊的情況。
聖盃佈局
<div class="container">
<!-- 優先渲染 -->
<div class="center">
center
</div>
<div class="left">
left
</div>
<div class="right">
right
</div>
</div>
複製程式碼
使三欄浮動,並相對定位,給左右兩個容器設定200px的寬度、中間的容器設定100%的寬度。
body,html {
height:100%;
padding: 0;
margin: 0
}
.container {
padding: 0 200px;
height: 100%;
}
.container > div {
position: relative;
float: left;
height: 100%;
}
.center {
width: 100%;
background-color: red;
}
.left {
width: 200px;
left: -200px;
margin-left: -100%;
background-color: green;
}
.right {
width: 200px;
right: -200px;
margin-left: -200px;
background-color: blue;
}
複製程式碼
步驟:
- 由於浮動的關係,給 left 設定
margin-left: -100%
即可使左側欄浮動到 center 上面,並位於 center 左側之上。 - 同樣為 right 設定
margin-left: -200px
,這裡的長度等於 right 的長度 - 這時 center 的兩側被 left 和 right 覆蓋了,因此給 container設定
padding: 0 200px
- 由於 left 和 right 也同時往中間縮,因此給 left 和 right 分別設定
left: -200px; right: -200px
,往兩側分別偏移自身的寬度去覆蓋掉 contaniner 使用padding後的空白位置。
相關解釋如下:
- 中間部分需要根據瀏覽器寬度的變化而變化,所以要用100%,這裡設左中右向左浮動,因為中間100%,左層和右層根本沒有位置上去
- 把左層margin負100後,發現left上去了,因為負到出視窗沒位置了,只能往上挪
- 按第二步這個方法,可以得出它只要挪動視窗寬度那麼寬就能到最左邊了,利用負邊距,把左右欄定位
- 但由於左右欄遮擋住了中間部分,於是採用相對定位方法,各自相對於自己把自己挪出去,得到最終結果
缺點:在視窗變小到限定值時佈局會亂掉,需要給它加上一個寬度限制min-width。而且聖盃佈局實際看起來是複雜的後期維護性也不是很高,在淘寶UED的探討下,出來了一種新的佈局方式就是雙飛翼佈局。
雙飛翼佈局
雙飛翼佈局給center 部分包裹了一個main,通過設定margin主動地把頁面撐開,為左右兩欄div留出位置。這時視窗寬度過小時就不會出現混亂的情況了。
<!-- 優先渲染 -->
<div class="center">
<div class="inner">
center
</div>
</div>
複製程式碼
body,html {
height:100%;
padding: 0;
margin: 0
}
.container {
height: 100%;
}
.container > div{
float: left;
height: 100%;
}
.center {
width: 100%;
background-color: red;
}
.left {
width: 200px;
margin-left: -100%;
background-color: green;
}
.right {
width: 200px;
margin-left: -200px;
background-color: blue;
}
/*新增*/
.inner {
margin: 0 200px;
}
複製程式碼
聖盃和雙飛翼佈局的不同在於解決“中間欄div內容不被遮擋”問題的思路不一樣:
聖盃佈局為了中間div內容不被遮擋,將父容器設定了左右padding-left
和padding-right
後,將左右兩個div用相對佈局position:relative
並分別配合right和left屬性,以便左右兩欄div移動後不遮擋中間div;
雙飛翼佈局為了中間div內容不被遮擋,直接在中間div內部建立子div用於放置內容,在該子div裡用margin-left
和margin-right
為左右兩欄div留出位置。增加多一個div就可以不用相對佈局了,只用到了浮動和負邊距。
浮動
//注意元素次序
<div class="left">Left</div>
<div class="right">Right</div>
<div class="main">Main</div>
複製程式碼
body,html {
height:100%;
padding: 0;
margin: 0
}
<!--左欄左浮動-->
.left {
background: red;
width: 100px;
float: left;
height: 100%;
}
<!--中間自適應-->
.main {
background: blue;
height: 100%;
margin:0px 200px 0px 100px;
}
<!--右欄右浮動-->
.right {
background: red;
width: 200px;
float: right;
height: 100%;
}
複製程式碼
flex佈局
<div class="flex">
<div class="left">left</div>
<div class="main">middle</div>
<div class="right">right</div>
</div>
複製程式碼
.flex {
display: flex;
flex-flow: row;
}
.left{
width: 180px;
height: 100px;
background-color: red;
}
.main{
flex: 1;
height: 100px;
background-color: blue;
}
.right {
width: 200px;
height: 100px;
background-color: green;
}
複製程式碼
總結
左中右佈局的話記住三種應該就沒問題了,聖盃和雙飛翼佈局需要理解,別像我面試的時候只憋出來一個聖盃,還忘了具體怎麼實現......都是淚。
還有瀏覽器的適配問題,因為被問到了,頭疼......大家有時間的話自己可以搜一下,之後有時間的話我再補充吧,應付面試的話以上方法應該就夠了。