移动端 Web怎么循序渐进地开发一个移动端页面

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了移动端 Web怎么循序渐进地开发一个移动端页面相关的知识,希望对你有一定的参考价值。

1. 移动页面开发基础

1.1 像素——什么是像素

像素是 Web 页面布局的基础,那么到底什么才是一个像素呢?

像素:一个像素就是计算机屏幕所能显示一种特定颜色的最小区域。这是像素的概念,实际上,Web 前端开发领域,像素有以下两层含义:

(1) 设备像素:设备屏幕的物理像素,对于任何设备来讲物理像素的数量是固定的。

(2) CSS像素:这是一个抽象的概念,它是为 Web 开发者创建的。

如下图,是在缩放比例为1,即 scale = 1 的情况下,设备像素和CSS像素示意图:

 

我们再来考虑这样一个问题:当我们给一个元素设置了 width:200px; 这条样式时,到底发生了什么?

当我们给元素设置了 width:200px 时,这个元素的宽度跨越了200个CSS像素。但是它并不一定跨越了200个设备像素,至于会跨越多少个设备像素,就取决于手机屏幕的特性用户的缩放,举个例子:

苹果手机的视网膜屏幕,是一个高密度屏幕,它的像素密度是普通屏幕的两倍,所以当我们设置 width:200px;时,200个CSS像素跨越了400个设备像素,如下图:

 

如果用户缩小页面,那么CSS像素会明显小于一个设备像素,这个时候 width:200px; 这条样式中所设置的200个CSS像素跨越不了200个设备像素,如下图:

 

 让我们简单总结下:

○ Web前端领域,像素分为设备像素和CSS像素

○ 一个CSS像素的大小是可变的,比如用户缩放页面的时候,实际上就是在缩小或放大CSS像素,而设备像素无论大小还是数量都是不变的。

 

1.2 移动端的三个视口

我们应该都写过这样的样式:width:25%; 但是我们在给一个元素加上这样的样式之后发生了什么呢?我们都知道:一个块元素默认的宽度时父元素的100%,是基于父元素的,所以这里的25%指的是父元素宽度的25%,所以 body 元素的默认宽度时 html 元素的100%,那么 html元素又是基于谁的呢?这就要引出一个概念:初始包含块视口

 

1.2.1 第一个视口:布局视口

首先,我们需要了解一件事情:

浏览器厂商是希望满足用户即使在移动端,例如手机上也能浏览为PC端设计的网站,所以浏览器厂商必须想办法来满足这个需求。

在PC端浏览器中,视口只有一个,并且视口的宽度 = 浏览器窗口的宽度,但是在移动端也要根据这个来设计的话,那么PC端设计的网站会很丑,因为PC端的网页宽度有 800 以上个CSS像素。而手机屏幕要窄很多,这个时候在PC端25%的宽度在移动端看起来会很窄。所以,布局视口的概念产生了。

布局视口:移动端CSS布局的依据视口,即CSS布局会根据布局视口来计算。

也就是说:在移动端,视口和浏览器窗口将不再关联。实际上,布局视口要比浏览器窗口大得多(在手机或平板中浏览器布局视口的宽度在768~1024像素之间),布局视图和窗口的关系如下图所示:

 

可以通过以下 javascript 代码获取布局视口的宽度和高度:

document.documentElement.clientWidth;
document.documentElement.clientHeight;

 

1.2.2 第二个视口:视觉视口

视觉视口,即用户当前看到网站的区域,如下图所示:

 

1.2.3 第三个视口:理想视口

前面提到过,布局视口的宽度一般在 680~1024 像素之间,这样可以使得PC网站在手机中不被压扁,但是这样不理想。因为手机更适合窄的网站,换句话说,布局视口并不是最理想的宽度,所以就引入了理想视口。

理想视口,定义了视口的理想宽度,比如对应 iPhone 5来讲,理想视口是 320*568。但是最终作用的还是布局视口,因此我们的CSS是依据布局视口计算的.

所以我们可以这样理解视口:理想的布局视口。下面这段代码可以告诉手机浏览器要把布局视口设置为理想视口:

<meta name="viewport" content="width=device-width" />

这段代码告诉浏览器:将布局视口的宽度设为理想视口。所以,上面的代码中的 width 指的是布局视口的宽, device-width 实际上就是理想视口的宽度。

好了,移动端的三个视口介绍完了,我们总结下:

