## 響應式之柵格系統
1. 為什么響應式開發需要柵格化?
2. 柵格化解決了什么問題?
3. 柵格化是怎么工作,是怎樣解決問題的?
4. 怎么使用合適的柵格化類?
閱讀完本文后,相信你就會有這些問題的答案了。
*****
https://v3.bootcss.com/css/#grid-media-queries
```css
/* 超小屏幕(手機,小于 768px) */
/* 沒有任何媒體查詢相關的代碼,因為這在 Bootstrap 中是默認的(還記得 Bootstrap 是移動設備優先的嗎?) */
/* 小屏幕(平板,大于等于 768px) */
@media (min-width: @screen-sm-min) { ... }
/* 中等屏幕(桌面顯示器,大于等于 992px) */
@media (min-width: @screen-md-min) { ... }
/* 大屏幕(大桌面顯示器,大于等于 1200px) */
@media (min-width: @screen-lg-min) { ... }
```
移動優先,樣式先從移動端開始寫,沒有查詢代碼,默認就代表為移動端準備的。然后依次考慮屏幕變大,逐步覆蓋、重寫樣式以滿足屏幕越大時的樣式,當然 “偶爾也會在媒體查詢代碼中包含 max-width 從而將 CSS 的影響限制在更小范圍的屏幕大小之內。”

