css的結構與布局
1.自適應內部元素
在css中,不給元素一個height值時,元素會自適應其內部的元素高度,有時我們想讓元素的寬度也達到此效果,應用場景如下。
如下當前的這種布局,想要改成最外層的div的寬度由當前的圖片撐開的效果,這時就要用到min-content這個屬性值。
css代碼如下:
div {
/*只需要給最層的div的寬度值設置成min-content即可 */
width: min-content;
}
最終效果:
min-content將解析這個容器內部最大的不可斷行元素的寬度(即最寬的單詞,圖片或具有固定寬度的盒元素)
2.精確的控制表格的列寬
在使用表格布局時,當表格的內容不確定時,布局很難預測,因為表格的列寬是根據它的內容進行計算的,即使顯示的設置了width,也不會生效,還是會根據它的內容生成寬度。會根據加載的內容不停的重繪,直到加載完。
平時生成的表格如下:
為了讓設置的寬度生效,并且能讓過多的文字省略號顯示,解決辦法就是使用table-layout: fixed這個樣式
代碼如下:
table {
table-layout: fixed;
width: 100%; /*必須指定一個width,否則不生效*/
}
最終的效果如下:
3.根據兄弟元素的數量設置樣式
在一些應用場景中,我們可能需要根據元素的數量來設置樣式,比如說列表越來越長的時候,我們可能需要調整間隔或者大小,來減少長度,提升用戶的體驗
例如當列表項中共有4項的時候,選中所有列表,可以通過使用scss這種預處理器,編寫mixin
代碼如下:
/定義mixin/
@mixin n-items($n) {
&:first-child:nth-last-child(#{$n}),
&:first-child:nth-last-child(#{$n}) ~ & {
@content;
}
}
/調用方法/
li {
/當列表正好包含四項時 命中所有列表項/
/定義樣式/
@include n-items(4) {
width: 40px;
height: 100px;
background: red;
float: left;
margin: 10px;
}
}</code></pre>
效果如下:

4.根據兄弟元素的數量范圍匹配元素
應該場景同上,解決辦法也是編寫mixin
例如,當列表的總數是4或者更多時,選中所有列表項
代碼如下:
/定義mixin/
@mixin n-items($n) {
/當列表的總數是4或者更多時,選中所有列表項/
&:first-child:nth-last-child(#{$n + 4}),
&:first-child:nth-last-child(#{$n + 4}) ~ & {
@content;
}
}
// 改寫成 -n + 4 表示列表中有4個或者小于4時,選中所有
// 同理,如2 ~ 6時,設置 n + 2 ~ -n + 6
@mixin n-items($n) {
&:first-child:nth-last-child(#{$n + 2}):nth-last-child(#{$ -n + 6}),
&:first-child:nth-last-child(#{$n + 2}):nth-last-child(#{$ -n + 6}) ~ & {
@content;
}
}</code></pre>
5.滿幅的背景,定寬的內容
頁面上有很多布局是那種內容是固定寬的,背景是占滿整個視口的寬的,比如下面這種布局:

實現方式有很多種,一般我們實現的代碼結構都是這種的:
<footer>
<div class="wrapper">
</div>
</footer>
/ css樣式/
footer {
background: "#333";
}
.wrapper {
max-width: 900px;
margin: 1em auto;
}</code></pre>
其中margin: 1em auto;就是為了讓內容div居中,我們有一種更好的方式,只用一層DOM結構實現上面的布局,就是使用calc這個屬性。
實現代碼如下:
<footer>
/ 內容 /
</footer>
/ css樣式/
footer {
background: "#333";
/ 當瀏覽器不支持calc的時候回退一下/
padding: 1em;
padding: 1em calc(50% - 450px);
}</code></pre>
原理:百分比是按照視口的寬度來解析的,所以即使里面的內容不設置寬,也會給里面的內容留出 450*2的空間,達到了之前設置 max-width: 900px;的效果。
6.垂直居中
在css中水平居中比較簡單,對于行級元素,對它的父元素使用text-align: center;對于塊級元素,就對它自身使用margin: auto;對于垂直居中比較難處理,目前的解決方法有:
1.基于絕對定位的方法
(1) 當元素是定寬高的時候:
div {
width: 200px;
height: 100px;
position: absolute;
top: 50%;
left: 50%;
margin-top: -50px;
margin-left: -100px;
}
通過calc代碼可以簡化成下面這樣:
div {
width: 200px;
height: 100px;
position: absolute;
top: calc(50% - 50px);
left: calc(50% - 100px);
}
(2) 對于那些寬高不定的元素,實現方法如下:
div {
position: absolute;
top: 50%;
left: 50%;
transfrom: translate(-50%, -50%);
}
以上方案也有一個弊端就是必須是絕對定位的元素。
2.基于視口單位的方法
css3中定義了一些視口相關的單位:
-
vw 是與視口寬度相關的。1vw 實際上表示視口寬度的1%,而不是100%。
?
-
同樣,1vh表示視口高度的 1%
-
當視口寬度小于高度時,1vmin等于 1vw,否則等于 1vh。
-
當視口寬度大于高度時,1vmax等于 1vw,否則等于 1vh。
所以我們的垂直居中可以這樣實現:
div {
width: 200px;
padding: 2px 4px;
margin: 50vh auto 0;
transform: translateY(-50%);
}
**注:這里不使用50%,而是視口單位的原因是,margin的百分比是以父元素的寬度作為解析基準的,不論是margin-top or margin-left**
這種的方法是有局限性的,只能用在視口中居中的場景。
3.基于flex的方法
這種應該算是最佳的解決辦法:
實現方法:
body {
display: flex;
}
div {
margin: auto;
}</code></pre>
當使用flex布局時,使用margin: auto; 在水平和垂直方向都會居中。在不指定width的情況下,width: max-content;
flexbox還有一個公共就是可以將匿名的容器(就是那些沒有被標簽包住的文本節點)垂直居中:
<div>text</div>
div {
width: 100px;
height: 50px;
display: flex;
align-items: center;
justify-content: center;
}</code></pre>
7.緊貼底部的頁腳
具有塊級樣式的頁腳,當頁面內容足夠長的時候,頁腳會緊貼視口的底部;但是當頁面內容的長度 < 視口height - 頁腳height的時候,頁腳就會緊貼在內容的下面。一般的設計是給頁腳一個固定的height,這種顯然不健壯,在css3中有更好的解決方案。
(1) 最原始的固定高度的解決方案
html結構如下:
<header>
<h1>hello</h1>
</header>
<main>
<p>this is ...</p>
</main>
<footer>
<p>Made in ...</p>
<p>Made in ...</p>
</footer>
header {
height: 10px
}
footer p {
line-height: 1.5px;
padding: 1px;
margin: 1px;
}</code></pre>
假設當前的頁腳文字永遠不會折行,可以計算當前的頁腳的高度是:2 * 行高 + 3 * 段落垂直外邊距 + 頁腳垂直內邊距 = 2 * 1.5px + 3 * 1px + 1px = 7px;
main {
min-height: calc(100vh - 7px - 10px);
/* 避免內邊距或外邊距對高度記得算影響 */
border-sizing: border-box;
}
當header和main放在一個div里時,css樣式可以直接寫成 div{min-height: calc(100vh - 7px)};
這種方法的局限性是不允許文字折行,并且布局是這種簡單的布局,并且每當頁腳的尺寸變化時,都需要跟著調整min-height的值。
(2)基于flex的解決方案
body {
display: flex;
flex-flow: columm;
min-height: 100vh; / 至少會占據整個視口的高度 /
}
main {
flex: 1;
}</code></pre>
來自:https://segmentfault.com/a/1190000009138735