○ 在PC端,布局视图就是浏览器窗口

○ 在移动端,视口被分为两个:布局视口、视觉视口

○ 移动端还有一个理想视口,它是布局视口的理想尺寸,即理想的布局视口。(PS:理想视口的尺寸设备因设备和浏览器的不同而不同)

○ 可以将布局视口的宽度设为理想视口

 

1.3 设备像素比(DPR)

下面还需了解一个概念:设备像素比(Device Pixel Ratio,简称 DPR)。

下面的是设备像素比的计算公式,公式成立的前提是:(缩放比例为1)

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

与理想视口一样,设备像素比对于不同的设备是不同的,但是他们都是合理的,比如早期 iPhone的设备像素是320px,理想视口也是320px,所以早期 iPhone 的 DPR = 1 。而后来 iPhone 的设备像素为 640px,理想视口还是320px,所以后来 iPhone 的DPR = 2 。

在开发中,打开浏览器的调试工具可以看到设备像素比,如下图(这里是谷歌的开发者工具,缩放比例默认为1):

 

从上图,我们可以获取以下信息:

iPhone 7的理想视口是:375*667 <==> device-width = 375,device-height = 667

iPhone 7的像素比是:2

根据公式:设备像素比(DPR) = 设备像素比 / 理想视口CSS像素个数,可知 iPhone 7的设备像素为 750*1334

 

1.4 缩放

在前面设备像素比公式的时候讲到了其成立的前提是:缩放比例为1。

从前面可以了解到CSS像素的大小是可变,而缩放从技术实现的角度来讲,就是放大和缩小CSS像素。

 

1.5 meta标签

meta视口标签存在的主要目的是为了让布局视口和理想视口的宽度匹配,meta视口标签应该放在 HTML文档的 head 标签内,语法如下:

<meta name="viewport" content="name=value,name=value" />

其中,content 属性是一个字符串值,字符串是由逗号","分隔的"名/值"对组成,共有5个:

width:设置布局视口的宽
init-scale:设置页面的初始缩放程度
minimum-scale:设置了页面最小缩放程度
maximum-scale:设置了页面最大缩放程度
user-scalable:是否允许用户对页面进行缩放操作

下面是一个常用的 meta 标签实例:

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

上面这行代码的意思是:让布局视口的宽度等于理想视口的宽度,页面的初始缩放比例以及最大缩放比例都为1,且不允许用户对页面机芯缩放操作。

 

1.6 媒体查询

媒体查询是响应式设计的基础,它有以下三点作用:

1、检测媒体的类型,比如 screen,tv等
2、检测布局视口的特性,比如视口的宽高分辨率等
3、特性相关查询,比如检测浏览器是否支持某某特性(这一点不讨论,因为它被目前浏览器支持的功能对于web开发来讲很无用)

CSS 中使用媒体查询的方法:

@media 媒体类型 and (视口特性阈值) {
   // 满足条件的CSS样式代码   
}

下面是一段在CSS中使用媒体查询的示例:

@media all and (min-width:321px) and (max-width:400px){
   .box { background:red; }
}

上面代码中,媒体类型为 all,代表任何设备,并且设备的布局视口宽度大于等于321px且小于等于400px时,让拥有 box 类的元素背景变红。

 

2. 移动页面开发进阶

2.1 保持设备像素和CSS像素一致

那如何很好的开发一个移动端的页面呢?我们先从移动端的PSD设计稿件开始把。

移动端稿件尺寸和PC端的区别具体在设计图的尺寸上。我们以 iPhone 6的设计图尺寸标准为例:

这张设计图很简单,只有一个红色方块。我们可以直接就在编辑器上开始写对应的代码:

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

这代码貌似没啥问题,但运行后才发现不是想要的结果:

 

从效果图可以看到问题,红色方块与整个页面的比例和PSD原稿不一样。

那为什么我们按原稿测量的尺寸写出来的代码效果却和PSD原稿显示的不一样呢?这是因为PSD原稿的尺寸是按照设备像素设计的,所以我们设计稿的尺寸就是iPhone 6的设备像素的尺寸,也就是 750px,而我们CSS中的样式是基于布局视口的尺寸计算的,由于HTML页面中由于写入了以下meta标签:

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

在前面讲过,width=width-device 这段代码是让布局视口的尺寸等于理想视口的。

根据公式(缩放比例为1):设备像素比 = 设备像素个数 / 理想视口像素个数,iPhone 6的设备像素比为2,设备像素为750,可得其理想视口尺寸为375px,从开发者工具上也可以明显看出。而我们CSS中的样式是基于布局视口计算的,故显示的效果不同。

据此,我们需要修改红色方块的宽高,把原稿的宽高除以设备像素比,得到新的宽高为100px,效果图如下:

 

这里显示效果和PSD原稿一致。

但是,问题来了!如果我们在做页面的时候,测量了一个元素的宽度,宽度是一个奇数,比如111px。按照前面的说明,我们将测量到的数值除以2,得到的是55.5px。但是,手机没办法显示不到一个像素的像素值,会自动补全一个像素后进行显示,最终会将元素显示为56px,这并不是我们想要的结果。

另外,这里我们除以2,是因为 iPhone 6的设备像素比是2,但不是所有的移动设备的设备像素比都是2,并且不同设备的设备像素也不一样,这就导致了理想视口的尺寸是不一样的。所以,我们直接根据我们iPhone 6的设计稿得来的尺寸除以设备像素比2用来编写CSS是不能在所有设备下完好显示的。

 

因此,我们要换一个方法。

如果我们能将布局视口的尺寸设置为和设备像素尺寸相等的话,这样我们就保证了设计图与页面的1:1的关系,可以直接使用PSD原稿中测量的尺寸,然后在其他尺寸手机中进行等比例缩放就可以了。

 

那么,我们如何才能让布局视口的尺寸等于设备像素的尺寸呢?

我们注意到 meta 标签中这段代码: width=device-width,这是声明让布局视口尺寸等于理想视口的尺寸。

根据公式(缩放比例为1):设备像素比(DPR)= 设备像素个数 / 理想视口像素个数(device-width)

以 iPhone 6为例:

设备像素比(DPR):2

设备像素个数:750

所以,在缩放比例为1的情况下,iPhone 6理想视口的设备像素个数为 750 / 2 = 375,即对于 iPhone 6来说,device-width = 375 。

 

我们通过 width=device-width 这行代码,间接地将布局视口的尺寸设为了 375。

同样,我们能改变理想视口的尺寸,也就改变了布局视口的尺寸。

那如何改变理想视口的尺寸呢?这就要用到缩放了。

前面有简单讲到,缩放就是缩小或放大CSS像素的过程,以 iPhone 6为例,当缩放比为1:1时,由于iPhone 6的DPR为2,所以iPhone的设备像素与CSS像素的关系就像下图一样:

 

 一个CSS像素宽度等于两个设备像素宽度,所以750px的设备宽度的布局视口为375 CSS像素。

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

 

但是,我们的缩放倍数是多少呢?在缩放比例为1时,一个CSS像素的宽度 = 两个设备像素的宽度。

如果我们想让一个CSS像素的宽度 = 一个设备像素的宽度,我们就要将CSS像素缩小为原来的 0.5倍。

实际上,我们缩小的倍数 = 设备像素比的倒数。

 

这样,我们在不改变原稿的样式的情况下,修改前面HTML代码如下:

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

运行后,会发现现实效果和设计稿完全一致。

 

但是,这里有个前提:那就是缩放 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\');

其中, window.devicePixelRatio 的值为设备像素比。

于是,我们的HTML代码变成这样:

<!DOCTYPE html>
<html>
<head>
    <title>Red Box</title>
    <meta charset="utf-8" />
     <meta name="viewport" content="" />
    <style type="text/css">
    body{ margin: 0;padding: 0;}
    .red_box{ width: 200px;height: 200px;background: red;}
    </style>
</head>
<body>
    <div class="red_box"></div>
    <script>
    var scale = 1 / window.devicePixelRatio;
    document
    .querySelector(\'meta[name="viewport"]\') //获取 name为 viewport的 meta元素
    // 设置 content属性
    .setAttribute(\'content\',\'width=device-width,initial-scale=\' + scale + \', maximum-scale=\' + scale + \', minimum-scale=\' + scale + \', user-scalable=no\');
    </script>
</body>
</html>

 

这样就保证了,在任何设备下,布局视口的宽度总是等于设备像素。

我们来简单的做下对比,下面两张图片分部是HTML代码在模拟器 Nexus 5X 和 iPhone X 下的显示情况:

 

 

从图片中可以看到,即使设备变了,设备像素变了,DPR变了,红色方块的大小也没有改变,都是100px 。

但是,这样页面的元素就不成比例,会影响到整体布局。

我们需要让页面元素跟着设备的变化等比缩放。而这就是我们要解决的第二个问题。

那怎么实现呢?这就需要讲到 rem 了。

 

2.2 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\';

以 iPhone 6为例,html 标签的 font-size 的值就等于 750 / 10 = 75px ,红色方块 200px 换算为 rem 单位就是 200 / 75 = 2.6666667 rem。

如果以 iPhone 5为例,其设备像素为 640,font-size 则为 640 /10 = 64px,即 1rem = 64px。所以,在 iPhone 6中显示为 200px 的元素在 iPhone 5中会显示为 2.6666667 * 64 px。

这样,在不同设备中就实现了让元素等比缩放,不会影响整体布局。

PS:做页面的时候文字字体大小不要用 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\');

(2) 动态设置 html 字体大小

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

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

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

 

根据前面的说明,我们可以得到一个 HTML 页面模板:

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

 

根据模板,修正前面的 HTML 代码如下:

<!DOCTYPE html>
<html>
<head>
    <title>Red Box</title>
    <meta charset="utf-8" />
     <meta name="viewport" content="" />
    <style type="text/css">
    body{ margin: 0;padding: 0;}
    .red_box{ width: 2.66666667rem;;height: 2.66666667rem;;background: red;}
    </style>
</head>
<body>
    <div class="red_box"></div>
    <script>
    var scale = 1 / window.devicePixelRatio;
    document
    .querySelector(\'meta[name="viewport"]\') //获取 name为 viewport的 meta元素
    // 设置 content属性
    .setAttribute(\'content\',\'width=device-width,initial-scale=\' + scale + \', maximum-scale=\' + scale + \', minimum-scale=\' + scale + \', user-scalable=no\');
    // 设置页面的的 font-size 值
     document.documentElement.style.fontSize = document.documentElement.clientWidth / 10 + \'px\';
    </script>
</body>
</html>

现在,元素就可以根据手机尺寸的不同等比缩放了。

 

但是,这个方法有个缺点。第一,转化为 rem 单位时,需要除以 font-size 的值,这个值可不好算,还需要计算器来完成,影响开发效率。第二,在转为 rem 单位还会遇到除不尽的数,例如之前的例子中的 2.6666667rem,可能会使页面元素尺寸有偏差。

 

上面做页面的思路是:

拿到设计图,比如 iPhone 6的设计图,就将浏览器设置 iPhone 6设备调试,然后用 JavaScript 动态修改 meta 标签,使布局视口的尺寸等于设计图尺寸,也就是设备像素尺寸,然后使用 rem 替代 px 作为尺寸单位,使得页面在不同设备中等比缩放。

 

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

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

 继续以 iPhone 6为例,根据公式(缩放比为1):设备像素比 = 设备像素个数 / 理想视口像素个数。

我们知道:

设备像素 = 设计尺寸 = 750px

布局视口 = 375px

 

假设我们以 iPhone 6设计图尺寸为标准,在设计图的尺寸下设置一个 font-size 值为 100px。

也就是说:750px 宽的页面,我们设置 100px的 font-size 值,那么页面的宽度换算为 rem 就等于 750 / 100 = 7.5 rem 。

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

 

如下在 iPhone 5 下呢?因为 iPhone 5的布局视口宽度为 320px,所以如果页面总宽以 7.5 为标准,那么 iPhone 5下我们设置的 font-size 值是: 320 / 7.5 = 43.6666667px 。

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

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

这样,无论在什么设备情况下,我们页面的总宽度都是 7.5 rem。因此,我们直接在设计图上测量 px单位的尺寸,然后除以 100转换成 rem 单位就是 200/100 = 2rem。

因为在不用设备下我们动态设置了 html 标签的 font-size 值,所以不同设备下相同的 rem 值对应的像素值是不同的。这样就实现了在不同设备下等比缩放。

我们修改 html 代码如下:

<!DOCTYPE html>
<html>
<head>
    <title>Red Box</title>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no" />
    <style type="text/css">
    body移动端web开发框架

前端er们如何最快开发h5移动端页面

reactjs适合移动端的web页面开发吗

移动web开发之移动端真机测试

移动端Web页面适配方案(整理版)

移动端兼容