目录
一、媒体查询(Meida Queries)
要是通过查询设备的宽度来执行不同的 css
代码,最终达到界面的配置;
语法:
@media screen and (max-width: 600px) { /*当屏幕尺寸小于600px时,应用下面的CSS样式*/
/*你的css代码*/
}
那么问题来了,我怎么判断这个屏幕在多大的时候设置媒体查询的分割点呢?
1、通过js获取当前屏幕的大小
document.documentElement.clientWidth
2、常见分割点
部分来自参考原文链接
如果我们选择600px
,900px
,1200px
,1800px
作为分割点,可以适配到常见的14个机型:
当然这只是其中的一种分割方案,我们还可以这样划分:480px
,800px
,1400px
,1400px
而作为曾经典型的响应式布局框架,Bootstrap
是怎么进行断点的呢?
上面的分割方案不一定满足项目中的实际需求,我们可以先用跨度大的分割点进行分割,如果出现不适配的情况可以再根据实际情况增加新的分割点。
不管是移动优先还是PC优先,都是依据当随着屏幕宽度增大或减小的时候,后面的样式会覆盖前面的样式。因此,移动端优先首先使用的是min-width
,PC端优先使用的max-width
移动优先:
/* iphone6 7 8 */
body {
background-color: yellow;
}
/* iphone 5 */
@media screen and (max-width: 320px) {
body {
background-color: red;
}
}
/* iphoneX */
@media screen and (min-width: 375px) and (-webkit-device-pixel-ratio: 3) {
body {
background-color: #0FF000;
}
}
/* iphone6 7 8 plus */
@media screen and (min-width: 414px) {
body {
background-color: blue;
}
}
/* ipad */
@media screen and (min-width: 768px) {
body {
background-color: green;
}
}
/* ipad pro */
@media screen and (min-width: 1024px) {
body {
background-color: #FF00FF;
}
}
/* pc */
@media screen and (min-width: 1100px) {
body {
background-color: black;
}
}
复制代码
PC优先:
/* pc width > 1024px */
body {
background-color: yellow;
}
/* ipad pro */
@media screen and (max-width: 1024px) {
body {
background-color: #FF00FF;
}
}
/* ipad */
@media screen and (max-width: 768px) {
body {
background-color: green;
}
}
/* iphone6 7 8 plus */
@media screen and (max-width: 414px) {
body {
background-color: blue;
}
}
/* iphoneX */
@media screen and (max-width: 375px) and (-webkit-device-pixel-ratio: 3) {
body {
background-color: #0FF000;
}
}
/* iphone6 7 8 */
@media screen and (max-width: 375px) and (-webkit-device-pixel-ratio: 2) {
body {
background-color: #0FF000;
}
}
/* iphone5 */
@media screen and (max-width: 320px) {
body {
background-color: #0FF000;
}
}
缺点
- 代码量比较大,维护不方便
- 为了兼顾大屏幕或高清设备,会造成其他设备资源浪费,特别是加载图片资源
- 为了兼顾移动端和PC端各自响应式的展示效果,难免会损失各自特有的交互方式
二、百分比布局
通过百分比单位,可以使得浏览器中组件的宽和高随着浏览器的高度的变化而变化,从而实现响应式的效果。Bootstrap里面的栅格系统就是利用百分比来定义元素的宽高,CSS3
支持最大最小高,可以将百分比和max(min)
一起结合使用来定义元素在不同设备下的宽高。
/* pc width > 1100px */
html, body { margin: 0;padding: 0;width: 100%;height: 100%;}
aside {
width: 10%;
height: 100%;
background-color: red;
float: left;
}
main {
height: 100%;
background-color: blue;
overflow: hidden;
}
/* ipad pro */
@media screen and (max-width: 1024px) {
aside {
width: 8%;
background-color: yellow;
}
}
/* ipad */
@media screen and (max-width: 768px) {
aside {
float: none;
width: 100%;
height: 10%;
background-color: green;
}
main {
height: calc(100vh - 10%);
background-color: red;
}
}
/* iphone6 7 8 plus */
@media screen and (max-width: 414px) {
aside {
float: none;
width: 100%;
height: 5%;
background-color: yellow;
}
main {
height: calc(100vh - 5%);
background-color: red;
}
}
/* iphoneX */
@media screen and (max-width: 375px) and (-webkit-device-pixel-ratio: 3) {
aside {
float: none;
width: 100%;
height: 10%;
background-color: blue;
}
main {
height: calc(100vh - 10%);
background-color: red;
}
}
/* iphone6 7 8 */
@media screen and (max-width: 375px) and (-webkit-device-pixel-ratio: 2) {
aside {
float: none;
width: 100%;
height: 3%;
background-color: black;
}
main {
height: calc(100vh - 3%);
background-color: red;
}
}
/* iphone5 */
@media screen and (max-width: 320px) {
aside {
float: none;
width: 100%;
height: 7%;
background-color: green;
}
main {
height: calc(100vh - 7%);
background-color: red;
}
}
复制代码
- webkit-min-device-pixel-ratio: 1.5
是指当时显示屏最小的色倍为1.5倍的
它是设备上物理像素和设备独立像素( device-independent pixels (dips) )的比例,即 devicePixelRatio = 屏幕物理像素/设备独立像素
例如iPhone4S,分辨率为:960×640,取屏幕宽度计算,物理像素640px,设备独立像素320px,那么,devicePixelRatio 值为 640px / 320px = 2,又如iPhone3,计算出来的 devicePixelRatio 值为 320px / 320px = 1
- 但是我们必须要弄清楚css中子元素的百分比到底是相对谁的百分比。直接上结论吧:
- 子元素的
height
或width
中使用百分比,是相对于子元素的直接父元素,width
相对于父元素的width
,height
相对于父元素的height
; - 子元素的
top
和bottom
如果设置百分比,则相对于直接非static
定位(默认定位)的父元素的高度, -
同样子元素的
left
和right
如果设置百分比,则相对于直接非static
定位(默认定位的)父元素的宽度; - 子元素的
padding
如果设置百分比,不论是垂直方向或者是水平方向,都相对于直接父亲元素的width
,而与父元素的height
无关。 - 跟
padding
一样,margin
也是如此,子元素的margin
如果设置成百分比,不论是垂直方向还是水平方向,都相对于直接父元素的width
; border-radius
不一样,如果设置border-radius
为百分比,则是相对于自身的宽度,除了border-radius
外,还有比如translate
、background-size
等都是相对于自身的;
- 从上述对于百分比单位的介绍我们很容易看出如果全部使用百分比单位来实现响应式的布局,有明显的以下两个缺点:
- 计算困难,如果我们要定义一个元素的宽度和高度,按照设计稿,必须换算成百分比单位。
- 可以看出,各个属性中如果使用百分比,相对父元素的属性并不是唯一的。比如
width
和height
相对于父元素的width
和height
,而margin
、padding
不管垂直还是水平方向都相对比父元素的宽度、border-radius
则是相对于元素自身等等,造成我们使用百分比单位容易使布局问题变得复杂
三、Flex弹性布局
具体使用见弹性盒子
以天猫为例,meta标签的viewport是固定的,
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
四、使用rem
相对于根元素html的font-size大小决定的。
而em
是相对于父元素的
《移动Web资源整理》中写到对于需要适配各种移动设备,使用rem,例如只需要适配iPhone和iPad等分辨率差别比较挺大的设备
rem配置参考,适合视觉稿宽度为640px的:
<meta content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no" name="viewport">
html{font-size:10px}
@media screen and (min-width:321px) and (max-width:375px){html{font-size:11px}}
@media screen and (min-width:376px) and (max-width:414px){html{font-size:12px}}
@media screen and (min-width:415px) and (max-width:639px){html{font-size:15px}}
@media screen and (min-width:640px) and (max-width:719px){html{font-size:20px}}
@media screen and (min-width:720px) and (max-width:749px){html{font-size:22.5px}}
@media screen and (min-width:750px) and (max-width:799px){html{font-size:23.5px}}
@media screen and (min-width:800px){html{font-size:25px}}
一个小demohttp://peunzhang.github.io/demo/rem/index.html
body:
a:
:
在响应式布局中,必须通过js动态控制根元素的font-size大小
/*上述代码中将视图容器分为10份,font-size用十分之一的宽度来表示,最后在header标签中执行这段代码,就可以动态定义font-size的大小,从而1rem在不同的视觉容器中表示不同的大小,用rem固定单位可以实现不同容器内布局的自适应。*/
function refreshRem() {
var docEl = doc.documentElement;
var width = docEl.getBoundingClientRect().width;
var rem = width / 10;
docEl.style.fontSize = rem + 'px';
flexible.rem = win.rem = rem;
}
win.addEventListener('resize', refreshRem);
假设,html我们设置font-size:12px; 也就是说12px相对于1rem,那么18px也就是 18/12 = 1.5rem。
但是相比百分比布局,需要借助JS或media query实现,略有一点瑕疵
rem + viewport
这也是淘宝使用的方案,根据屏幕宽度设定 rem
值,需要适配的元素都使用 rem
为单位,不需要适配的元素还是使用 px
为单位。
根据rem
将页面放大dpr
倍, 然后viewport
设置为1/dpr
.
- 如iphone6 plus的dpr为3, 则页面整体放大3倍, 1px(css单位)在plus下默认为3px(物理像素)
- 然后
viewport
设置为1/3, 这样页面整体缩回原始大小. 从而实现高清。
五、视口单位(vw vh)
vw
表示相对于视图窗口的宽度
vh
表示相对于视图窗口高度
除了vw
和vh
外,还有vmin
和vmax
两个相关的单位
那么vw或者vh很类似百分比单位。vw和%的区别为:
使用视口单位来实现响应式有两种做法:
1.仅使用vw作为CSS单位
-
对于设计稿的尺寸转换为为单位,我们使用
Sass
函数编译//iPhone 6尺寸作为设计稿基准 $vm_base: 375; @function vw($px) { @return ($px / 375) * 100vw; }
-
无论是文本还是布局宽度、间距等都使用
vw
作为单位.mod_nav { background-color: #fff; &_list { display: flex; padding: vm(15) vm(10) vm(10); // 内间距 &_item { flex: 1; text-align: center; font-size: vm(10); // 字体大小 &_logo { display: block; margin: 0 auto; width: vm(40); // 宽度 height: vm(40); // 高度 img { display: block; margin: 0 auto; max-width: 100%; } } &_name { margin-top: vm(2); } } } }
-
1物理像素线(也就是普通屏幕下1px,高清屏幕下0.5px的情况)采用
transform
属性scale
实现.mod_grid { position: relative; &::after { // 实现1物理像素的下边框线 content: ''; position: absolute; z-index: 1; pointer-events: none; background-color: #ddd; height: 1px; left: 0; right: 0; top: 0; @media only screen and (-webkit-min-device-pixel-ratio: 2) { -webkit-transform: scaleY(0.5); -webkit-transform-origin: 50% 0%; } } ... }
-
对于需要保持宽高比的图,应该用
padding-top
实现.mod_banner { position: relative; padding-top: percentage(100/700); // 使用padding-top height: 0; overflow: hidden; img { width: 100%; height: auto; position: absolute; left: 0; top: 0; } }
2.搭配vw和rem
虽然采用vw
适配后的页面效果很好,但是它是利用视口单位实现的布局,依赖视口大小而自动缩放,无论视口过大还是过小,它也随着时候过大或者过小,失去了最大最小宽度的限制,此时我们可以结合rem
来实现布局
-
给根元素大小设置随着视口变化而变化的
vw
单位,这样就可以实现动态改变其大小 -
限制根元素字体大小的最大最小值,配合
body
加上最大宽度和最小宽度// rem 单位换算:定为 75px 只是方便运算,750px-75px、640-64px、1080px-108px,如此类推 $vm_fontsize: 75; // iPhone 6尺寸的根元素大小基准值 @function rem($px) { @return ($px / $vm_fontsize ) * 1rem; } // 根元素大小使用 vw 单位 $vm_design: 750; html { font-size: ($vm_fontsize / ($vm_design / 2)) * 100vw; // 同时,通过Media Queries 限制根元素最大最小值 @media screen and (max-width: 320px) { font-size: 64px; } @media screen and (min-width: 540px) { font-size: 108px; } } // body 也增加最大最小宽度限制,避免默认100%宽度的 block 元素跟随 body 而过大过小 body { max-width: 540px; min-width: 320px; }
六、图片响应式
<img srcset="photo_w350.jpg 1x, photo_w640.jpg 2x" src="photo_w350.jpg" alt="">
淘宝实现方式
上面说到的淘宝的实现方式即rem
+viewport
缩放来实现。
transform: scale(0.5)
CSS
代码:
1 2 3 4 5 6 7 8 | div{ width: 1px; height: 100%; display: block; border-left: 1px solid #e5e5e5; -webkit-transform: scaleX(.5); transform: scaleX(.5); } |
七、响应式布局的成型方案
现在的css,UI框架等都已经考虑到了适配不同屏幕分辨率的问题,实际项目中我们可以直接使用这些新特性和框架来实现响应式布局。可以有以下选择方案:
- 利用上面的方法自己来实现,比如CSS3 Media Query,rem,vw等
- Flex弹性布局,兼容性较差
- Grid网格布局,兼容性较差
- Columns栅格系统,往往需要依赖某个UI库,如Bootstrap
八、响应式布局的要点
在实际项目中,我们可能需要综合上面的方案,比如用rem
来做字体的适配,用srcset
来做图片的响应式,宽度可以用rem
,flex
,栅格系统等来实现响应式,然后可能还需要利用媒体查询来作为响应式布局的基础,因此综合上面的实现方案,项目中实现响应式布局需要注意下面几点:
- 设置viewport
- 媒体查询
- 字体的适配(字体单位)
- 百分比布局
- 图片的适配(图片的响应式)
- 结合flex,grid,BFC,栅格系统等已经成型的方案