看文章之前,先來看兩個例子。這是我們在專案中最常見的專案佈局方式。
案例一:多個容器按照相同間距水平排列。
案例二:常見的選單導航
看到這兩個案例時,你可以先短暫的想想平時都是如何實現的,很多同學的答案應該是這樣的。
// 案例一
<div class="demo">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
.demo {
padding: 1em 0;
width: 470px;
background-color: #e5e5e5;
overflow: hidden;
}
.item {
float: left;
margin-left: 10px;
width: 150px;
height: 100px;
background-color: #fff;
border: 1px solid #999999;
box-sizing: border-box;
}
.item:first-child {
margin-left: 0;
}
//案例二
<div class="demo2">
<a href="" class="nav">導航1</a>
<a href="" class="nav">導航2</a>
<a href="" class="nav">導航3</a>
</div>
.demo2 {
width: 200px;
background-color: cadetblue;
}
.nav {
display: block;
width: 100%;
border-bottom: 1px solid #000;
color: #fff;
}
複製程式碼
效果我們是做到了,但是這裡所有畫素都是你自己固定計算的。
比如第一個例子中,父容器的寬度為 470 = 3*150 + 20。如果在不使用 flex 佈局的情況下,你想讓三個元素自適應螢幕寬度有什麼好辦法?
或者你想把三個元素擴充套件成四個,這個時候你就需要手動計算每個元素的寬度。這樣好像很是麻煩。
那今天就來說說,如何利用「流」的特性,解決平時在專案中遇到的一些佈局問題。
在剛開始學習 CSS 時我們都會經常聽到這麼一個概念叫「文件流」,很多人並沒有深究文件流是為何物。
那什麼是「文件流」呢?
文件流
文件流:是引導網頁中的元素排列和佈局的,它預設的方向是從左向右,從上而下。
而「流」具有最大的一個特點就是自適應性。你可以把它想象成像水流一樣,當水流倒入一個容器時,它會自動充滿整個容器。而 CSS 中的文件流,其表現是一致的,有異曲同工之妙。
不僅如此,你也經常會聽到「脫離文件流」,比如浮動,絕對定位等都可以脫離文件流,而脫離文件流不是本文要說的重點,所以就不展開多說,今天主要是聊一聊「流的自適應性」。
文件流中有兩個比較重要的概念:塊級元素(block)、內聯元素(inline),對應到最具代表性的元素就是<div>
、<span>
。
塊級元素預設會充滿整個螢幕,具有自適應性,而內聯元素預設則是水平排列。
你可以想象為塊級元素就想是水流一樣充滿容器,而內聯元素就是漂浮在水裡按照從左到右排列的物體。
在專案中會經常碰到
display:block
這個屬性。但注意,它與塊級元素不是同一個東西。display:table
,也屬於塊級元素。
失去流動性
到這裡你應該明確了流的特性,其實很多人都知道「文件流」這個概念,但卻沒有好好的去利用,從而給自己增加了一些不必要的麻煩。
比如以前我會寫出這樣的 CSS:
span {
display: block;
width: 100%;
}
複製程式碼
如果明白流的特性的話,其實 width: 100%;
這個屬性是多餘的,因為塊級元素在流佈局中預設是自動充滿容器的。
你是否也中槍寫過這種 CSS ?歡迎在評論區說出你的問題。
但如果僅僅只是多了一條屬性,其實也就是增加了一行程式碼顯得不那麼簡潔而已,可事情總是沒有那麼簡單。
一旦你給元素新增了寬度(width)屬性,它就會失去流動性,即便是它的值為 100%,也是會失去。
對,你沒有看錯,只要有了寬度屬性,它就會失去了它最牛逼的流動性。這樣就變的毫無價值。
比如開頭中導航案例,如果給導航加入一些邊距。就會出現不好的效果。
.nav {
display: block;
padding: 10px; //新增的邊距
width: 100%;
border-bottom: 1px solid #000;
color: #fff;
}
複製程式碼
而如果我們把寬度屬性去掉,就會得到完美的展示效果。
.nav {
display: block;
padding: 10px;
border-bottom: 1px solid #000;
color: #fff;
}
複製程式碼
可能你之前並沒有意識到,加入寬度屬性帶來的危害。
但當你看到這篇文章之後,你應該警惕寬度給流動性帶來的危害,儘量少用寬度,甚至是「無寬度」。
在此之前我相信很多夥伴在專案彙總遇到過超出寬度的情況,但很少有人去探究,所以很多人都會發揮他特有的計算能力,然後寫出如下程式碼。
.nav {
display: block;
padding: 10px;
width: 180px; // 200px - 10px*2
border-bottom: 1px solid #000;
color: #fff;
}
複製程式碼
貌似也實現了該有的功能,不過這種缺點我們顯而易見,就是太過固定,任何一點的改動都需要你重新計算。
可能有人會說,兄die,我的計算能力很驚人,你管的著嗎,好吧這,波算我輸。
那為什麼加了寬度屬性會超出,而不加寬度屬性就可以了呢?
原來是因為,當元素不設定寬度屬性時或者是 width:auto
,元素的margin、border、padding 可以自動分配空間。
一旦,我們設定了固定的寬度屬性,就算是100%,它就會根據 CSS 的盒模型進行計算。從而失去了自動分配空間的流動性。
至於如何計算的細節,因為盒模型的不同,所以寬度的作用就不同,它包含的東西也就不一樣。具體不在多說。
兄die,這時候知道「無寬度」有多牛逼了吧。
因為這裡我提到了盒模型,你會想到把上面的案例,改變下盒模型不就行了嗎?比如我們這麼做:
.nav {
display: block;
padding: 10px;
width: 100%;
border-bottom: 1px solid #000;
box-sizing: border-box; //改變盒模型
color: #fff;
}
複製程式碼
確實在這個案例中是可以這麼用的,但是如果想實現案例一的水平有間距排列問題,就有點力不從心了。
由於 CSS 盒模型,是不計算 margin 的,水平排列可以很容易實現,但是想要有相同間距,就比較難以實現。
這個時候你就可以嘗試利用流的特性,來很好的實現這個方案。
寬度分離
這時候我們可以利用流的特性,進行寬度分離。
<div class="demo">
<div class="item">
<div class="child">內容</div>
</div>
<div class="item">
<div class="child">內容</div>
</div>
<div class="item">
<div class="child">內容</div>
</div>
<div class="item">
<div class="child">內容</div>
</div>
</div>
.demo {
padding: 1em;
background-color: #e9e9e9;
overflow: hidden;
}
.item {
float: left;
width: 25%;
}
.child {
margin: 0 10px;
padding: 10px;
border: 1px solid #ccc;
}
複製程式碼
你會發現,無論你如何改變它的 margin、padding、border 它都會自動填充分配空間,再也不會出現佈局錯亂,超出等等一系列的情況。
以上就是利用流的特性,讓佈局變得簡單、靈活。當然,流的特性不僅僅限於這兩種佈局。
還比如表單的佈局,通常表單的佈局都是比較難處理的一點,這時候你不妨試試利用「無寬度」、「寬度分離」原則嘗試一下,也許會有新的發現。小夥伴們趕緊放飛下自己的想象力吧。
最後,如果覺得文章不錯,對你有所啟發,點贊是一種態度也是一種認可。
微信公眾號:六小登登,更多幹貨文章,這裡有我的很多故事,歡迎一起交流。
本文參考:《CSS世界》