>

原文出处,移动端页面开发适配 rem布局原理

- 编辑:澳门博发娱乐官网 -

原文出处,移动端页面开发适配 rem布局原理

浅谈Web自适应

2016/07/28 · 基础技术 · 自适应

原文出处: 卖烧烤夫斯基   

特别说明:在开始这一切之前,请开发移动界面的工程师们在头部加上下面这条meta:

之前分享过一篇文章《教会你开发移动端页面的文章(一)》。那是本篇文章的基础,如果没有阅读过的同学可以去看看,今天就给大家带来干货,真真正正的讲到如何很好的开发一个移动端的页面

一篇真正教会你开发移动端页面的文章(二)

2017/12/07 · 基础技术 · 移动端

原文出处: HcySunYang   

移动端页面开发适配 rem布局原理,rem布局

主题 HTML
移动端页面开发适配 rem布局原理

什么是适配,为什么要适配

我们拿到的设计图一般是以640,750,1080分辨率为基准设计的,而现在的手机终端各式各样,分辨率不同,逻辑像素不同 ,适口不同,所以为了让我们的页面在每个设备上都可以良好的展示,那么就需要为这些设备做统一的处理,这个过程就称为移动端适配。

需要知道的一些概念:

物理像素(physical pixel)

一个物理像素是显示器(手机屏幕)上最小的物理显示单元,可以理解为我们平时说的分辨率;

设备独立像素(density-independent pixel)

设备独立像素(也叫密度无关像素),可以认为是计算机坐标系统中得一个点,这个点代表一个可以由程序使用的虚拟像素(比如 css像素),然后由相关系统转换为物理像素,在这里可以理解为我们说的视觉视口的大小;

所以说,物理像素和设备独立像素之间存在着一定的对应关系,这就是接下来要说的设备像素比。

设备像素比(device pixel ratio)

设备像素比(简称dpr)定义了物理像素和设备独立像素的对应关系,它的值可以按如下的公式的得到:

设备像素比 = 物理像素 设备独立像素 在某一方向上,x方向或者y方向

设备像素比也是设备生产的时候设置好的,在javascript中,可以通window.devicePixelRatio获取到当前设备的dpr。

视口(viewport)

pc端视口指浏览器窗口内的内容区域,不包含工具条,滚动条.

移动浏览器中视口分为几种情况

metaname=viewportcontent=“width=device-width,minimum-scale=1.0,maximum-scale=1.0”中content所设置的视口,称为布局视口,最大值由浏览器厂商规定 ,可以document.documentElement.clientWidth获取其宽度.

而我们看到的浏览器的窗口,网页区域的大小,称为视觉视口,用css像素表示(设备逻辑像素)

rem

rem是css3 的一个长度单位 ,相对文档跟元素 html;比如设置html font-size=100px;那么1rem=100px;之后的所有元素都可以用这个基准值来设置大小;

常用的方案:

固定高度,宽度自适应(百分比,em)

使用 rem布局

下面总结了网易 淘宝首页使用rem的方案

网易的做法:

1) 将布局适口设置为视觉适口,不进行缩放,即理想适口。

meta name=viewportcontent=initial-scale=1,maximum-scale=1, minimum-scale=1”

2) 以设计稿分辨率为基准,取100px为font-size的参照,那么body元素的宽度就可以设置为width6.4rem(640100),当我们将布局视口设置为320时,于是html的 font-size=deviceWidth 6.4。

3) 通过document.documentElement.clientWidth获取 deviceWidth;

4) 当页面的dom ready后设置html font-size,

document.documentElement.style.fontSize =document.documentElement.clientWidth 6.4 + ‘px’
5) 通过 mediaQuery 设置字体大小,字体大小不可以使用rem,原因是误差太大。

以640的设计稿为例最终的设置html font-size代码如下,布局时拿设计稿标注的尺寸除以100,就是rem的值,相当简单啊

var deviceWidth = document.documentElement.clientWidth;
if(deviceWidth 640) deviceWidth = 640;
document.documentElement.style.fontSize = deviceWidth 6.4 + 'px';
这里if(deviceWidth 640) deviceWidth = 640; 是因为当deviceWidth大于640时物理分辨率已经大于1280(取决于 dpr ),应该去访问pc的网站;

淘宝的做法:

原理

1) 通过dpr设置缩放比,实现布局视口大小,

var scale = 1 devicePixelRatio;
document.querySelector('meta[name=viewport]').setAttribute('content','initial-scale='+ scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no');
2) 动态计算html的font-size

document.documentElement.style.fontSize = document.documentElement.clientWidth 10 + ‘px’;
这里的意思是,clientWidth 10 得到是布局视口下的rem基准值(以iphone6为例 1rem=75px),那么设计稿正好也是 750,所以对应的关系 clientWidth 10==设计稿的尺寸x, 那么x=设计稿的尺寸rem基准值。

如果是iphone6 plus rem基准值等于clientWidth 10 等于124.2,那么x=750124.2。

关于具体的实现 淘宝提供了一个开源的方案lib-flexible: httpsgithub.comamfelib-f... ;

具体逻辑 :

1)判断head中是否设置了viewport,如果有设置,按照已有viewport 设置缩放比;

if (metaEl) {
console.warn('将根据已有的meta标签来设置缩放比例');
var match = metaEl.getAttribute('content').match(initial-scale=([d.]+));
if (match) {
scale = parseFloat(match[1]);
dpr = parseInt(1 scale);
}
}
2)如果没有设置meta viewport,判断是否设置dpr,如果有,通过dpr计算缩放scale。

var content = flexibleEl.getAttribute('content');
if (content) {
var initialDpr = content.match(initial-dpr=([d.]+));
var maximumDpr = content.match(maximum-dpr=([d.]+));maximum 设置最大值,与initial的值比较,取最小值;
if (initialDpr) {
dpr = parseFloat(initialDpr[1]);
scale = parseFloat((1 dpr).toFixed(2));
}
if (maximumDpr) {
dpr = parseFloat(maximumDpr[1]);
scale = parseFloat((1 dpr).toFixed(2));
}
}
3)如果 dpr &scale都没有设置,那么就通过设备的dpr设置起缩放 scale,

if (!dpr && !scale) {meta[name=viewport]&&meta[name=flexible]都不存在。

var isAndroid = win.navigator.appVersion.match(androidgi);
var isIPhone = win.navigator.appVersion.match(iphonegi);
var devicePixelRatio = win.devicePixelRatio;
if (isIPhone) {
iOS下,对于2和3的屏,用2倍的方案,其余的用1倍方案
if (devicePixelRatio = 3 && (!dpr dpr = 3)) {
dpr = 3;
} else if (devicePixelRatio = 2 && (!dpr dpr = 2)){
dpr = 2;
} else {
dpr = 1;
}
} else {
其他设备下,仍旧使用1倍的方案
dpr = 1;
}
scale = 1 dpr;
}
4)得到scale之后 ,如果meta 的viewport不存在,那么就创建一个meta[name=“viewport”],将scale配置进去。

metaEl = doc.createElement('meta');

metaEl.setAttribute('name', 'viewport');
metaEl.setAttribute('content', 'initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no');

if (docEl.firstElementChild) {

docEl.firstElementChild.appendChild(metaEl);

}
5)动态改写html的font-size

var width = docEl.getBoundingClientRect().width;获取html的宽度

if (width dpr 540) {判断屏幕逻辑像素大于540时,取540
width = 540 dpr;
}
var rem = width 10;
docEl.style.fontSize = rem + 'px';
flexible.rem = win.rem = rem;
总结:

