响应式布局指的是同一页面在不一样屏幕尺寸下有不一样的布局。传统的开发方式是PC端开发一套,手机端再开发一套,而使用响应式布局只要开发一套就够,缺点就是CSS
比较重。下面是博客网站对不一样设备适配后的结果,分别是iPhone5/SE
,iphone6/7/8
,iphone 6/7/8 plus
,ipad pro
,dell台式宽屏(1440 X 900)
。javascript
响应式设计与自适应设计的区别:响应式开发一套界面,经过检测视口分辨率,针对不一样客户端在客户端作代码处理,来展示不一样的布局和内容;自适应须要开发多套界面,经过检测视口分辨率,来判断当前访问的设备是pc端、平板、手机,从而请求服务层,返回不一样的页面。css
CSS3
媒体查询可让咱们针对不一样的媒体类型定义不一样的样式,当重置浏览器窗口大小的过程当中,页面也会根据浏览器的宽度和高度从新渲染页面。html
如何肯定媒体查询的分割点也是一个开发中会遇到的问题,下面是市场上的移动设备和电脑屏幕分辨率的分布状况,能够发现不一样品牌和型号的设备屏幕分辨率通常都不同前端
若是咱们选择600px
,900px
,1200px
,1800px
做为分割点,能够适配到常见的14个机型:java
固然这只是其中的一种分割方案,咱们还能够这样划分:480px
,800px
,1400px
,1400px
ios
而做为曾经典型的响应式布局框架,Bootstrap
是怎么进行断点的呢?css3
上面的分割方案不必定知足项目中的实际需求,咱们能够先用跨度大的分割点进行分割,若是出现不适配的状况能够再根据实际状况增长新的分割点。git
不论是移动优先仍是PC优先,都是依据当随着屏幕宽度增大或减少的时候,后面的样式会覆盖前面的样式。所以,移动端优先首先使用的是min-width
,PC端优先使用的max-width
。github
移动优先:web
/* 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;
}
}
复制代码
经过百分比单位,可使得浏览器中组件的宽和高随着浏览器的高度的变化而变化,从而实现响应式的效果。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;
}
}
复制代码
可是咱们必需要弄清楚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
则是相对于元素自身等等,形成咱们使用百分比单位容易使布局问题变得复杂。REM
是CSS3
新增的单位,而且移动端的支持度很高,Android2.x+,ios5+都支持。rem
单位都是相对于根元素html的font-size
来决定大小的,根元素的font-size
至关于提供了一个基准,当页面的size发生变化时,只须要改变font-size
的值,那么以rem
为固定单位的元素的大小也会发生响应的变化。 所以,若是经过rem
来实现响应式的布局,只须要根据视图容器的大小,动态的改变font-size
便可(而em
是相对于父元素的)。
rem响应式的布局思想:
rem
作单位(首先在HTML总设置一个基准值:px
和rem
的对应比例,而后在效果图上获取px
值,布局的时候转化为rem
值)rem布局的缺点:
在响应式布局中,必须经过js来动态控制根元素font-size
的大小,也就是说css样式和js代码有必定的耦合性,且必须将改变font-size
的代码放在css
样式以前
/*上述代码中将视图容器分为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);
复制代码
REM
布局也是目前多屏幕适配的最佳方式。默认状况下咱们html标签的font-size
为16px,咱们利用媒体查询,设置在不一样设备下的字体大小。
/* pc width > 1100px */
html{ font-size: 100%;}
body {
background-color: yellow;
font-size: 1.5rem;
}
/* ipad pro */
@media screen and (max-width: 1024px) {
body {
background-color: #FF00FF;
font-size: 1.4rem;
}
}
/* ipad */
@media screen and (max-width: 768px) {
body {
background-color: green;
font-size: 1.3rem;
}
}
/* iphone6 7 8 plus */
@media screen and (max-width: 414px) {
body {
background-color: blue;
font-size: 1.25rem;
}
}
/* iphoneX */
@media screen and (max-width: 375px) and (-webkit-device-pixel-ratio: 3) {
body {
background-color: #0FF000;
font-size: 1.125rem;
}
}
/* iphone6 7 8 */
@media screen and (max-width: 375px) and (-webkit-device-pixel-ratio: 2) {
body {
background-color: #0FF000;
font-size: 1rem;
}
}
/* iphone5 */
@media screen and (max-width: 320px) {
body {
background-color: #0FF000;
font-size: 0.75rem;
}
}
复制代码
css3
中引入了一个新的单位vw/vh
,与视图窗口有关,vw
表示相对于视图窗口的宽度,vh
表示相对于视图窗口高度,除了vw
和vh
外,还有vmin
和vmax
两个相关的单位。各个单位具体的含义以下:
单位 | 含义 |
---|---|
vw | 相对于视窗的宽度,1vw 等于视口宽度的1%,即视窗宽度是100vw |
vh | 相对于视窗的高度,1vh 等于视口高度的1%,即视窗高度是100vh |
vmin | vw和vh中的较小值 |
vmax | vw和vh中的较大值 |
用视口单位度量,视口宽度为100vw,高度为100vh(左侧为竖屏状况,右侧为横屏状况)。例如,在桌面端浏览器视口尺寸为650px,那么 1vw = 650 * 1% = 6.5px(这是理论推算的出,若是浏览器不支持0.5px,那么实际渲染结果多是7px)。
那么vw或者vh很相似百分比单位。vw和%的区别为:
单位 | 含义 |
---|---|
% | 大部分相对于祖先元素,也有相对于自身的状况好比(border-radius、translate等) |
vw/vh | 相对于视窗的尺寸 |
从对比中咱们能够发现,vw
单位与百分比相似,单确有区别,前面咱们介绍了百分比单位的换算困难,这里的vw
更像"理想的百分比单位"。任意层级元素,在使用vw
单位的状况下,1vw都等于视图宽度的百分之一。
使用视口单位来实现响应式有两种作法:
对于设计稿的尺寸转换为为单位,咱们使用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;
}
}
复制代码
虽然采用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 {
display: inline-block;
max-width: 100%;
height: auto;
}
复制代码
inline-block
元素相对于它周围的内容之内联形式呈现,但与内联不一样的是,这种状况下咱们能够设置宽度和高度。 max-width
保证了图片可以随着容器的进行等宽扩充(即保证全部图片最大显示为其自身的 100%。此时,若是包含图片的元素比图片固有宽度小,图片会缩放占满最大可用空间),而height
为auto
能够保证图片进行等比缩放而不至于失真。若是是背景图片的话要灵活运用background-size
属性。
那么为何不能用width:100%
呢?由于这条规则会致使它显示得跟它的容器同样宽。在容器比图片宽得多的状况下,图片会被无谓地拉伸。
<img srcset="photo_w350.jpg 1x, photo_w640.jpg 2x" src="photo_w350.jpg" alt="">
复制代码
若是屏幕的dpi = 1的话则加载1倍图,而dpi = 2则加载2倍图,手机和mac基本上dpi都达到了2以上,这样子对于普通屏幕来讲不会浪费流量,而对于视网膜屏来讲又有高清的体验。
若是浏览器不支持srcset
,则默认加载src里面的图片。
可是你会发现实际状况并非如此,在Mac上的Chrome它会同时加载srcset
里面的那张2x的,还会再去加载src里面的那张,加载两张图片。顺序是先把全部srcset
里面的加载完了,再去加载src的。这个策略比较奇怪,它竟然会加载两张图片,若是不写src,则不会加载两张,可是兼容性就没那么好。这个多是由于浏览器认为,既然有srcset
就不用写src了,若是写了src,用户多是有用的。而使用picture
就不会加载两张
.banner{
background-image: url(/static/large.jpg);
}
@media screen and (max-width: 767px){
background-image: url(/static/small.jpg);
}
复制代码
picturefill.min.js :解决IE等浏览器不支持 的问题
<picture>
<source srcset="banner_w1000.jpg" media="(min-width: 801px)">
<source srcset="banner_w800.jpg" media="(max-width: 800px)">
<img src="banner_w800.jpg" alt="">
</picture>
<!-- picturefill.min.js 解决IE等浏览器不支持 <picture> 的问题 -->
<script type="text/javascript" src="js/vendor/picturefill.min.js"></script>
复制代码
picture
必需要写img标签,不然没法显示,对pictur
e的操做最后都是在img上面,例如onload事件是在img标签触发的,picture
和source
是不会进行layout的,它们的宽和高都是0。
另外使用source
,还能够对图片格式作一些兼容处理:
<picture>
<source type="image/webp" srcset="banner.webp"> <img src="banner.jpg" alt=""> </picture> 复制代码
总结:响应式布局的实现能够经过媒体查询+px
,媒体查询+百分比,媒体查询+rem
+js
,vm/vh
,vm/vh
+rem
这几种方式来实现。但每一种方式都是有缺点的,媒体查询须要选取主流设备宽度尺寸做为断点针对性写额外的样式进行适配,但这样作会比较麻烦,只能在选取的几个主流设备尺寸下呈现完美适配,另外用户体验也不友好,布局在响应断点范围内的分辨率下维持不变,而在响应断点切换的瞬间,布局带来断层式的切换变化,如同卡带的唱机般“咔咔咔”地一下又一下。经过百分比来适配首先是计算麻烦,第二各个属性中若是使用百分比,其相对的元素的属性并非惟一的,这样就形成咱们使用百分比单位容易使布局问题变得复杂。经过采用rem
单位的动态计算的弹性布局,则是须要在头部内嵌一段脚原本进行监听分辨率的变化来动态改变根元素字体大小,使得CSS
与JS
耦合了在一块儿。经过利用纯css
视口单位实现适配的页面,是既能解决响应式断层问题,又能解决脚本依赖的问题的,可是兼容性尚未彻底能结构接受。
如今的css,UI框架等都已经考虑到了适配不一样屏幕分辨率的问题,实际项目中咱们能够直接使用这些新特性和框架来实现响应式布局。能够有如下选择方案:
在实际项目中,咱们可能须要综合上面的方案,好比用rem
来作字体的适配,用srcset
来作图片的响应式,宽度能够用rem
,flex
,栅格系统等来实现响应式,而后可能还须要利用媒体查询来做为响应式布局的基础,所以综合上面的实现方案,项目中实现响应式布局须要注意下面几点:
参考文章: