响应式设计(responsive web design,RWD)

1,224 阅读10分钟

响应式设计RWD:指的是允许Web页面适应不同屏幕宽度因素等,进行布局和外观的调整的一系列实践。这是改变我们设计多设备网页的方式的思想。

也就是一个网站能够兼容多个终端,而不是为一个终端做的特定的版本。

可以通过以下几种方式完成响应式布局:

  • 媒体查询
  • 百分比
  • 自适应场景下的rem解决方案
  • 通过vw/vh来实现自适应

基本原理:通过媒体查询检测不同的设备屏幕尺寸做处理;

页面头部必须设置meta声明的viewport

什么是 Viewport?

viewport 是用户网页的可视区域。

设置 Viewport

一个常用的针对移动网页优化过的页面的 viewport meta 标签大致如下:

<meta name="viewport" content="width=device-width, initial-scale=1.0">
属性名取值描述
width正整数定义布局视口的宽度,单位为像素, 控制 viewport 的大小,可以指定的一个值,如 600,或者特殊的值,如 device-width 为设备的宽度(单位为缩放为 100% 时的 CSS 的像素)。
height正整数定义布局视口的高度,单位为像素,很少使用
initial-scale[0,10]初始缩放比例,1表示不缩放,也即是当页面第一次 load 的时候缩放比例
minimum-scale[0,10]允许用户缩放到的最小比例
maximum-scale[0,10]允许用户缩放到的最小比例
user-scalableyes/no是否允许用户手动缩放页面,默认值为yes,如果设为`no`的话阻止缩放

应该避免使用minimum-scalemaximum-scale,尤其是将user-scalable设为no。用户应该有权力尽可能大或小地进行缩放,阻止这种做法会引起访问性问题。

一、媒体查询@media

使用 @media 查询,你可以针对不同的屏幕大小定义不同的样式。 @media 可以针对不同的屏幕尺寸设置不同的样式,特别是如果你需要设置设计响应式的页面,

CSS语法:

@media mediaType and|not|only (media feature) {     
    /*CSS-Code;*/
}

示例:

下面的媒体查询进行测试,以知晓当前的Web页面是否被展示为屏幕媒体(也就是说不是印刷文档),且视口至少有800像素宽。用于.container选择器的CSS将只会在这两件前提存在的情况下应用。

@media screen and (min-width: 800px) { 
  .container { 
    margin: 1em 2em; 
  } 
} 
.container { 
     margin: 2em 4em;  //普通场景
} 

你可以在一张样式表上加入多条媒体查询,调整整个页面或者部分页面以达到适应各式屏幕尺寸的最佳效果。媒体查询,以及样式改变时的点,被叫做断点(breakpoints)。

媒体类型(mediaType )

类型有很多,在这里不一一列出来了,只列出了常用的几个。

描述
all用于所有设备
print用于打印机和打印预览
screen用于电脑屏幕,平板电脑,智能手机等。**(最常用)**
speech应用于屏幕阅读器等发声设备

媒体功能

以下列出常用的几个

描述
max-width定义输出设备中的页面最大可见区域宽度
min-width定义输出设备中的页面最小可见区域宽度
@media (min-width: 1200){ //>=1200的设备 }
@media (min-width: 992px){ //>=992的设备 }
@media (min-width: 768px){ //>=768的设备 }
/*当页面宽度大于1000px且小于1200px的时候执行,1000-1200*/
@media screen and (min-width:1000px) and (max-width: 1200px){    
    body{        
            font-size:16px    
    }
}
/*当页面宽度大于1280px且小于1366px的时候执行,1280-1366*/
@media screen and (min-width:1280px) and (max-width: 1366px){    
    body{        
        font-size:18px    
    }
}
/*当页面宽度大于1440px且小于1600px的时候执行,1440-1600*/
@media screen and (min-width:1440px) and (max-width:1600px){    
    body{        
        font-size:20px    
    }
}
/*当页面宽度大于1680px且小于1920px的时候执行,1680-1920*/
@media screen and (min-width:1680px) and (max-width:1920px){   
     body{        
        font-size:22px    
    }
}

px与视口

px:css像素

1个css像素可以表示成:

1 CSS像素 = 物理像素/分辨率

我们直到,在pc端的布局视口通常情况下为980px,移动端以iphone6为例,分辨率为375 * 667,也就是说布局视口在理想的情况下为375px。比如现在我们有一个750px * 1134px的视觉稿,那么在pc端,一个css像素可以如下计算:

PC端: 1 CSS像素 = 物理像素/分辨率 = 750 / 980 =0.76 px

而在iphone6下:

iphone6:1 CSS像素 = 物理像素 /分辨率 = 750 / 375 = 2 px

也就是说在PC端,一个CSS像素可以用0.76个物理像素来表示,

而iphone6中 一个CSS像素表示了2个物理像素。

此外不同的移动设备分辨率不同,也就是1个CSS像素可以表示的物理像素是不同的,

因此如果在css中仅仅通过px作为长度和宽度的单位,造成的结果就是无法通过一套样式,实现各端的自适应。

二、百分比

除了用px结合媒体查询实现响应式布局外,我们也可以通过百分比单位 " % " 来实现响应式的效果。

比如当浏览器的宽度或者高度发生变化时,通过百分比单位,通过百分比单位可以使得浏览器中的组件的宽和高随着浏览器的变化而变化,从而实现响应式的效果。

_**css中的子元素中的百分比(%)到底是谁的百分比?**_

1. 百分比的具体分析

(1)子元素height和width的百分比

子元素的height或width中使用百分比,是相对于子元素的直接父元素,width相对于父元素的width,height相对于父元素的height。比如:

<div class="parent">
  <div class="child"></div>
</div>

.father{width:200px;height:100px;}.child{width:50%;height:50%;}

(2) top和bottom 、left和right

子元素的top和bottom如果设置百分比,则相对于直接非static定位(默认定位)的父元素的高度,同样

子元素的left和right如果设置百分比,则相对于直接非static定位(默认定位的)父元素的宽度。

(3)padding, margin

子元素的padding或者margin如果设置百分比,不论是垂直方向或者是水平方向,都相对于直接父亲元素的width,而与父元素的height无关

(4)border-radius,translate、background-size

border-radius不一样,如果设置border-radius为百分比,则是相对于自身的宽度。

除了border-radius外,还有比如translate、background-size等都是相对于自身的。

2. 百分比单位布局应用

百分比单位在布局上应用还是很广泛的,这里介绍一种应用。

比如我们要实现一个固定长宽比的长方形,比如要实现一个长宽比为4:3的长方形,我们可以根据padding属性来实现,因为padding不管是垂直方向还是水平方向,百分比单位都相对于父元素的宽度,因此我们可以设置padding-top为百分比来实现,长宽自适应的长方形:

<div class="trangle"></div>

设置样式让其自适应:

.trangle{
  height:0;
  width:100%;
  padding-top:75%;
}

通过设置padding-top:75%,相对比宽度的75%,因此这样就设置了一个长宽高恒定比例的长方形

3. 百分比单位缺点

有明显的以下两个缺点:

(1)计算困难,如果我们要定义一个元素的宽度和高度,按照设计稿,必须换算成百分比单位。
(2)各个属性中如果使用百分比,相对父元素的属性并不是唯一的。比如width和height相对于父元素的width和height,而margin、padding不管垂直还是水平方向都相对比父元素的宽度、border-radius则是相对于元素自身等等,造成我们使用百分比单位容易使布局问题变得复杂。

三、自适应场景下的rem解决方案

rem(font size of the root element)是指相对于根元素的字体大小的单位。

em(font size of the element)是指相对于父元素的字体大小的单位。

它们之间其实很相似,只不过一个计算的规则是依赖根元素一个是依赖父元素计算。

所谓依赖根元素来计算的方式,就是先给予html元素一个font-size,然后我们所有的rem就根据这个font-size来计算,例如:

html{ 
    font-size:16px;
}

那么我们这里的1rem就应该这么来计算:1x16=16px=1rem;

通过rem来实现响应式布局

rem单位都是相对于根元素html的font-size来决定大小的,根元素的font-size相当于提供了一个基准,当页面的size发生变化时,只需要改变font-size的值,那么以rem为固定单位的元素的大小也会发生响应的变化
因此,如果通过rem来实现响应式的布局,只需要根据视图容器的大小,动态的改变font-size即可。

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);

上述代码中将视图容器分为10份,font-size用十分之一的宽度来表示,最后在header标签中执行这段代码,就可以动态定义font-size的大小,从而1rem在不同的视觉容器中表示不同的大小,用rem固定单位可以实现不同容器内布局的自适应。

rem 布局的缺点

通过rem单位,可以实现响应式的布局,特别是引入相应的postcss相关插件,免去了设计稿中的px到rem的计算

缺陷是:

**在响应式布局中,必须通过js来动态控制根元素font-size的大小。**

也就是说css样式和js代码有一定的耦合性。且必须将改变font-size的代码放在css样式之前。

四、通过vw/vh来实现自适应

1、什么是vw/vh ?

css3中引入了一个新的单位vw/vh,与视图窗口有关。

vw表示相对于视图窗口的宽度

vh表示相对于视图窗口高度,除了vw和vh外,还有vmin和vmax两个相关的单位。各个单位具体的含义如下:

单位含义
vw相对于视窗的宽度,视窗宽度是100vw
vh相对于视窗的高度,视窗高度是100vh
vminvw和vh中的较小值
vmaxvw和vh中的较大值

很类似百分比单位。vw和%的区别为:

单位含义
%大部分相对于祖先元素,也有相对于自身的情况比如(border-radius、translate等)
vw/vh相对于视窗的尺寸

百分比单位很难换算,但是 任意层级元素,在使用vw单位的情况下,1vw都等于视图宽度的百分之一。

2. vw单位换算

例:将px换算成vw单位,很简单,只要确定视图的窗口大小(布局视口),如果我们将布局视口设置成分辨率大小,比如对于iphone6/7 375*667的分辨率,那么px可以通过如下方式换算成vw:

1px = (1/375)*100 vw

此外,也可以通过postcss的相应插件,预处理css做一个自动的转换,postcss-px-to-viewport可以自动将px转化成vw。
postcss-px-to-viewport的默认参数为:

var defaults = {
  viewportWidth: 320,
  viewportHeight: 568, 
  unitPrecision: 5,
  viewportUnit: 'vw',
  selectorBlackList: [],
  minPixelValue: 1,
  mediaQuery: false
};

通过指定视窗的宽度和高度,以及换算精度,就能将px转化成vw。

3. vw/vh单位的兼容性

可以在caniuse.com/ 查看各个版本的浏览器对vw单位的支持性。

参考文章:

github.com/fortheallli…