使用rem布局,实质都是通过动态改写html的font-size基准值,来实现不同设备下的良好统一适配;

网易与淘宝不同 的地方是 ,网易将布局视口设置成了 视觉视口,淘宝将布局视口设置成了物理像素大小,通过 scale缩放嵌入了 视觉视口中;

容器元素的字体大小都不使用rem,需要额外的media查询;

rem布局原理,rem布局 主题 HTML 移动端页面开发适配 rem布局原理 什么是适配,为什么要适配 我们拿到的设计图一般是...

前言

图片 1

随着移动设备的普及,移动web在前端工程师们的工作中占有越来越重要的位置。移动设备更新速度频繁,手机厂商繁多,导致的问题是每一台机器的屏幕宽度和分辨率不一样。这给我们在编写前端界面时增加了困难,适配问题在当下显得越来越突出。记得刚刚开始开发移动端产品的时候向设计MM要了不同屏幕的设计图,结果可想而知。本篇博文分享一些卤煮处理多屏幕自适应的经验,希望有益于诸君。

特别说明:在开始这一切之前,请开发移动界面的工程师们在头部加上下面这条meta:

XHTML

<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">

1
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">

<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">

 

移动端开发的干货篇

之前写了一篇文章《一篇真正教会你开发移动端一面的文章(一)》/)。那是本篇文章的基础,如果没有阅读过的同学可以去看看,今天就给大家带来干货,真真正正的讲到如何很好的开发一个移动端的页面

图片 2

好了,让我们开始吧,从哪里开始呢?从设计图开始,即PSD稿件:
移动端PSD稿件的尺寸肯定较之PC端的PSD稿件不同,具体体现在设计图的尺寸上,现在移动端的设计图尺寸大多以iPhone5和iPhone6的设备像素尺寸作为依据,比如拿到一张PSD设计图,它的总宽度为640px(iPhone5)或者750px(iPhone6)。本例就拿iPhone6的设计图尺寸为标准进行讲解,其它设计图尺寸道理是一样的,这并不影响我们的开发。

首先我们要有一张设计图才行,看下图,假设我们有一张设计图,它很简单,只有一个红色的方块:

图片 3

拿到了设计图,于是你开开心心的开始写代码了,你打开了编辑器,并写下了如下HTML代码:

JavaScript

<!DOCTYPE html> <html> <head> <title></title> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no" /> </head> <body> <div class="box"></div> </body> </html>

1
2
3
4
5
6
7
8
9
10
11
12
13
<!DOCTYPE html>
<html>
<head>
    <title></title>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no" />
</head>
<body>
 
    <div class="box"></div>
 
</body>
</html>

HTML代码写好了,你用了一个带有box类的div标签作为ps稿中的红色块,经过尺寸测量,你为上面代码添加了CSS样式,最后你的代码是这样的:

JavaScript

<!DOCTYPE html> <html> <head> <title></title> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no" /> <style> body{ margin: 0; padding: 0; } .box{ width: 200px; height: 200px; background: red; } </style> </head> <body> <div class="box"></div> </body> </html>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<!DOCTYPE html>
<html>
<head>
    <title></title>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no" />
    <style>
    body{
        margin: 0;
        padding: 0;
    }
    .box{
        width: 200px;
        height: 200px;
        background: red;
    }
    </style>
</head>
<body>
 
    <div class="box"></div>
 
</body>
</html>

上面的代码中,你只是在原来的基础上增加了CSS样式,首先你清除了body标签上的默认样式,这个没什么好说的,然后你根据设计图中测量的尺寸来给box编写样式,宽200px;高200px;背景红色。看上去并没有什么问题,于是你开开心心的打开浏览器,刷新页面,你的脸色沉了下来,因为你看到了你不想看到的结果,如下图,上图为设计稿的样式,下图为你编写的html文件的样式:

图片 4

图片 5

通过对比psd原稿和我们目前所写的html页面,可以看出我们html页面的问题,红色方块与整个页面的比例和psd原稿不一样啊,那么为什么我们明明是按照原稿测量的尺寸写出来的代码却和psd原稿显示的效果不一样呢?别忘了,psd原稿的尺寸是按照设备像素设计的,由于我们所用的设计稿是基于iPhone6设计的,所以我们设计稿的尺寸就是iPhone6的设备像素的尺寸,也就是750px,而我们CSS中的样式是基于布局视口的尺寸计算的,由于我们html页面中由于写入了以下meta标签:

<meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no"/>

1
<meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no"/>

在上一篇我们讲过, width=device-width 这段代码是让布局视口的尺寸等于理想视口。
根据公式(缩放比例为1):
设备像素比(DPR) = 设备像素个数 / 理想视口像素个数(device-width)
因为iPhone6的DPR(设备像素比)为2,设备像素为750,所以iPhone6的理想视口尺寸为375px。所以上面代码最终导致的是:使我们布局视口的宽度变成了375px。而我们CSS中编写的样式尺寸又是基于布局视口计算的,所以我们得到的页面看上去比例不对,如下图:

图片 6
图片 7

如上面两幅图片,我们知道,psd稿的总宽是750px,元素宽200px,而我们真正做页面的时候,布局视口的宽度是375px,正好是设计稿的一半。所以我们不能直接使用设计稿上面测量所得的像素尺寸,根据比例,我们应该将测量所得的尺寸除以2,才是我们CSS中布局所用的尺寸,据此,我们将200px除以2得到100px,于是我们修改代码,将红色方块的宽高都设为100px,刷新页面,看看比例是不是和设计图一样了?答案是肯定的,如下图为修改后的html页面:

图片 8

这样,我们就得到了正确的数据,并且正确的写出了页面,你很高兴,可是问题来了,如果你在做页面的时候,测量了一个元素的宽度,宽度是一个奇数,比如111像素,按照我们之前的做法是,将测量到的数据除以2,得到我们真正使用的数据,所以111除以2等于55.5px,我们知道,计算机(手机)没办法显示不到一个像素的像素值,计算机(手机)会自动将其补全为一个像素进行显示,所以最终会将元素显示为56像素,这并不是我们想要的结果。
另外,我们的设计稿是基于iphone6设计的,我们调试页面也是在iphone6下调试的。又因为iphone6的设备像素比试2,所以我们才能由设计稿测量的数据除以2后直接使用,并且在iphone6下没有问题,但是你要知道,并不是所有手机的设备像素比都是2,有的手机的设备像素比试2.5或者3。并且不同设备的设备像素又不同,这样就导致理想视口的尺寸不同,从而导致布局视口的尺寸不同,那么我们直接根据iphone6的设计稿尺寸除以2得到的尺寸用来编写CSS是不能在所有设备下完好显示的。

所以,我们要换一个方法。
于是我们想到:如果我们能将布局视口的尺寸设置为和设备像素尺寸相等的话,这样我们就保证了设计图与页面的1:1关系,那么我们就可以直接使用psd中测量的尺寸了,然后在其他尺寸的手机中,我们进行等比缩放就ok了。那么如何才能让布局视口的尺寸等于设备像素尺寸呢?

我们注意到meta标签中的 width=device-width 这段代码,首先你要明白这句话的意思,前面讲过,这句话最终导致的结果是:让布局视口的尺寸等于理想视口的尺寸。言外之意就是,在代码 width=device-width 中:

width:是布局视口的width
device-width:是理想视口的宽度

根据公式(缩放比例为1):