bootstrap 系統的柵格化起作用是通過作用于元素的 `width: {0~100}%` 和 `float: left` 兩個樣式(布局樣式)而生效的。為元素添加這兩種樣式屬性達到柵格效果,我們將這種方式稱之為 **柵格作用** ,而 柵格作用 是有 閾值 的,只有在屏幕滿足閾值 時 柵格作用才會生效(即 `>=閾值`),`.col-xs-`、`.col-sm-`、`.col-md-`、`.col-lg-` 就是用來控制這個 柵格作用 生效的 閾值的(我們稱之為 `閾值類`)。
比如:`.col-md-` 表示 在 `中等屏幕 桌面顯示器 (≥992px)` 時 適配元素才會具有 柵格作用。所以你看到的效果就是,在屏幕 ≥992px 時,適配元素具有 柵格的列排列效果(`width: {0~100}%` 和 `float: left`),在屏幕 <992px 時,適配元素不在具有 柵格作用,變的和普通元素一樣(`width: 100%;
`),就是普通的塊級元素,不在水平排列,而是獨占一行,即傳統的行排列。
那么 這個通過 閾值(閾值類) 來控制 柵格作用 是否有效 的做法有什么用呢?要回答這個問題,就要弄清楚下面這些問題?
**Q:手機和平板、PC的區別?**
A:我們知道,移動網站的布局不能照搬PC上的布局,手機屏幕比較窄,與PC相比,在內容布局上就有很大的差異,PC上很多左右水平布局,而在手機上,為了不出現水平滾動條,內容更多是單行排列(較小的內容也可以水平排列,這也是我們柵格化解決的問題之一)。平板介于手機和PC的中間。
**Q:為什么你想將某些元素水平排列?**
A:水平排列可以展示更多的信息,通常只要屏幕足夠寬,我們就越想利用水平排列以展示更多內容。
**Q:為什么你想讓一個元素總是水平排列?**
A:這個元素比較小,我認為即使屏幕再小也能顯示。
**Q:為什么你要控制某些元素只在大屏幕中才水平排列顯示?**
這個元素比較大,我認為小屏幕下水平一行展示不了(會出現水平滾動條或溢出截斷),所以只在大屏幕下水平排列,小屏幕下還是傳統的行排列。
**Q:為什么有時候用多個 閾值(多個`.col-`)來控制 元素的 柵格作用 是否有效?**
在屏幕越小的過程中,`.col-lg-`、`.col-md-`、`.col-sm-` **是逐漸媒體查詢失效的** (**注意 `.col-xs-` 自始至終都不會失效,而是被覆蓋的,要知道它不在媒體查詢之內哦**),所以如果你想讓元素在屏幕越小的這個過程中 保持 柵格作用,那么你就需要 多個 閾值來控制。
反之 在屏幕越大的過程中,`.col-xs-`、`.col-sm-`、`.col-md-`、`.col-lg-` **是逐漸被媒體查詢覆蓋的**。
反復體驗這個屏幕變化的過程,你就會知道在什么時候為元素使用合適的 閾值類名了。
**換句話來說,就是 你想為多種設備 提供不同的 展示效果,想讓元素在不同設備下有不同的顯示效果。**
一般情況下,我們只使用 `.col-sm-`就可以了,只區分手機就行了,平板和PC都展示一樣的效果,即表示我們只區分 **是否為手機** (PC有柵格效果,手機版為傳統的行排列)。
*****
### 柵格系統-特性實例demo
https://material.io
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<style>
// 注意這在 bootstrap.min.css 的前面 ,以不影響柵格類,滿足bootstrap的柵格條件時會被覆蓋的
[class*=col-] {
// 過度效果讓你更好的觀察到柵格元素的布局變化
transition: all 0.3s ease-in-out;
// 事實上100%為塊級元素的默認值,這里顯式的聲明下,以配合后面的柵格以實現過度效果
width: 100%;
}
.demo .demo-wrap {
margin: 30px auto;
border: 1px #dedede dashed;
}
.demo .demo-wrap .demo-content {
height: 100px;
line-height: 100px;
color: #fff;
text-align: center;
border-radius: 15px;
transition: all 0.3s ease-in-out;
margin: 20px 0;
overflow: hidden;
}
.demo .demo-wrap:nth-child(1) .demo-content {
background-color: #ff86b1;
}
.demo .demo-wrap:nth-child(2) .demo-content {
background-color: #5179ff;
}
.demo .demo-wrap:nth-child(3) .demo-content {
background-color: #1fb729;
}
.demo .demo-wrap:nth-child(4) .demo-content {
background-color: #fba223;
}
.demo .demo-wrap:nth-child(5) .demo-content {
background-color: #b749ff;
}
</style>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
</head>
<body>
<div class="demo">
<div class="container demo-wrap">
<div class="row">
<div class="col-xs-8 col-sm-4 col-md-4 col-lg-4"><div class="demo-content">col-xs-8 col-sm-4 col-md-4 col-lg-4</div></div>
<div class="col-xs-4 col-sm-4 col-md-4 col-lg-4"><div class="demo-content">col-xs-4 col-sm-4 col-md-4 col-lg-4</div></div>
<div class="col-xs-12 col-sm-4 col-md-4 col-lg-4"><div class="demo-content">col-xs-12 col-sm-4 col-md-4 col-lg-4</div></div>
</div>
</div>
<div class="container demo-wrap">
<div class="row">
<div class="col-xs-4"><div class="demo-content">col-xs-4</div></div>
<div class="col-xs-4"><div class="demo-content">col-xs-4</div></div>
<div class="col-xs-4"><div class="demo-content">col-xs-4</div></div>
</div>
</div>
<div class="container demo-wrap">
<div class="row">
<div class="col-sm-4"><div class="demo-content">col-sm-4</div></div>
<div class="col-sm-4"><div class="demo-content">col-sm-4</div></div>
<div class="col-sm-4"><div class="demo-content">col-sm-4</div></div>
</div>
</div>
<div class="container demo-wrap">
<div class="row">
<div class="col-md-4"><div class="demo-content">col-md-4</div></div>
<div class="col-md-4"><div class="demo-content">col-md-4</div></div>
<div class="col-md-4"><div class="demo-content">col-md-4</div></div>
</div>
</div>
<div class="container demo-wrap">
<div class="row">
<div class="col-lg-4"><div class="demo-content">col-lg-4</div></div>
<div class="col-lg-4"><div class="demo-content">col-lg-4</div></div>
<div class="col-lg-4"><div class="demo-content">col-lg-4</div></div>
</div>
</div>
</div>
</body>
</html>
```
*****
### 響應式開發注意事項
#### 1. 移動優先:媒體查詢代碼的書寫順序
>[tip] **注意移動優先,任何時候,媒體查詢代碼都有寫在后面,否則因為css覆蓋特性而可能不會生效,而不在媒體查詢之內的代碼默認就為移動端的。** (媒體查詢代碼的書寫順序對css覆蓋特性的影響和普通代碼是一樣的)
```css
.login-btn {
border: 1px #828282 solid;
padding: 5px 12px !important;
border-radius: 15px;
font-size: 15px;
margin-top: 18px;
}
/* 平板時的導航樣式 768px <= x < 992px */
@media (min-width: 768px) and (max-width: 992px) {
.navbar .container {
width: 100%;
}
.navbar-nav>li>a {
padding: 20px;
}
.login-btn {
// 如果順序不對,這里會被覆蓋
margin-top: 13px;
}
}
--------------------------
要特別注意以下書寫規則,不按照這個規則書寫,會有問題
@media (min-width: a){}
@media (min-width: b){}
@media (min-width: c){}
這里 a < b < c
@media (max-width: a){}
@media (max-width: b){}
@media (max-width: c){}
這里 c < b < a
```
#### 2. 媒體查詢代碼要寫精確
如果你發現需要經常使用 `!important`,則要思考是不是你的媒體查詢代碼寫的不夠精確,要知道這可不是一個好的信號,過多的 `!important` 會使你的代碼在不知不覺中陷入這種優先級爭奪的泥潭中。大多數情況下,只要媒體查詢代碼寫精確了(**有區間限定值**),都是可以避免 `!important` 的,只有特殊情況下,在沒有更好的辦法了時才用它。
比如:
```css
// 默認沒有媒體查詢即為手機
// 1. 平板
// 沒有區間限定值時表示并不準確,例如:此時不只表示為 平板,還可能為桌面顯示器、大桌面顯示器;沒有限定區間的媒體查詢都可能表示多種設備
@media (min-width: 768px) {}
// 2. 平板
@media (min-width: 768px) and (max-width: 992px) {}
// 中等屏幕 桌面顯示器
@media (min-width: 992px) and (max-width: 1200px) {}
// 大屏幕 大桌面顯示器
@media (min-width: 1200px) {}
```
顯然使用第二種媒體查詢表示平板要更加精確,使用精確的媒體查詢能避免后面很多不必要的麻煩。
#### 3. 移動優先
移動優先,通常都是在媒體查詢里面寫布局樣式,不在媒體查詢里面的代碼,直接就是移動端的和元素本來的基本樣式,因為元素形態樣式不論多大屏幕小都是相同的,不同的基本都是布局樣式和大小等。當然也有例外,那就是你想讓某元素在不同屏幕下呈現不同的效果,這也沒什么不可以,但是通常這種情況很少見,因為這不能使移動端到pc端過度時,頁面整體內容保持一致,這就像是兩個網站了。
**bootstrap 是如何體現自己是移動優先的?**
```css
.collapse {
display: none;
}
@media (min-width: 768px)
bootstrap.css:4186
.navbar-collapse.collapse {
display: block!important;
height: auto!important;
padding-bottom: 0;
overflow: visible!important;
}
```
先直接定義的就是移動端的,然后才是大屏幕的。
#### 4. 如果不想重用
https://v3.bootcss.com/css/#grid-media-queries
```css
/* 超小屏幕(手機,小于 768px) .col-xs- */
/* .col-xs- 不在媒體查詢中 */
/* 沒有任何媒體查詢相關的代碼,因為這在 Bootstrap 中是默認的(還記得 Bootstrap 是移動設備優先的嗎?) */
/* 但是如果不想重用,或實際重用較少,導致需要覆蓋太多屬性比較麻煩時,也可以用媒體查詢 */
/* 另外在實際編碼時往往很難嚴格的遵守“移動優先”(沒有任何媒體查詢相關的代碼就是移動端的代碼)的編碼方式,所以也可以違背常規,此時也需要用媒體查詢 */
/* 超小屏幕(手機,小于 768px) */
@media (max-width: 768px) {
/* 不需要重用的屬性 */
/* ... */
}
/* 小屏幕(平板,大于等于 768px) .col-sm- */
@media (min-width: 768px) {}
/* 中等屏幕(桌面顯示器,大于等于 992px) .col-md- */
@media (min-width: 992px) {}
/* 大屏幕(大桌面顯示器,大于等于 1200px) .col-lg- */
@media (min-width: 1200px) {}
```
15英寸筆記本屏幕一般為 `1366px`
>[tip] <768px 時導航折疊,=768px 時不會折疊,而iPad剛好是 768px ,所以這里寫代碼時要注意一下。(還有柵格化生效的節點也包括等于,有時這也需要注意)
*****
### 擴展
[Bootstrap柵格系統詳解,響應式布局 - 流風,飄然的風 - 博客園](https://www.cnblogs.com/zdz8207/p/Bootstrap-row-container.html)
> Bootstrap 柵格系統的精妙之處, 通過container, row, column都有15px的padding槽邊和 row的margin -15px設置,巧妙實現在 column 中嵌套 row進行nesting 擴展(超過12列),而不需要再套一層 container
>
> 正確使用:container > row > column 或 column > row > column (因為column 和 container 有同樣的內補)
[手機屏幕尺寸大全-25學堂](https://www.25xt.com/screen/phone.html)
[一行css代碼搞定響應式布局](https://mp.weixin.qq.com/s/oIszJeXGWA0Xfo0SyFqhnA)
[關于響應式布局,你必須要知道的](https://mp.weixin.qq.com/s/y0a5t3Kd-GWACRlEg1cprQ)
[響應式布局新方案](https://mp.weixin.qq.com/s/qi92_WQz2CaqYHTtvE7SzA)
*****
### 如何學習
學一個東西,一定要有學習過程的學習筆記(提問,思考驗證,記錄等),然后還要動手實踐,并且要做實際項目來印證鍛煉。這樣才能真正掌握。
(那一晚做夢都是柵格系統布局,屏幕逐漸變大,覆蓋,逐漸變小,失效……)
*****
last update:2018-12-9 15:08:33
- 開始
- 微信小程序
- 獲取用戶信息
- 記錄
- HTML
- HTML5
- 文檔根節點
- 你真的了解script標簽嗎?
- 文檔結構
- 已經落后的技術
- form表單
- html實體
- CSS
- css優先級 & 設計模式
- 如何編寫高效的 CSS 選擇符
- 筆記
- 小計
- flex布局
- 細節體驗
- Flex
- Grid
- tailwindcss
- JavaScript
- javascript物語
- js函數定義
- js中的數組對象
- js的json解析
- js中數組的操作
- js事件冒泡
- js中的判斷
- js語句聲明會提前
- cookie操作
- 關于javascript你要知道的
- 關于innerHTML的試驗
- js引擎與GUI引擎是互斥的
- 如何安全的修改對象
- 當渲染引擎遇上強迫癥
- 不要使用連相等
- 修改數組-對象
- 算法-函數
- 事件探析
- 事件循環
- js事件循環中的上下文和作用域的經典問題
- Promise
- 最佳實踐
- 頁面遮罩加載效果
- 網站靜態文件之思考
- 圖片加載問題
- 路由及轉場解決方案
- web app
- 寫一個頁面路由轉場的管理工具
- 談編程
- 技術/思想的斗爭
- 前端技術選型分析
- 我想放點html模板代碼
- 開發自適應網頁
- 后臺前端項目的開發
- 網站PC版和移動版的模板方案
- 前后端分離
- 淘寶前后端分離
- 前后端分離的思考與實踐(一)
- 前后端分離的思考與實踐(二)
- 前后端分離的思考與實踐(三)
- 前后端分離的思考與實踐(四)
- 前后端分離的思考與實踐(五)
- 前后端分離的思考與實踐(六)
- 動畫
- 開發小技巧
- Axios
- 屏幕適配
- 理論基礎
- 思考
- flexible.js原理
- 實驗
- rem的坑,為什么要設置成百分比,為什么又是62.5%
- 為什么以一個標準適配的,其它寬度也能同等適配
- 自適應、響應式、彈性布局、屏幕適配
- 適配:都用百分比?
- 番外篇
- 給你看看0.5px長什么樣?
- 用事實證明viewport scale縮放不會改變rem元素的大小
- 為什么PC端頁面縮放不會影響rem元素
- 究竟以哪個為設備獨立像素
- PC到移動端初試
- 深入理解px
- 響應式之柵格系統
- 深入理解px(二)
- 一篇搞定移動端適配
- flex版柵格布局
- 其他
- 瀏覽器加載初探
- 警惕你的開發工具
- JS模塊化
- webpack
- 打包原理
- 異步加載
- gulp
- 命名規范
- 接口開發
- sea.js學習
- require.js學習
- react學習
- react筆記
- vue學習
- vue3
- 工具、技巧
- 臨時筆記
- 怎么維護好開源項目
- 待辦
- 對前端MVV*C框架的思考
- jquery問題
- 臨時
- 好文
- 節流防抖