## 响应式之栅格系统
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 的影响限制在更小范围的屏幕大小之内。”
![](http://cdn.aipin100.cn/18-11-15/97968706.jpg)
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问题
- 临时
- 好文
- 节流防抖