设备像素比(DPR) = 设备像素个数 / 理想视口像素个数(device-width)

以iphone6为例:
设备像素比(DPR):2
设备像素个数:750
所以在缩放比例为1的情况下,iphone6理想视口的像素个数为 750 / 2 = 375,也就是说,对于iphone6来讲 device-width的值为375

所以我们通过width=device-width这句话,间接的将布局视口的尺寸设为了375,也就是说,如果我们能改变理想视口的尺寸,也就改变了布局适口的尺寸,如何改变理想视口的尺寸呢?这就要讲到缩放了,上一篇我们讲到过缩放,缩放是缩小或放大CSS像素的过程,以iphone6为例,当我们缩放比例为1:1的时候,由于iphone6的设备像素比为2,所以iphone6的设备像素与CSS像素的关系看起来就像下图这样:

图片 9

一个CSS像素宽度等于两个设备像素宽度,所以750px的设备宽度的布局视口为357CSS像素。这是在缩放比例为1的情况下,既然缩放可以放大或缩小CSS像素,所以如果我们将CSS像素的宽度缩放至与设备像素宽度相等了,那么750个设备像素也就能显示750个CSS像素,缩放后的设备像素与CSS像素看起来应该像下图这样:

图片 10

但是,我们的缩放倍数是多少呢?在缩放比例为1的时候,一个CSS像素的宽度 = 两个设备像素的宽度,如果我们想让 一个CSS像素的宽度 = 一个设备像素的宽度,我们就要将CSS像素缩小为原来的0.5倍,实际上,我们缩小的倍数 = 设备像素比的倒数。
于是,我们修改上面的HTML代码(修改了meta标签):

JavaScript

<html> <head> <title></title> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width,initial-scale=0.5,maximum-scale=0.5,user-scalable=no" /> <style> body{ margin: 0; padding: 0; } .box{ width: 200px; height: 200px; background: red; } </style> </head> <body> <div class="box"></div> </body> </html>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<html>
<head>
    <title></title>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width,initial-scale=0.5,maximum-scale=0.5,user-scalable=no" />
    <style>
    body{
        margin: 0;
        padding: 0;
    }
    .box{
        width: 200px;
        height: 200px;
        background: red;
    }
    </style>
</head>
<body>
 
    <div class="box"></div>
 
</body>
</html>

注意,上面代码中我们给红色方块使用的CSS尺寸直接使用的是psd稿中测量的尺寸,我们刷新页面,怎么样?满意吧:

图片 11

但是我们这是有个前提的,那就是缩放0.5倍只适用于设备像素比为2的设备(因为缩放值 = 1 / 设备像素比)。所以,为了适应所有的设备,我们应该用javascript代码动态生成meta标签:

var scale = 1 / window.devicePixelRatio; document.querySelector('meta[name="viewport"]').setAttribute('content','width=device-width,initial-scale='

  • scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no');
1
2
var scale = 1 / window.devicePixelRatio;
document.querySelector('meta[name="viewport"]').setAttribute('content','width=device-width,initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no');

其中 window.devicePixelRatio 的值为设备像素比。
于是我们的代码变成了这样:

JavaScript

<html> <head> <title></title> <meta charset="utf-8" /> <meta name="viewport" content="" /> <style> body{ margin: 0; padding: 0; } .box{ width: 200px; height: 200px; background: red; } </style> </head> <body> <div class="box"></div> <script> var scale = 1 / window.devicePixelRatio; document.querySelector('meta[name="viewport"]').setAttribute('content','width=device-width,initial-scale='

  • scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no'); </script> </body> </html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<html>
<head>
    <title></title>
    <meta charset="utf-8" />
    <meta name="viewport" content="" />
    <style>
    body{
        margin: 0;
        padding: 0;
    }
    .box{
        width: 200px;
        height: 200px;
        background: red;
    }
    </style>
</head>
<body>
 
    <div class="box"></div>
 
    <script>
    var scale = 1 / window.devicePixelRatio;
    document.querySelector('meta[name="viewport"]').setAttribute('content','width=device-width,initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no');
    </script>
</body>
</html>

上面的代码最终能保证一个问题,那就是无论任何设备,布局视口的宽度总是等于设备像素。
这样,我们在设计图中测量为200px的宽度就能直接用在CSS中了,并且在iphone6中显示完好,可是别忘了,我们的设计图就是根据iphone6设计的,如果换做其他设备,还能显示完好么?我们不妨试一下,如下图,是上面代码在iphone5和iphone6下的对比:

图片 12

图片 13

我们发现,无论是五还是6,即使设备像素变了,即屏幕宽度变了,可是红色方块的宽度并没有变,这并不是一个好的现象,因为这样页面的元素就不成比例了,会影响到布局,所以我们要想办法让我们页面的元素跟着设备变化而等比缩放,这就是我们要解决的第二个问题,怎么实现呢?这就要讲到rem的知识点了。

简单事情简单做-宽度自适应

所谓宽度自适应严格来说是一种PC端的自适应布局方式在移动端的延伸。在处理PC端的前端界面时候需要用到全屏布局时采用的就是此种布局方式。它的实现方式也比较简单,将外层容器元素按照百分比铺满地方式,里面的子元素固定或者左右浮动。

CSS

.div { width:100%; height:100px; } .child { float: left; } .child { float:right; }

1
2
3
4
5
6
7
8
9
.div {
  width:100%; height:100px;
}
.child {
  float: left;
}
.child {
  float:right;
}

由于父级元素采用百分比的布局方式,随着屏幕的拉伸,它的宽度会无限的拉伸。而子元素由于采用了浮动,那么它们的位置也会固定在两端。该宽度自适应在新的时代有了新的方法,随着弹性布局的普及,它经常被flex或者box这样的伸缩性布局方式替代,变得越来越“弹性”十足。需要了解弹性布局,请前往Flex布局教程和卤煮box布局教程比较。

简单事情简单做-宽度自适应所谓宽度自适应严格来说是一种PC端的自适应布局方式在移动端的延伸。在处理PC端的前端界面时候需要用到全屏布局时采用的就是此种布局方式。它的实现方式也比较简单,将外层容器元素按照百分比铺满地方式,里面的子元素固定或者左右浮动。

图片 14

rem

什么是rem?
rem是相对尺寸单位,相对于html标签字体大小的单位,举个例子:
如果html的font-size = 18px;
那么1rem = 18px,需要记住的是,rem是基于html标签的字体大小的。

相信你已经明白了,对没错,我们要把之前用px做元素尺寸的单位换成rem,所以,现在的问题就是如果转换,因为rem是根据html标签的font-size值确定的,所以我们只要确定html标签的font-size值就行了,我们首先自己定一个标准,就是让font-size的值等于设备像素的十分之一,即:

document.documentElement.style.fontSize = document.documentElement.clientWidth / 10 + 'px';

1
document.documentElement.style.fontSize = document.documentElement.clientWidth / 10 + 'px';

以iphone6为例,html标签的font-size的值就等于 750 / 10 = 75px 了,这样 1rem = 75px,所以红色方块200px换算为rem单位就是 200 / 75 = 2.6666667rem。
那么在iphone5中呢?因为iphone5的设备像素为640,所以iphone的html标签的font-size的值为 640 / 10 = 64px,所以 1rem = 64px,所以在iphone6中显示为200px的元素在iphone5中会显示为 2.6666667 * 64 像素,这样,在不同设备中就实现了让元素等比缩放从而不影响布局。而上面的方法也是手机淘宝所用的方法。所以,现在你只需要将你测量的尺寸数据除以75就转换成了rem单位,如果是iPhone5就要除以64,即除以你动态设置的font-size的值。

另外需要注意的是:做页面的时候文字字体大小不要用rem换算,还是使用px做单位。后面会讲到。

让我们来总结一下我们现在了解的方法:

1、将布局视口大小设为设备像素尺寸:

var scale = 1 / window.devicePixelRatio; document.querySelector('meta[name="viewport"]').setAttribute('content','width=device-width,initial-scale='

  • scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no');
1
2
var scale = 1 / window.devicePixelRatio;
document.querySelector('meta[name="viewport"]').setAttribute('content','width=device-width,initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no');

2、动态设置html字体大小:

document.documentElement.style.fontSize = document.documentElement.clientWidth / 10 + 'px';

1
document.documentElement.style.fontSize = document.documentElement.clientWidth / 10 + 'px';

3、将设计图中的尺寸换算成rem

元素的rem尺寸 = 元素的psd稿测量的像素尺寸 / 动态设置的html标签的font-size值

说了一大堆,其实我们使用下面的html莫板就可以写页面了,唯一需要你做的就是计算元素的rem尺寸,所以即使你没看懂上面的讲述也不重要,你只要将莫板拿过去用就好了:

JavaScript

<html> <head> <title></title> <meta charset="utf-8" /> <meta name="viewport" content="" /> </head> <body> <script> var scale = 1 / window.devicePixelRatio; document.querySelector('meta[name="viewport"]').setAttribute('content','width=device-width,initial-scale='

  • scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no'); document.documentElement.style.fontSize = document.documentElement.clientWidth / 10 + 'px'; </script> </body> </html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<html>
<head>
    <title></title>
    <meta charset="utf-8" />
    <meta name="viewport" content="" />
</head>
<body>
 
 
 
    <script>
    var scale = 1 / window.devicePixelRatio;
    document.querySelector('meta[name="viewport"]').setAttribute('content','width=device-width,initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no');
 
    document.documentElement.style.fontSize = document.documentElement.clientWidth / 10 + 'px';
    </script>
</body>
</html>

现在我们使用上面的方法修改我们的代码如下:

JavaScript

<html> <head> <title></title> <meta charset="utf-8" /> <meta name="viewport" content="" /> <style> body{ margin: 0; padding: 0; } .box{ width: 2.66666667rem; height: 2.66666667rem; background: red; } </style> </head> <body> <div class="box"></div> <script> var scale = 1 / window.devicePixelRatio; document.querySelector('meta[name="viewport"]').setAttribute('content','width=device-width,initial-scale='

  • scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no'); document.documentElement.style.fontSize = document.documentElement.clientWidth / 10 + 'px'; </script> </body> </html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<html>
<head>
    <title></title>
    <meta charset="utf-8" />
    <meta name="viewport" content="" />
    <style>
    body{
        margin: 0;
        padding: 0;
    }
    .box{
        width: 2.66666667rem;
        height: 2.66666667rem;
        background: red;
    }
    </style>
</head>
<body>
 
    <div class="box"></div>
 
    <script>
    var scale = 1 / window.devicePixelRatio;
    document.querySelector('meta[name="viewport"]').setAttribute('content','width=device-width,initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no');
 
    document.documentElement.style.fontSize = document.documentElement.clientWidth / 10 + 'px';
    </script>
</body>
</html>

打开浏览器,分别在iPhone6和iPhone5下查看页面,我们会发现,现在的元素可以根据手机的尺寸不同而等比缩放了。

上面的方法是手机淘宝的方法,有一个缺点,就是转化rem单位的时候,需要除以font-size的值,淘宝用的是iPhone6的设计图,所以淘宝转换尺寸的时候要除以75,这个值可不好算,所以还要借用计算器来完成,影响开发效率,另外,在转还rem单位时遇到除不尽的数时我们会采用很长的近似值比如上面的2.6666667rem,这样可能会使页面元素的尺寸有偏差。

除了上面的方法比较通用之外,还有一种方式,我们来重新思考一下:

上面做页面的思路是:拿到设计图,比如iPhone6的设计图,我们就将浏览器设置到iPhone6设备调试,然后使用js动态修改meta标签,使布局视口的尺寸等于设计图尺寸,也就是设备像素尺寸,然后使用rem替代px做尺寸代为,使得页面在不同设备中等比缩放。

现在假如我们不去修改meta标签,正常使用缩放为1:1的meta标签,即使用如下meta标签:

<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no"/>

1
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no"/>

还以iPhone6为例,我们知道,在缩放为1:1的情况下,根据公式:

设备像素比(DPR) = 设备像素个数 / 理想视口像素个数(device-width)

我们知道:
设备像素 = 设计图尺寸 = 750px
布局视口 = 375px

假设我们以iPhone6设计图尺寸为标准,在设计图的尺寸下设置一个font-size值为100px。
也就是说:750px宽的页面,我们设置100px的font-size值,那么页面的宽度换算为rem就等于 750 / 100 = 7.5rem。

我们就以页面总宽为7.5rem为标准,那么在布局视口中,也就是页面总宽为375px下,font-size值应该是多少?很简单:

font-size = 375 / 7.5 = 50px

那么在iPhone5下呢?因为iPhone5的布局视口宽为320px,所以如果页面总宽以7.5为标准,那么iPhone5下我们设置的font-size值应该是:

font-size = 320 / 7.5 =42.666666667px

也就是说,不管在什么设备下,我们都可以把页面的总宽度设为一个以rem为单位的定值,比如本例就是7.5rem,只不过,我们需要根据布局视口的尺寸动态设置font-size的值:

document.documentElement.style.fontSize = document.documentElement.clientWidth / 7.5 + 'px';

1
document.documentElement.style.fontSize = document.documentElement.clientWidth / 7.5 + 'px';

这样,无论在什么设备下,我们页面的总宽度都是7.5rem,所以我们直接在设计图上测量px单位的尺寸,然后除以100转换成rem单位后直接使用就可以了,比如,在iPhone6设计图中测量一个元素的尺寸为200px,那么转换成rem单位就是 200 / 100 = 2rem,因为在不同设备下我们动态设置了html标签的font-size值,所以不同设备下相同的rem值对应的像素值是不同的,这样就实现了在不同设备下等比缩放。我们修改html代码如下:

JavaScript

<html> <head> <title></title> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no" /> <style> body{ margin: 0; padding: 0; } .box{ width: 2rem; height: 2rem; background: red; } </style> </head> <body> <div class="box"></div> <script> document.documentElement.style.fontSize = document.documentElement.clientWidth / 7.5 + 'px'; </script> </body> </html>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<html>
<head>
    <title></title>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no" />
    <style>
    body{
        margin: 0;
        padding: 0;
    }
    .box{
        width: 2rem;
        height: 2rem;
        background: red;
    }
    </style>
</head>
<body>
 
    <div class="box"></div>
 
    <script>
    document.documentElement.style.fontSize = document.documentElement.clientWidth / 7.5 + 'px';
    </script>
</body>
</html>

刷新页面,分别在iPhone6和iPhone5下调试查看结果,会发现如下图,使我们想要的效果,等比缩放,ok,实际上这种做法也是网易的做法:

图片 15

图片 16

下面,我们来总结一下第二种做法:

1、拿到设计图,计算出页面的总宽,为了好计算,取100px的font-size,如果设计图是iPhone6的那么计算出的就是7.5rem,如果页面是iPhone5的那么计算出的结果就是6.4rem。
2、动态设置html标签的font-size值:

document.documentElement.style.fontSize = document.documentElement.clientWidth / 以rem为单位的页面总宽 + 'px';

1
  document.documentElement.style.fontSize = document.documentElement.clientWidth / 以rem为单位的页面总宽 + 'px';

如iPhone6的设计图就是:

document.documentElement.style.fontSize = document.documentElement.clientWidth / 7.5 + 'px';

1
  document.documentElement.style.fontSize = document.documentElement.clientWidth / 7.5 + 'px';

iPhone5的设计图就是:

document.documentElement.style.fontSize = document.documentElement.clientWidth / 6.4 + 'px';

1
  document.documentElement.style.fontSize = document.documentElement.clientWidth / 6.4 + 'px';

3、做页面是测量设计图的px尺寸除以100得到rem尺寸。
4、和淘宝的做法一样,文字字体大小不要使用rem换算。

下面是这种做法的html模板:

JavaScript

<html> <head> <title></title> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no" /> <style> body{ margin: 0; padding: 0; } .box{ width: 2rem; height: 2rem; background: red; } </style> </head> <body> <div class="box"></div> <script> document.documentElement.style.fontSize = document.documentElement.clientWidth / 7.5 + 'px'; </script> </body> </html>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<html>
<head>
    <title></title>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no" />
    <style>
    body{
        margin: 0;
        padding: 0;
    }
    .box{
        width: 2rem;
        height: 2rem;
        background: red;
    }
    </style>
</head>
<body>
 
    <div class="box"></div>
 
    <script>
    document.documentElement.style.fontSize = document.documentElement.clientWidth / 7.5 + 'px';
    </script>
</body>
</html>

由于这种做法在开发中换算rem单位的时候只需要将测量的尺寸除以100即可,所以不需要使用计算器我们就可以很快的完成计算转换,所以这也会提升开发效率,本人也比较青睐这种做法。

另外,无论是第一种做法还是第二种做法,我们都提到了,文字字体大小是不要换算成rem做单位的,而是使用媒体查询来进行动态设置,比如下面的代码就是网易的代码:

代码片段一:

@media screen and (max-width: 321px) { body { font-size:16px } } @media screen and (min-width: 321px) and (max-width:400px) { body { font-size:17px } } @media screen and (min-width: 400px) { body { font-size:19px } }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@media screen and (max-width: 321px) {
    body {
        font-size:16px
    }
}
 
@media screen and (min-width: 321px) and (max-width:400px) {
    body {
        font-size:17px
    }
}
 
@media screen and (min-width: 400px) {
    body {
        font-size:19px
    }
}

代码片段二:

@media screen and (max-width: 321px) { header,footer { font-size:16px } } @media screen and (min-width: 321px) and (max-width:400px) { header,footer { font-size:17px } } @media screen and (min-width: 400px) { header,footer { font-size:19px } }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@media screen and (max-width: 321px) {
    header,footer {
        font-size:16px
    }
}
 
@media screen and (min-width: 321px) and (max-width:400px) {
    header,footer {
        font-size:17px
    }
}
 
@media screen and (min-width: 400px) {
    header,footer {
        font-size:19px
    }
}

我们总结一下网易在文字字体大小上的做法,在媒体查询阶段,分为三个等级分别是:
321px以下
321px – 400px之间
400px以上

具体文字大小要多少个像素这个以设计图为准,但是这三个等级之间是有规律的,仔细观察发现,321px以下的屏幕字体大小比321px – 400px之间的屏幕字体大小要小一个像素,而321px – 400px之间的屏幕字体大小要比400以上屏幕字体大小要小2个像素。依照这个规律,我们根据设计图所在的像素区段先写好该区段的字体大小,然后分别写出另外两个区段的字体大小媒体查询代码就可以了。

终于码完了这第二篇文章,无力再多说其他的话,望对大家有帮助,有些细节地方没有细说,另外作者水平有限,希望大家指正共同进步,谢谢。

1 赞 3 收藏 评论

图片 17

大小之辨-完全自适应

“完全自适应式”是卤煮对越此方案的叫法,由于卤煮现在找不到官方名称,所以暂时就这样叫它。这种解决方案相对前一种来说进步不少,不仅仅宽度实现了自适应,而且界面所有的元素大小和高度都会根据不同分辨率和屏幕宽度的设备来调整元素、字体、图片、高度等属性的值。简单来说就是在不同的屏幕下,你看到的字体和元素高宽度的大小是不一样的。在这里,有人就会说利用的是媒体查询熟悉,根据不同的屏幕宽度,调整样式。卤煮之前也是这样想的,但是你需要考虑到界面上的许多元素需要设置字体,如果用media query为每个元素在不同的设备下都设置不同的属性的话,那么有多少种屏幕我们的css就会增加多少倍。实际上在这里,我们采用的是js和css熟悉rem来解决这个问题的。

REM属性指的是相对于根元素设置某个元素的字体大小。它同时也可以用作为设置高度等一系列可以用px来标注的单位。

CSS

html { font-size: 10px; } div { font-size: 1rem; height: 2rem; width: 3rem; border: .1rem solid #000; }

1
2
3
4
5
6
7
8
9
10
html {
font-size: 10px;
}
div {
font-size: 1rem;
height: 2rem;
width: 3rem;
border: .1rem solid #000;
}

采用以上写法,div继承到了html节点的font-size,为本身定义了一系列样式属性,此时1em计算为10px,即根节点的font-size值。所以,这时div的高度就是20px,宽度是30px,边框是1px,字体大小则是10px;一旦有了这样的方法,我们自然可以根据不同的屏幕宽度设置不同的根节点字体大小。假设我们现在设计的标准是iphone5s,iphone5系列的屏幕分辨率是640。为了统一规范,我们将iphone5 分辨率下的根元素font-size设置为100px;

CSS

<!--iphone5--> html { font-size: 100px; }

1
2
3
4
<!--iphone5-->
html {
font-size: 100px;
}

那么以此为基准,可以计算出一个比例值6.4。我们可以得知其他手机分辨率的设备下根元素字体大小:

JavaScript

/* 数据计算公式 640/100 = device-width / x 可以设置其他设备根元素字体大小 ihone5: 640 : 100 iphone6: 750 : 117 iphone6s: 1240 : 194 */ var deviceWidth = window.documentElement.clientWidth; document.documentElement.style.fontSize = (deviceWidth / 6.4) + 'px';

1
2
3
4
5
6
7
8
/*
数据计算公式 640/100 = device-width / x  可以设置其他设备根元素字体大小
ihone5: 640  : 100
iphone6: 750 : 117
iphone6s: 1240 : 194
*/
var deviceWidth = window.documentElement.clientWidth;
document.documentElement.style.fontSize = (deviceWidth / 6.4) + 'px';

在head中,我们将以上代码加入,动态地改变根节点的font-size值,得到如下结果:

图片 18

图片 19

图片 20

接下来我们可以根据根元素的字体大小用rem设置各种属性的相对值。当然,如果是移动设备,屏幕会有一个上下限制,我们可以控制分辨率在某个范围内,超过了该范围,我们就不再增加根元素的字体大小了:

JavaScript

var deviceWidth = document.documentElement.clientWidth > 1300 ? 1300 : document.documentElement.clientWidth; document.documentElement.style.fontSize = (deviceWidth / 6.4) + 'px';

1
2
var deviceWidth = document.documentElement.clientWidth > 1300 ? 1300 : document.documentElement.clientWidth;
document.documentElement.style.fontSize = (deviceWidth / 6.4) + 'px';

一般的情况下,你是不需要考虑屏幕动态地拉伸和收缩。当然,假如用户开启了转屏设置,在网页加载之后改变了屏幕的宽度,那么我们就要考虑这个问题了。解决此问题也很简单,监听屏幕的变化就可以做到动态切换元素样式:

JavaScript

window.onresize = function(){ var deviceWidth = document.documentElement.clientWidth > 1300 ? 1300 : document.documentElement.clientWidth; document.documentElement.style.fontSize = (deviceWidth / 6.4) + 'px'; };

1
2
3
4
window.onresize = function(){
      var deviceWidth = document.documentElement.clientWidth > 1300 ? 1300 : document.documentElement.clientWidth;
      document.documentElement.style.fontSize = (deviceWidth / 6.4) + 'px';
};

为了提高性能,让代码开起来更加完美,可以为它加上节流阀函数:

JavaScript

window.onresize = _.debounce(function() { var deviceWidth = document.documentElement.clientWidth > 1300 ? 1300 : document.documentElement.clientWidth; document.documentElement.style.fontSize = (deviceWidth / 6.4) + 'px'; }, 50);

1
2
3
4
window.onresize = _.debounce(function() {
      var deviceWidth = document.documentElement.clientWidth > 1300 ? 1300 : document.documentElement.clientWidth;
      document.documentElement.style.fontSize = (deviceWidth / 6.4) + 'px';
}, 50);

顺带解决高保真标注与实际开发值比例问题

如果你们设计稿标准是iphone5,那么拿到设计稿的时候一定会发现,完全不能按照高保真上的标注来写css,而是将各个值取半,这是因为移动设备分辨率不一样。设计师们是在真实的iphone5机器上做的标注,而iphone5系列的分辨率是640,实际上我们在开发只需要按照320的标准来。为了节省时间,不至于每次都需要将标注取半,我们可以将整个网页缩放比例,模拟提高分辨率。这个做法很简单,为不同的设备设置不同的meta即可:

JavaScript

var scale = 1 / devicePixelRatio; document.querySelector('meta[name="viewport"]').setAttribute('content', 'initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no');

1
2
var scale = 1 / devicePixelRatio;
document.querySelector('meta[name="viewport"]').setAttribute('content', 'initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no');

这样设置同样可以解决在安卓机器下1px像素看起来过粗的问题,因为在像素为1px的安卓下机器下,边框的1px被压缩成了0.5px了。总之是一劳永逸!淘宝和网易新闻的手机web端就是采用以上这种方式,自适应各种设备屏幕的,大家有兴趣可以去参考参考。下面是完整的代码:

XHTML

<!DOCTYPE html> <html> <head> <title>测试</title> <meta name="viewport" content="width=device-width,user-scalable=no,maximum-scale=1" /> <script type="text/javascript"> (function() { // deicePixelRatio :设备像素 var scale = 1 / devicePixelRatio; //设置meta 压缩界面 模拟设备的高分辨率 document.querySelector('meta[name="viewport"]').setAttribute('content', 'initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no'); //debounce 为节流函数,自己实现。或者引入underscoure即可。 var reSize = _.debounce(function() { var deviceWidth = document.documentElement.clientWidth > 1300 ? 1300 : document.documentElement.clientWidth; //按照640像素下字体为100px的标准来,得到一个字体缩放比例值 6.4 document.documentElement.style.fontSize = (deviceWidth / 6.4) + 'px'; }, 50); window.onresize = reSize; })(); </script> <style type="text/css"> html { height: 100%; width: 100%; overflow: hidden; font-size: 16px; } div { height: 0.5rem; widows: 0.5rem; border: 0.01rem solid #19a39e; } ........ </style> <body> <div> </div> </body> </html>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
<!DOCTYPE html>
<html>
<head>
  <title>测试</title>
  <meta name="viewport" content="width=device-width,user-scalable=no,maximum-scale=1" />
  <script type="text/javascript">
(function() {
  // deicePixelRatio :设备像素
  var scale = 1 / devicePixelRatio;
  //设置meta 压缩界面 模拟设备的高分辨率
  document.querySelector('meta[name="viewport"]').setAttribute('content', 'initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no');
  //debounce 为节流函数,自己实现。或者引入underscoure即可。
  var reSize = _.debounce(function() {
      var deviceWidth = document.documentElement.clientWidth > 1300 ? 1300 : document.documentElement.clientWidth;
      //按照640像素下字体为100px的标准来,得到一个字体缩放比例值 6.4
      document.documentElement.style.fontSize = (deviceWidth / 6.4) + 'px';
  }, 50);
  window.onresize = reSize;
})();
  </script>
  <style type="text/css">
    html {
      height: 100%;
      width: 100%;
      overflow: hidden;
      font-size: 16px;
    }
    div {
      height: 0.5rem;
      widows: 0.5rem;
      border: 0.01rem solid #19a39e;
    }
    ........
  </style>
  <body>
    <div>
    </div>
  </body>
</html>

.div { width:100%; height:100px;}
.child { float: left; }
.child { float:right;}

 

让元素飞起来-媒体查询

运用css新属性media query 特性也可以实现我们上说到过的布局样式。为尺寸设置根元素字体大小:

CSS

@media screen and (device-width: 640px) { /*iphone4/iphon5*/ html { font-size: 100px; } } @media screen and (device-width: 750px) { /*iphone6*/ html { font-size: 117.188px; } } @media screen and (device-width: 1240px) { /*iphone6s*/ html { font-size: 194.063px; } }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@media screen and (device-width: 640px) { /*iphone4/iphon5*/
      html {
        font-size: 100px;
      }
    }
@media screen and (device-width: 750px) { /*iphone6*/
      html {
        font-size: 117.188px;
      }
    }
@media screen and (device-width: 1240px) { /*iphone6s*/
      html {
        font-size: 194.063px;
      }
    }

这种方式也是可行的,缺点是灵活性不高,取每个设备的精确值需要自己去计算,所以只能取范围值。考虑设备屏幕众多,分辨率也参差不齐,把每一种机型的css代码写出来是不太可能的。但是它也有优点,就是无需监听浏览器的窗口变化,它会跟随屏幕动态变化。媒体查询的用法当然不仅仅像在此处这么简单,相对于第二种自适应来说有很多地方是前者所远远不及的。最明显的就是它可以根据不同设备显示不同的布局样式!请注意,这里已经不是改变字体和高度那么简单了,它直接改变的是布局样式!

CSS

@media screen and (min-width: 320px) and (max-width: 650px) { /*手机*/ .class { float: left; } } @media screen and (min-width: 650px) and (max-width: 980px) { /*pad*/ .class { float: right; } } @media screen and (min-width: 980px) and (max-width: 1240px) { /*pc*/ .class { float: clear; } }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@media screen and (min-width: 320px) and (max-width: 650px) { /*手机*/
  .class {
    float: left;
  }
}
@media screen and (min-width: 650px) and (max-width: 980px) { /*pad*/
  .class {
    float: right;
  }
}
@media screen and (min-width: 980px)  and (max-width: 1240px) { /*pc*/
  .class {
    float: clear;
  }
}

此种自适应布局一般常用在兼容PC和手机设备,由于屏幕跨度很大,界面的元素以及远远不是改改大小所能满足的。这时候需要重新设计整界面的布局和排版了:

如果屏幕宽度大于1300像素

图片 21

如果屏幕宽度在600像素到1300像素之间,则6张图片分成两行。

图片 22

如果屏幕宽度在400像素到600像素之间,则导航栏移到网页头部。

图片 23

许多css框架经常用到这样的多端解决方案,著名的bootstrap就是采用此种方式进行栅格布局的。

由于父级元素采用百分比的布局方式,随着屏幕的拉伸,它的宽度会无限的拉伸。而子元素由于采用了浮动,那么它们的位置也会固定在两端。该宽度自适应在新的时代有了新的方法,随着弹性布局的普及,它经常被flex或者box这样的伸缩性布局方式替代,变得越来越“弹性”十足。

好了,让我们开始吧,从哪里开始呢?从设计图开始,即PSD稿件:移动端PSD稿件的尺寸肯定较之PC端的PSD稿件不同,具体体现在设计图的尺寸上,现在移动端的设计图尺寸大多以iPhone5和iPhone6的设备像素尺寸作为依据,比如拿到一张PSD设计图,它的总宽度为640px(iPhone5)或者750px(iPhone6)。本例就拿iPhone6的设计图尺寸为标准进行讲解,其它设计图尺寸道理是一样的,这并不影响我们的开发。

总结

不管哪一种自适应方式,我们的目的是使得开发网页在各种屏幕下变得好看:如果你的项目定位的用户群仅仅是使用某种机型的人,那么可以采用第一种自适应方式。如果你的客户主要是移动端,但是客户的设备类型庞杂,建议采用第二种方式。如果你雄心勃勃地需要建立一套兼容PC、PAD、mobile多端的一体化web应用,那么第三种选择显然是最适合你的。每种方式都有自己的利弊,根据需求权衡利害,合理地实现自适应布局,需要不停的实践和摸索。路漫漫其修远兮,吾将上下而求索。

需要了解弹性布局,请前往Flex布局教程和卤煮box布局教程比较。大小之辨-完全自适应“完全自适应式”是卤煮对越此方案的叫法,由于卤煮现在找不到官方名称,所以暂时就这样叫它。这种解决方案相对前一种来说进步不少,不仅仅宽度实现了自适应,而且界面所有的元素大小和高度都会根据不同分辨率和屏幕宽度的设备来调整元素、字体、图片、高度等属性的值。简单来说就是在不同的屏幕下,你看到的字体和元素高宽度的大小是不一样的。

 

参考资料

自适应网页设计(Responsive Web Design)
移动前端自适应解决方案和比较
移动web适配利器-rem

1 赞 13 收藏 评论

图片 24

在这里,有人就会说利用的是媒体查询,根据不同的屏幕宽度,调整样式。卤煮之前也是这样想的,但是你需要考虑到界面上的许多元素需要设置字体,如果用media query为每个元素在不同的设备下都设置不同的属性的话,那么有多少种屏幕我们的css就会增加多少倍。

首先我们要有一张设计图才行,看下图,假设我们有一张设计图,它很简单,只有一个红色的方块:

实际上在这里,我们采用的是js和css熟悉rem来解决这个问题的。REM属性指的是相对于根元素设置某个元素的字体大小。它同时也可以用作为设置高度等一系列可以用px来标注的单位。

 

html {font-size: 10px;}
div {font-size: 1rem;height: 2rem;width: 3rem;border: .1rem solid #000;}

图片 25

采用以上写法,div继承到了html节点的font-size,为本身定义了一系列样式属性,此时1em计算为10px,即根节点的font-size值。所以,这时div的高度就是20px,宽度是30px,边框是1px,字体大小则是10px;一旦有了这样的方法,我们自然可以根据不同的屏幕宽度设置不同的根节点字体大小。

 

假设我们现在设计的标准是iphone5s,iphone5系列的屏幕分辨率是640。为了统一规范,我们将iphone5 分辨率下的根元素font-size设置为100px;
html {font-size: 100px;}
那么以此为基准,可以计算出一个比例值6.4。我们可以得知其他手机分辨率的设备下根元素字体大小:

拿到了设计图,于是你开开心心的开始写代码了,你打开了编辑器,并写下了如下HTML代码:

var deviceWidth = window.documentElement.clientWidth;document.documentElement.style.fontSize = (deviceWidth / 6.4) + 'px';

 

在head中,我们将以上代码加入,动态地改变根节点的font-size值,得到如下结果:![浅谈Web自适应(三种方法)

 

(http://cdn.attach.qdfuns.com/notes/pics/201612/02/163942hfeyaarfyzz7zfzh.jpg)接下来我们可以根据根元素的字体大小用rem设置各种属性的相对值。当然,如果是移动设备,屏幕会有一个上下限制,我们可以控制分辨率在某个范围内,超过了该范围,我们就不再增加根元素的字体大小了:

<!DOCTYPE html>

<html>

<head>

    <title></title>

    <meta charset="utf-8" />

    <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no" />

</head>

<body>

 

    <div class="box"></div>

 

</body>

</html>

var deviceWidth = document.documentElement.clientWidth > 1300 ? 1300 : document.documentElement.clientWidth;document.documentElement.style.fontSize = (deviceWidth / 6.4) + 'px';

 

一般的情况下,你是不需要考虑屏幕动态地拉伸和收缩。当然,假如用户开启了转屏设置,在网页加载之后改变了屏幕的宽度,那么我们就要考虑这个问题了。解决此问题也很简单,监听屏幕的变化就可以做到动态切换元素样式:

HTML代码写好了,你用了一个带有box类的div标签作为ps稿中的红色块,经过尺寸测量,你为上面代码添加了CSS样式,最后你的代码是这样的:

window.onresize = function(){ var deviceWidth = document.documentElement.clientWidth > 1300 ? 1300 : document.documentElement.clientWidth; document.documentElement.style.fontSize = (deviceWidth / 6.4) + 'px';};

 

为了提高性能,让代码开起来更加完美,可以为它加上节流阀函数:

 

window.onresize = _.debounce(function() { var deviceWidth = document.documentElement.clientWidth > 1300 ? 1300 : document.documentElement.clientWidth; document.documentElement.style.fontSize = (deviceWidth / 6.4) + 'px';}, 50);

<!DOCTYPE html>

<html>

<head>

    <title></title>

    <meta charset="utf-8" />

    <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no" />

    <style>

    body{

        margin: 0;

        padding: 0;

    }

    .box{

        width: 200px;

        height: 200px;

        background: red;

    }

    </style>

</head>

<body>

 

    <div class="box"></div>

 

</body>

</html>

顺带解决高保真标注与实际开发值比例问题如果你们设计稿标准是iphone5,那么拿到设计稿的时候一定会发现,完全不能按照高保真上的标注来写css,而是将各个值取半,这是因为移动设备分辨率不一样。设计师们是在真实的iphone5机器上做的标注,而iphone5系列的分辨率是640,实际上我们在开发只需要按照320的标准来。
为了节省时间,不至于每次都需要将标注取半,我们可以将整个网页缩放比例,模拟提高分辨率。这个做法很简单,为不同的设备设置不同的meta即可:

 

var scale = 1 / devicePixelRatio;document.querySelector('meta[name="viewport"]').setAttribute('content', 'initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no');

上面的代码中,你只是在原来的基础上增加了CSS样式,首先你清除了body标签上的默认样式,这个没什么好说的,然后你根据设计图中测量的尺寸来给box编写样式,宽200px;高200px;背景红色。看上去并没有什么问题,于是你开开心心的打开浏览器,刷新页面,你的脸色沉了下来,因为你看到了你不想看到的结果,如下图,上图为设计稿的样式,下图为你编写的html文件的样式:

这样设置同样可以解决在安卓机器下1px像素看起来过粗的问题,因为在像素为1px的安卓下机器下,边框的1px被压缩成了0.5px了。总之是一劳永逸!淘宝和网易新闻的手机web端就是采用以上这种方式,自适应各种设备屏幕的,大家有兴趣可以去参考参考。下面是完整的代码:html 代码

 

<!DOCTYPE html>
<html>
<head>
<title>测试</title>
<meta name="viewport" content="width=device-width,user-scalable=no,maximum-scale=1" />
<script type="text/javascript">
(function() {
// deicePixelRatio :设备像素
var scale = 1 / devicePixelRatio;
//设置meta 压缩界面 模拟设备的高分辨率
document.querySelector('meta[name="viewport"]').setAttribute('content', 'initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no');
//debounce 为节流函数,自己实现。或者引入underscoure即可。
var reSize = _.debounce(function() {
var deviceWidth = document.documentElement.clientWidth > 1300 ? 1300 : document.documentElement.clientWidth;
//按照640像素下字体为100px的标准来,得到一个字体缩放比例值 6.4
document.documentElement.style.fontSize = (deviceWidth / 6.4) + 'px';
}, 50);

图片 26

window.onresize = reSize;
})();
</script>
<style type="text/css">
html {
height: 100%;
width: 100%;
overflow: hidden;
font-size: 16px;
}

图片 27

div {
  height: 0.5rem;
  widows: 0.5rem;

 

让元素飞起来-媒体查询运用css新属性media query 特性也可以实现我们上说到过的布局样式。为尺寸设置根元素字体大小:
@media screen and (device-width: 640px) { html { font-size: 100px; } }@media screen and (device-width: 750px) { html { font-size: 117.188px; } }@media screen and (device-width: 1240px) { html { font-size: 194.063px; } }
这种方式也是可行的,缺点是灵活性不高,取每个设备的精确值需要自己去计算,所以只能取范围值。考虑设备屏幕众多,分辨率也参差不齐,把每一种机型的css代码写出来是不太可能的。
但是它也有优点,就是无需监听浏览器的窗口变化,它会跟随屏幕动态变化。媒体查询的用法当然不仅仅像在此处这么简单,相对于第二种自适应来说有很多地方是前者所远远不及的。最明显的就是它可以根据不同设备显示不同的布局样式!

通过对比psd原稿和我们目前所写的html页面,可以看出我们html页面的问题,红色方块与整个页面的比例和psd原稿不一样啊,那么为什么我们明明是按照原稿测量的尺寸写出来的代码却和psd原稿显示的效果不一样呢?别忘了,psd原稿的尺寸是按照设备像素设计的,由于我们所用的设计稿是基于iPhone6设计的,所以我们设计稿的尺寸就是iPhone6的设备像素的尺寸,也就是750px,而我们CSS中的样式是基于布局视口的尺寸计算的,由于我们html页面中由于写入了以下meta标签:

请注意,这里已经不是改变字体和高度那么简单了,它直接改变的是布局样式!@media screen and (min-width: 320px) and (max-width: 650px) { .class { float: left; }}
@media screen and (min-width: 650px) and (max-width: 980px) { .class { float: right; }}
@media screen and (min-width: 980px) and (max-width: 1240px) { .class { float: clear; }}

 

此种自适应布局一般常用在兼容PC和手机设备,由于屏幕跨度很大,界面的元素以及远远不是改改大小所能满足的。这时候需要重新设计整界面的布局和排版了:如果屏幕宽度大于1300像素![浅谈Web自适应(三种方法)]

<meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no"/>

(http://cdn.attach.qdfuns.com/notes/pics/201612/02/163942oave3gugrdgyvx3z.jpg)如果屏幕宽度在600像素到1300像素之间,则6张图片分成两行。

 

图片 28

在上一篇我们讲过, width=device-width 这段代码是让布局视口的尺寸等于理想视口。

浅谈Web自适应(三种方法)

根据公式(缩放比例为1):

如果屏幕宽度在400像素到600像素之间,则导航栏移到网页头部。
许多css框架经常用到这样的多端解决方案,著名的bootstrap就是采用此种方式进行栅格布局的。
总结不管哪一种自适应方式,我们的目的是使得开发网页在各种屏幕下变得好看:如果你的项目定位的用户群仅仅是使用某种机型的人,那么可以采用第一种自适应方式。如果你的客户主要是移动端,但是客户的设备类型庞杂,建议采用第二种方式。如果你雄心勃勃地需要建立一套兼容PC、PAD、mobile多端的一体化web应用,那么第三种选择显然是最适合你的。每种方式都有自己的利弊,根据需求权衡利害,合理地实现自适应布局,需要不停的实践和摸索。路漫漫其修远兮,吾将上下而求索。

设备像素比(DPR) = 设备像素个数 / 理想视口像素个数(device-width)

因为iPhone6的DPR(设备像素比)为2,设备像素为750,所以iPhone6的理想视口尺寸为375px。所以上面代码最终导致的是:使我们布局视口的宽度变成了375px。而我们CSS中编写的样式尺寸又是基于布局视口计算的,所以我们得到的页面看上去比例不对,如下图:

 

图片 29

图片 30

 

如上面两幅图片,我们知道,psd稿的总宽是750px,元素宽200px,而我们真正做页面的时候,布局视口的宽度是375px,正好是设计稿的一半。所以我们不能直接使用设计稿上面测量所得的像素尺寸,根据比例,我们应该将测量所得的尺寸除以2,才是我们CSS中布局所用的尺寸,据此,我们将200px除以2得到100px,于是我们修改代码,将红色方块的宽高都设为100px,刷新页面,看看比例是不是和设计图一样了?答案是肯定的,如下图为修改后的html页面:

 

图片 31

 

这样,我们就得到了正确的数据,并且正确的写出了页面,你很高兴,可是问题来了,如果你在做页面的时候,测量了一个元素的宽度,宽度是一个奇数,比如111像素,按照我们之前的做法是,将测量到的数据除以2,得到我们真正使用的数据,所以111除以2等于55.5px,我们知道,计算机(手机)没办法显示不到一个像素的像素值,计算机(手机)会自动将其补全为一个像素进行显示,所以最终会将元素显示为56像素,这并不是我们想要的结果。

 

另外,我们的设计稿是基于iphone6设计的,我们调试页面也是在iphone6下调试的。又因为iphone6的设备像素比试2,所以我们才能由设计稿测量的数据除以2后直接使用,并且在iphone6下没有问题,但是你要知道,并不是所有手机的设备像素比都是2,有的手机的设备像素比试2.5或者3。并且不同设备的设备像素又不同,这样就导致理想视口的尺寸不同,从而导致布局视口的尺寸不同,那么我们直接根据iphone6的设计稿尺寸除以2得到的尺寸用来编写CSS是不能在所有设备下完好显示的。

 

所以,我们要换一个方法。

 

于是我们想到:如果我们能将布局视口的尺寸设置为和设备像素尺寸相等的话,这样我们就保证了设计图与页面的1:1关系,那么我们就可以直接使用psd中测量的尺寸了,然后在其他尺寸的手机中,我们进行等比缩放就ok了。那么如何才能让布局视口的尺寸等于设备像素尺寸呢?

本文由胜博发-前端发布,转载请注明来源:原文出处,移动端页面开发适配 rem布局原理