移动web基础

移动端开发现状

  • 移动web开发指的是需要适配移动设备的网页开发
  • 移动web开发与pc端web开发没有本质的区别,使用的还是HTML/CSS/JavaScript的技术
  • 移动web开发与pc端web开发的区别是什么?

移动端的浏览器与pc端不同

谷歌浏览器 苹果浏览器、 UC浏览器 QQ浏览器 欧朋浏览器 百度手机浏览器  360安全浏览器  搜狗浏览器  猎豹浏览器等
国内的手机浏览器都是根据webkit内核修改过来的,国内没有自主研发的内核,国内的操作系统也是基于Android系统修改的。

因此在移动端,css3属性只需要加webkit前缀即可。

移动端设备尺寸不一样(尺寸非常多,碎片化很严重)

Android: 320*480 480*800  540*960 720*1280 1080*1920 2k屏 4k屏
iphpne:  640*960 640*1136 750*1334 1242*2208

移动端调试问题

  1. 模拟器调试
  2. 真机调试:使用手机进行访问。

手机设备五花八门,屏幕尺寸都大不一样,尤其是安卓端,给我们的页面预览带来了一些麻烦。在实际工作中,作为开发者不可能有足够的设备让我们去测试(除了测试部门 ),即便有,效率也特别的低,因此开发者一般都是通过浏览器的手机模拟器来模拟不同的设备。

视口viewport(重要)

问题:一个电脑上的网站,在手机端访问,效果是什么样的?

iPhone5的设备宽度只有320px,一张宽度为640px的图片在手机端访问,显示的效果是什么?

1. 在手机端,html的大小都是980px,为什么?
这主要是历史原因导致的,因为在移动设备刚流行的时候,网站大多都是pc端的,pc端的页面宽度一般都比较大,移动设备的宽度比较小,如果pc端页面直接在移动端显示的话,页面就会错乱。为了解决这个问题,移动端html的大小直接就定死成了980px(因为早起的pc端网站版心就是980px居多)。

2. 视口
在pc端,html的大小默认是继承了浏览器的宽度,即浏览器多宽,html的大小就是多宽,但是在移动端,多出来了一个视口的概念(乔布斯),视口说白了就是介于浏览器与html之间的一个东西,视口的宽度默认定死了980px,因此html的宽度默认就是980px,视口的特点是能够根据设备的宽度进行缩放。

3. 视口设置。
对于现在的移动端页面来说,视口默认为980px肯定不合适,因为设备宽度不够的话,视口会进行缩放,导致页面展示效果不好看。

视口参数设置

//width 设置视口的宽度
//width=device-width   设置视口宽度为设备的宽度(常用)。

//initial-scale 设置初始缩放比例
//initial-scale=1.0  表示不缩放

//user-scalable 设置是否允许用户缩放
//user-scalable=no  不允许用户缩放

//maximum-scale  设置允许的最大缩放比例
//maximum-scale=1.0  可以不设置,因为都禁止用户缩放了。

//minimum-scale 设置允许最小缩放比
//minimum-scale=1.0  不设置,因为都禁用用户缩放了。


//标准写法:
//快捷键:  meta:vp + tab键
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0">

流式布局

移动端的特点

  • 手机端的兼容性问题比PC端小很多,因为手机端的浏览器版本比较新
  • 手机端屏幕比较小,能够放的内容比较少。
  • 手机的分辨率比电脑的分辨率高很多,所以手机的设计图一般是2倍图或者3倍图

问题:布局的时候怎么解决屏幕大小不一致的问题?

  • PC端,固定版心,让所有分辨率的电脑的版心都是一样的,比如京东
  • 移动端:移动端无法设置版心,因为移动端的设备屏幕本身就小,设置版心不合适。因此移动端大多会采用流式布局(百分比布局)

流式布局,也叫百分比布局,是移动端开发中经常使用的布局方式之一。

流式布局的特征:

  • 宽度自适应,高度写死,并不是百分百还原设计图
  • 图标都是固定死大小的,包括字体等也是固定死的。并不是所有的东西都是自适应的。
  • 一些大的图片,设置宽度为百分比自适应即可,随着屏幕大小进行变化
  • 设计图一般是2倍图或者3倍图 是为了在手机端显示更清晰

经典的流式布局

//1. 左侧固定,右侧自适应
//2. 右侧固定,左侧自适应
//3. 两侧固定,中间自适应(圣杯布局,双飞翼布局)
//4. 等分布局

等分布局

一侧固定一侧适应

左边盒子左浮动,

右边盒子添加padding值把内容挤出来

不需要盒子之间的空隙可以使用overflow:hidden

需要盒子之间的空隙使用margin把盒子把盒子挤出来。

注意:继承的宽度无法使用padding和margin

需要先浮动元素占位置,否则无法排成一排

两侧固定中间适应

首先写左右浮动元素,中间元素使用overflow:hidden触发BFC和浮动区域不重叠 或者margin

中间盒子不用写宽度

弹性布局(Flex布局)

布局:其实就是调整元素在水平和垂直方向上的布局方式。

CSS3在布局方面做了非常大的改进,使得我们对块级元素的布局排列变得十分灵活,适应性非常强,其强大的伸缩性,在响应式开中可以发挥极大的作用。

display:flex;弹性布局的根本

【演示:01-伸缩布局初体验.html】

当给一个盒子设置了display:flex之后,这个盒子就有了主轴侧轴 的概念。 主轴:Flex容器的主轴主要用来配置Flex项目,默认是水平方向 侧轴:与主轴垂直的轴称作侧轴,默认是垂直方向的 方向:默认主轴从左向右 ,默认侧轴从上到下

容器属性

flex-direction(主轴方向)

flex-diretion主要是用来调整主轴的方向的,默认是水平方向

了解即可,一般来说,很少调整主轴的方向。

可选值

row:主轴方向为水平向右
row-reverse:主轴方向为水平向左
column:主轴方向为竖直向下
column-reverse:主轴方向是竖直向上。

注意:主轴变化后,侧轴更着改变

★justify-content(主轴对齐方式)

方向:默认主轴从左向右 ,类似X轴

justify-content主要用来设置主轴方向的对齐方式 ,可选的值有:

可选值:

flex-start: 起点对齐,弹性盒子元素将向起始位置对齐
flex-end: 终点对齐,弹性盒子元素将向结束位置对齐。
center: 居中对齐,弹性盒子元素将向行中间位置对齐
space-around:环绕分布,弹性盒子元素会平均地分布在行里
space-between:两端分布,第一个贴左边,最后一个贴右边,其他盒子均分,保证每个盒子之间的空隙是相等的。
space-evenly:均衡分布

★align-items(单行侧轴对齐方式 )

默认侧轴从上到下 ,类似Y轴

align-items用于调整侧轴的对齐方式 ,可选的值有:

flex-start: 元素在侧轴的起始位置对齐。 
flex-end: 元素在侧轴的结束位置对齐。
center: 元素在侧轴上居中对齐。
stretch: 元素的高度会被拉伸到最大,不能给死高度。(默认值)

flex-wrap(换行)

flex-wrap属性控制flex容器是单行或者多行,默认不换行

nowrap: 不换行(默认),会压缩子盒子的宽度。
wrap: 当宽度不够的时候,会换行。
wrap-reverse: 颠倒换行

align-content(多行侧轴对齐方式)

align-content用来设置多行的flex容器的排列方式。

flex-start: 起点对齐,各行向侧轴的起始位置堆叠。 
flex-end: 终点对齐,各行向弹性盒容器的结束位置堆叠。
center: 居中对齐,各行向弹性盒容器的中间位置堆叠。
space-around: 环绕分布,各行在侧轴中平均分布。 
space-between: 两端分布,第一行贴上边,最后一个行贴下边,其他行在弹性盒容器中平均分布。 
space-evenly:均衡分布
stretch:拉伸对齐,不设置高度的情况下。(默认值)

align-items与align-content的区别

align-items调整的是侧轴单行的对齐方式,不换行一般用align-items
align-content:必须是多行才生效,如果单行,没有效果。换行了就用align-content。

项目属性

flex属性

上述讲的属性都是给父盒子设置的,接下来的几个属性是给子盒子设置的。

flex属性用来设置子盒子如何分配主轴空间

flex:1 剩余空间平均分占其中一份

注意:flex属性给谁就分配给谁

order属性

order属性定义项目的排列顺序。数值越小,排列越靠前,默认为0。

order:1;

align-self

align-self也是用于设置在侧轴的位置,但是align-self给子元素设置,优先级比align-items的优先级高。

取值与align-items的取值一样。

阮一峰的博客http://www.ruanyifeng.com/blog/2015/07/flex-grammar.html

【案例:6面神骰】

【案例:携程】

响应式

什么是响应式布局

响应式布局(respond layout)是Ethan Marcotte在2010年5月份提出的一个概念,简而言之,就是一个网站能够兼容多个终端(手机、平板、pc电脑) ——而不是为每个终端做一个特定的版本。这个概念是为解决移动互联网浏览而诞生的。

为什么要有响应式布局?

  • 在移动互联日益成熟的时候,在PC端开发的网页已经无法满足移动设备的要求。
  • 通常的做法是针对移动端单独做一套特定的版本。
  • 如果终端越来越多,那么需要开发的版本就会越来越多(大屏设备的普及)
  • 响应式布局一个网站能够兼容多个终端(节约开发成本)

优点:

面对不同分辨率设备灵活性强

能够快捷解决多设备显示适应问题

**缺点: **

兼容各种设备工作量大,效率低下

代码累赘,会出现隐藏无用的元素,加载时间加长

响应式开发现状:

  • 如果已经存在PC的网站了,那么一般不会使用响应式开发,而是针对移动端再开发一套系统(比如京东、淘宝)
  • 新建站点 上采用响应式开发的越来越多。
  • 在国内,响应式开发还不是特别的流行。但响应式开发是大势所趋,会越来越流行。

响应式开发与移动web开发的比较

开发方式 移动web开发+pc开发 响应式开发
引用场景 一般已经有了PC端网站,只需要端独开发移动端网站即可 针对一些新建网站,并且要求适配移动端
开发 针对性强,开发效率高 兼容各种终端,效率低
适配 只能适配移动端或者PC端,pad上体验比较差 可以适配各种终端
效率 代码简介,加载快 代码相对复杂,加载慢
//思考:响应式开发的原理是什么?

媒体查询

媒体查询(Media Query)是CSS3提出来的一个新的属性,通过媒体查询可以查询到screen的宽度,从而指定某个宽度区间的网页布局。

设备分类

分类 宽度范围
大屏设备 >1200px
中屏设备 992px~1200px
小屏设备 768px~992px
超小屏设备 < 768px

媒体查询的使用

需求:

<!--
需求:
    大屏设备(>1200px)   版心:1170px   背景色:红色
    中屏设备(992-1200)  版心:970px    背景色:蓝色
    小屏设备(768-992)   版心:750px    背景色:黄色
    超小屏设备(<768px)  版心:100%     背景色:绿色
-->

响应式开发的原理:使用媒体查询实现不同终端的布局和样式的切换。

媒体查询语法:

/*查询屏幕*/
@media screen and 条件 {
}

/*条件的写法*/
/*min-width:只要屏幕宽度超过这个值的设备样式就能生效*/
/*max-width:只要屏幕宽度小于这个值的设备样式就能生效*/
@media screen and (min-width: 1200px) {
  .container {
    width: 1170px;
    background-color: red;
  }
}

@media screen and (min-width: 992px) and (max-width: 1200px) {
  .container {
    width: 970px;
    background-color: blue;
  }
}

@media screen and (min-width: 768px) and (max-width: 992px) {
  .container {
    width: 750px;
    background-color: yellow;
  }
}

@media screen and (max-width: 768px) {
  .container {
    width: 100%;
    background-color: green;
  }
}

弊端:现在只有一个div,要做一套响应式布局,就需要如此多的代码,非常的麻烦,因此我们会更多的借助一些响应式的框架,比如bootstrap。

bootstrap框架

Bootstrap,来自 Twitter,是目前很受欢迎的前端框架。Bootstrap 是基于 HTML、CSS、JAVASCRIPT 的,它简洁灵活,使得 Web 开发更加快捷。

bootstrap中文网

特点:

  • Bootstrap当下最流行的前端UI框架(有预制界面组件)。
  • 组件简洁大方、代码规范精简、界面自定义性强。
  • Bootstrap是基于HTML5和CSS3开发的, js功能效果依赖于 jQuery( 第三方库, 后面讲解 )。
  • Bootstrap中包含了丰富的Web组件,根据这些组件,可以快速的搭建一个漂亮、功能完备的网站。

优点:

  • 有自己的生态圈,不断的更新迭代
  • 提供了一套简洁、直观、强悍的组件
  • 标准化的HTML+CSS编码规范
  • 让开发更简单,提高了开发效率。
  • 扩展性强,虽然界面组件样式已经定义好了,我们还可以自定义,修改默认样式。

版本:

  • 2.x.x 停止维护
    • 优点:兼容性好
    • 缺点:代码不够简洁、功能不够完善
  • 3.x.x 目前使用最多
    • 优点:稳定,偏向于开发响应式布局,移动设备优先的WEB项目
    • 缺点:放弃了IE67,对IE8支持但是界面效果不友好
  • 4.x.x 阶段

基本模板

<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1,user-scalable=0">
    <title>Bootstrap 101 Template</title>
    <link rel="stylesheet" href="lib/bootstrap/css/bootstrap.min.css">  
    <!-- [if lt IE 9]>
      <script src="lib/html5shiv/html5shiv.min.js"></script>
      <script src="lib/respond/respond.min.js"></script>
    <![endif] -->
  </head>
  <body>
    <h1>你好,世界!</h1>

    <script src="lib/jquery/jquery.min.js"></script>
    <script src="lib/bootstrap/css/bootstrap.min.css"></script>
  </body>
</html>

全局样式

container容器

Bootstrap 需要为页面内容和栅格系统包裹一个 .container 容器。默认带了15px的padding值。

.container 类用于固定宽度并支持响应式布局的容器。

<div class="container">
  ...
</div>

.container-fluid 类用于 100% 宽度,占据全部视口(viewport)的容器,流式布局容器。

<div class="container-fluid">
  ...
</div>

注意:这两种 容器类不能互相嵌套。

栅格系统

栅格系统,也叫网格系统

  • .row用于抵消.container容器的15px的padding值
  • 可以在.row中嵌套column

栅格系统常用类(总共12列)

类名 例子 解释
.col-xs-xx .col-xs-6 在超小屏幕(及以上)生效
.col-sm-xx .col-sm-6 在小屏幕(及以上)生效
.col-md-xx .col-md-6 在中屏幕(及以上)生效
.col-lg-xx .col-lg-3 在大屏幕及生效,占1/4
.col-lg-xx .col-lg-4 在大屏幕及生效,占1/3
.col-lg-xx .col-lg-6 在大屏幕及生效,占1/2
col-*-* 列 实例 col-md-4
第一参数
lg 大屏及以上
md 中屏及以上
sm 小屏及以上
xm 超小屏及以上
第二参数
bootstrap默认把一行分成12等分,第二参数表示在12等分中占其中的几份

【案例:响应式栅格系统】

<!--
需求:
  1. 在大屏时显示6个等分的列2
  2. 在中屏时显示4个等分的列3
  3. 在小屏时显示3个等分的列4
  4. 在超小屏时显示2个等分的列6
-->

列嵌套

【案例:列嵌套.html】

<div class="col-lg-4">
      <!--栅格系统无处不在,只要父盒子有宽度,就可以使用栅格系统-->
      <div class="row">
        <div class="col-lg-6"></div>
        <div class="col-lg-6"></div>
      </div>
    </div>

列偏移

【案例:列偏移.html】

<!-- 使用 .col-md-offset-* 类可以将列向右侧偏移。-->
<div class="row">
  <div class="col-lg-3"></div>
  <!--col-lg-offset-3:在大屏下,这个div将向右侧偏移3个单位-->
  <div class="col-lg-6 col-lg-offset-3"></div>
</div>

列排序

通过使用 .col-md-push-* (往后推) 和 .col-md-pull-*(往前拉) 类就可以很容易的改变列(column)的顺序。

<div class="row">
  <div class="col-md-9 col-md-push-3">.col-md-9 .col-md-push-3</div>
  <div class="col-md-3 col-md-pull-9">.col-md-3 .col-md-pull-9</div>
</div>

响应式工具

//1. 大屏显示
//2. 中屏不显示
//3. 小屏显示
//4. 超小屏不显示

推荐使用hidden相关的属性

LESS

Less简介

Less 是一门 CSS 预处理语言,它扩展了 CSS 语言,增加了变量、Mixin、函数等特性。

浏览器不直接识别less文件,浏览器只识别css文件,所以我们写了less文件之后,我们需要预先把less文件转换成css文件。

less sass

本质上,LESS 包含一套自定义的语法及一个解析器,用户根据这些语法定义自己的样式规则,这些规则最终会通过解析器,编译生成对应的 CSS 文件。LESS 并没有裁剪 CSS 原有的特性,更不是用来取代 CSS 的,而是在现有 CSS 语法的基础上,为 CSS 加入程序式语言的特性。

less仅仅是写css的另一种方式,写出来的less文件浏览器也不识别,所以啊,我们写完了less文件,还需要通过less解析器解析成css,最终浏览器引入的还是css文件。

学习网站:

官网http://lesscss.org/ 中文网http://lesscss.cn/

less的编译

如何把less文件变成css文件

安装easy less插件

和前面的内容需要使用 ,
"less.compile": {
  "out": "../css/"
}

Less语法

less初体验

新建一个less文件,输入以下代码:

@color:red;
p {
  color:@color;
}

变量

可以变化的量

注释

/*这个注释是CSS中的注释,因此会编译到css中*/
//这个注释,CSS中用不了,因此不会编译出来。

变量

@wjs_color:#e92322;
body {
  background-color: @wjs_color;
}

div {
  width: 400px;
  height: 400px;
  border: 1px solid @wjs_color;
}

嵌套

我们可以在一个选择器中嵌套另一个选择器来实现继承,这样很大程度减少了代码量,并且代码看起来更加的清晰。

  • 使用伪类的时候 可以使用& 表示父选择器
@charset "UTF-8";
.wjs_header {
  border-bottom: 1px solid #ccc;
}
.wjs_header .header_item {
  height: 40px;
  line-height: 40px;
  text-align: center;
  border-left: 1px solid #ccc;
}
.wjs_header .header_item:first-child {
  border-left: none;
}

less数学运算

在我们的 CSS 中充斥着大量的数值型的 value,less可以直接支持运算,也提供了一系列的函数提供给我们使用。

less函数的使用(了解)

函数:可以重复使用

不带参数的函数

@charset "UTF-8";

//不会被编译
.btn() {
  width: 200px;
  height: 200px;
  background-color: #ccc;
}
.my_btn {
  .btn();
}

带参数的函数

.btn_border(@width) {
  border: @width solid #000;
}
.my_btn {
  //如果函数定义了参数,调用的时候必须传入参数,否则会报错
  .btn_border();
  //传入参数,就不会报错
  .btn_border(10px);
}
.btn_border(@width:1px) {
  border: @width solid #000;
}
.my_btn {
  //因为有默认值,所以不会报错
  .btn_border();
  //传入参数,会覆盖1px,也不会报错
  .btn_border(10px);
}

使用less重新实现京东首页的头部

rem

rem是什么?

rem(font size of the root element)是指相对于根元素的字体大小的单位。它就是一个相对单位。rem是相对于HTML便签的文字大小,默认大小font-size:16px。

em(font size of the element)是指相对于当前元素的字体大小的单位。它也是一个相对单位。

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

注意:rem主要利用与移动端,由于兼容性问题

html{
  font-size:16px;
}
body {
  font-size:20px;
}
div.em {
  /*em的计算方式参照的当前元素的font-size,如果不设置,默认继承自父盒子*/
  width:2em;
  height:2em;
  background-color:red;
}
/*rem的计算方式参照的是html的font-size*/
div.rem {
  width:2rem;
  height:2rem;
  background-color:blue;
}

为什么要用rem?

rem的主要目的就是解决用于不同屏幕的适配问题。rem能够等比例的适配所有的屏幕。

由于市面上手机种类繁多,导致移动端的屏幕种类非常的混乱,比如有常见的320px 360px 375px 384px 480px 640px等。在开发中,美工一般只会提供750px或者是640px的设计稿,这就要求我们通过一张设计稿能够适配所有的屏幕。通常解决方案如下:

  • 流式布局:虽然可以让各种屏幕都适配,但是显示效果不是非常的友好,因为只有几个尺寸的手机能够完美的显示出来视觉设计师和交互最想要的效果。但是目前使用流式布局的公司非常多,比如 亚马逊京东携程
  • 响应式布局:响应式这种方式在国内很少有大型企业的复杂性的网站在移动端用这种方法去做,主要原因是工作大,维护性难 。所以一般都是中小型的门户或者博客类站点会采用响应式的方法从PC端页面到移动端页面以及web app直接一步到位,因为这样反而可以节约成本。
  • rem布局:rem能够适配所有的屏幕,与less配合使用效果会更好。目前使用rem布局的有:淘宝苏宁

##rem带来的宽高度自适应

不同屏幕下对应不同的HTML下的font-size值

rem与响应式

因为rem的基准点是根元素html的字体大小,因此我们只需要设置不同屏幕的html的font-size大小不一样就可以达到不同屏幕的适配了。

rem与媒体查询

媒体查询:根据不同的屏幕运行不同的CSS

@media screen and(条件)and (条件) {
    当条件满足执行代码
}
条件:
1、min-width:320px; 最小宽度320px以上
2、max-width:640px; 最大宽度640px以下
3、width:540px; 	   宽度等于540px;
注意:and前后必须有空格

使用rem配合媒体查询可以适配多个终端

需求:750的设计图 里面得到的盒子的大小为100px 100px 改写成rem 可以实现在主流手机里面宽高自适应 
主流手机机型:320 360 375 384 400 414 424 480 540 720 750

px转换成rem的公式: px/html的font-size值 
动态计算不同屏幕对应的html的font-size值公式:  当前屏幕/设计图的宽 / 基于这个设计图的html的fontsize

HyBirdApp界面开发

虽然混合应用开发的界面部分就跟移动端网页开发基本一样,但如果直接把移动端网页原封不动的丢到混合应用中运行,显示效果肯定要打折扣,在一些细节上显示的会不够细腻,主要原因有两点:

  1. 前端在适配屏幕时处理不当,导致布局走样或者间距不合适,从而影响显示效果;
  2. 网页渲染对硬件适配能力存在不足,容易出现模糊现象,导致界面不精细。

总结起来,我们需要集中解决这两个问题,即页面适配和精细还原设计稿。

页面适配

移动端页面适配是前端开发领域的老问题了。随着系统和设备的更新迭代,目前只要在页面头部设置 viewport 适配代码,再配合 flex 弹性布局,基本上适配大部分的页面。

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

但上述方式只能实现相对“粗略”的适配,即便设置了 viewport,不同手机间的像素差异仍然很大。市面上常见尺寸中,宽度最小的手机只有 320px,最大的 iPhone 8 Plus 却达到了 414px,这种情况下想用 px 实现精细布局已不太可能。我们需要一种可以随屏幕宽度变化而变化的相对单位,才能做到真正的适配。目前,rem 方案的可靠性和兼容性已经得到业内的广泛认可,这里我们也推荐一种非常简单的基于 rem 的适配方案。

但上述方式只能实现相对“粗略”的适配,即便设置了 viewport,不同手机间的像素仍然存在差异。市面上常见尺寸中,宽度最小的手机只有 320px,最大的 iPhone 8 Plus 却达到了 414px,这种情况下想用 px 实现精细布局已不太可能。我们需要一种可以随屏幕宽度变化而变化的相对单位,才能做到真正的适配。目前,rem 方案的可靠性和兼容性已经得到业内的广泛认可,这里也推荐一种非常简单的基于 rem 的适配方案。

适配原理是先假定我们的屏幕宽度为 640px,此时将根节点(html)字号设置为 10px,即 “1rem=10px”,进而得到屏幕总宽度等于 64rem。

html{font-size:10px;}

/* 此时屏幕宽度 = 64rem */

当以此标准实现的页面运行在其他设备上时,我们只要通过改变根节点的字号,使“屏幕总宽度=64rem”这个等式始终成立就可以了,之前的做法是使用 JavaScript 检测屏幕宽度,然后计算出 rem 的值。

var html=document.documentElement;
var rootSize = html.clientWidth / 640 * 10;
html.style.fontSize=rootSize+'px' 

得益于规范的推广和手机系统的更新,如今我们用 CSS 也能实现相同效果,因为新规范中有一个 vw 单位,能够以屏幕宽度为单位1,实现任意百分比例的取值,即:

屏幕宽度=100vw

关联我们需要实现的等式屏幕宽度 = 64rem,可以得到:/

100vw = 64rem

进而得到:

1rem = 1.5625vw

实际上这样就实现了屏幕总宽度恒等于 64 rem,然后就可以愉快的使用 rem 单位做可以适配任何屏幕的精确布局了。

以上是理论,实际上这里会产生一个 Bug。由于多数屏幕的宽度都小于 640px,计算出来的 rem 也会小于 10px,但 WebKit 内核会强制将最小字号锁定在 12px,这将直接导致我们的适配等式无法成立,从而在应用中出现较大的偏差,所以实际开发中我们要将根节点(html)字号矫正为 15.625vw ,适配等式就变成了“屏幕总宽度=6.4rem”,那么“1rem=100px”,可以绕过 WebKit 的限制,同时开发中的换算压力也不大。

说了这么多,真正需要写的代码只有一行:

html { font-size: 15.625vw;}

此时在 640px 宽度的页面中,1rem=100px,且无论在任何尺寸的手机上都会保持这个比例,简单的应用示例如下:

<div style="width: 3.2rem;height:3.2rem;background:hotpink;">
  在任何手机屏幕上都显示为屏幕宽度50%的正方形
</div>

前端基于这套适配方案开发,需要将设计稿宽度约定为 640px,当在设计稿上量取20px时,代码中只要除以100,就可以很简单的换算得到 0.2rem。

如果设计稿宽度不是 640px(设计稿尺寸往往大于640px),也没有关系,这时可以有两种做法,一是根据实际设计稿尺寸修改根字号的值,但可能出现在算根字号的时候除不尽,勉强四舍五入的话,就会产生适配偏差,不推荐这么做;另一种做法就简单了,直接把设计稿的宽度修改为640px,也是推荐大伙使用的方法。

设计稿还原

提升网页的精细程度可以从两方面入手,一是使用技术手段排除显示层面的模糊现象,二是用心还原设计意图。

显示模糊-图片模糊

常见的显示模糊有两种情况,一是图片模糊,二是边框模糊,有经验的前端开发者应该对这两个问题都不陌生。

图片模糊的原因是手机屏幕的可测量尺寸与物理像素尺寸不一致,通常 Web 前端会习惯性的将图片尺寸切成可测量尺寸,而图片显示最清晰的状态应该是图片尺寸与显示屏的物理像素尺寸一致的时候

以iPhone8的屏幕为例,添加 viewport 适配代码以后,屏幕的可测量宽度为 375px,但这块屏幕的物理像素宽度却是 750px,说明这块屏幕的像素比(DPR)是2,也就是说显示的时候会用2个物理像素去模拟一个像素,来提高屏幕的显示精度。

img

image-20190323014602888

如果在这块屏幕上显示图片,理论上一张宽度375px的图片已经可以自动全屏了,但由于图片的像素数过低,包含的信息量不够分配给每一个物理像素,显示的时候就会通过插值算法生成更多的像素,去分配给物理像素显示,这必定会导致图片的显示锐度下降。而如果图片本身宽度就是 750px 的话,所包含的像素信息就正好能够分配给每一个物理像素,此时便可在这块屏幕上呈现最佳的显示效果。

也不是图片只要够大就没问题,图片尺寸大了将直接影响加载速度和内存占用,所以还要根据实际情况做取舍。如果是 App 的界面素材,通常会随 Hybrid App 打包进本地,这时不需要考虑加载速度,可以适当增大图片尺寸,目前主流机型的屏幕宽度最大就是 1080px,切图时可以参考这个值取适当大小的切片。而如果是业务中的远程图片,考虑到加载速度,单张图片大小不宜过大,建议控制在 50k 以内,如果后端能自动压缩图片最好,否则就只能控制图片的尺寸了。

个别情况也可以例外,例如产品详细页,通常只有几张产品大图,并发不会太多,而且通常会做成切换显示效果,第一时间只会显示第一张图片,这些因素就为图片加载创造了很好的条件。因此为了保证显示效果,将产品图做大一点也没有关系。

但如果是带缩略图的产品列表页,就一定要严格控制缩略图尺寸了,原因有两点,产品列表首屏显示6-10个产品很正常,这就是6-10个图片并发,图片加载慢的话很容易让加载时间超过1s,影响用户体验。另外产品列表通常会做成滚动加载,随着用户浏览加载的图片越来越多,手机的内存占用也会急剧上升,App的运行会更耗电。

总而言之,本地图片尽量做大,远程图片根据需求和场景做适当取舍,不能只为了显示清晰而丢了加载速度。

两倍图

由于手机端的像素密度要比PC端高,很多手机的像素密度是电脑的2倍甚至3倍,所以为了在手机上显示的图片更加清晰,设计师给的图片都是2倍图甚至3倍图

问题:** 如何使用2倍图片的精灵图或者3倍图片的精灵图呢

以2倍图为例:
1. 利用PS将精灵图缩小一倍,去量取对应的宽高和位置坐标
2. 利用background-size去缩放精灵图(缩放至原始图片的1/2)

 background-image: url('images/gyt.jpg');
            background-size: 300px 100px;
重点注意: 引用的图片还是原来的2倍图 

利用ps缩放图片:
1. 将图片选项卡拖拽出来或者选择菜单栏
2. 图像 - 图像大小 - 将宽度缩放至1/2即可 只需要缩放一个就行 默认会保证等比例 

显示模糊-边框问题

边框模糊也就是经典的 1px 边框问题,其产生的原因,从本质上来讲,跟图片模糊的原因一样。用 CSS 画出的 1px 只是可测量尺寸上的 1像素,不能保证就是物理层面上的1像素。在视网膜屏成为标配的今天,CSS 画的 1px 边框基本上都会被呈现为物理像素 2px 或 3px,到了界面上就会显得不精细,跟原生显示的真正1像素有明显差异。

img

1px 问题的解法有很多,其中利用 transform 所实现的方法应该是最方便的解法了,结合为元素和媒体查询。代码如下所示:

.border-bottom{border-bottom:1px solid #ccc;}

@media screen and (-webkit-min-device-pixel-ratio: 2) { 
  .border-bottom{position:relative;border:0;}
  .border-bottom:before{
    position: absolute;
    right: 0;
    bottom: 0;
    left: 0;
    height: 1px;
    content: '';
    transform: scaleY(.5);
    background-color: #ccc;
  }
}

这样显示出来的是真正的1像素边框,看上去非常锐利,显得界面更精致。

还原设计

还原设计这个点其实没有太多可说的,作为前端开发应该对设计稿进行还原。但在PC 时代还原设计还好说,毕竟直接量设计稿就可以达到像素级别的精度,但在混合应用开发中,压根就不存在什么像素级还原。因为最终的界面要跑在各种不同尺寸的屏幕上,这个界面是没有标准答案的,我们前端能做的只能是在所有屏幕上都尽可能的还原“设计意图”,不至于让界面看上去跟设计稿不是一回事。

这里简单提一下比较容易出问题的两个点。

首先是字号设置。我们使用的 rem 适配方案,理论上只要所有单位都用 rem 实现,是可以将设计稿完美适配到所有屏幕的,但文字是界面上比较特殊的一类元素,它们的适配逻辑并不应该简单的仿效布局适配。对于阅读性文字理应设置成一个最适合阅读的固定尺寸(px),大屏就显示的多一些,小屏就显示的少一些,而不是随着屏幕宽度增加而等比增大字号;修饰性文字则完全可以使用 em 单位做相对缩放,这样从逻辑上更能体现其与父元素之间的关系,而不是强调其与屏幕宽度之间的关系,这一点当手机横屏显示时差异非常大,使用 rem 单位的文字在横屏下会大的离谱,甚至会直接导致布局失效。

img

所以我们通常还是会用 px 或者 em 单位进行字号设置。但这样做也存在问题,就是只要稍微设置不当,就显得文字与周围布局不协调,从而破坏设计意图。这时候可以反复调整字号大小,并对比观察界面和设计稿,直到它们看上去感觉一样为止。

/*阅读类文本使用固定像素*/
.p{font-size:14px;}

/*标题类文本使用相对字号*/
.pro_title{font-size:1.2em;}
.channel_title{font-size:1.8em;}

除了字号以外,有些间距设置有时也不应该使用 rem 单位,究其根本还是因为它们从内在逻辑上就跟屏幕宽度没关系,比如说下图文字列表的 padding:

这个间距从设计意图上说,是列表项文字的“呼吸空间”,它的大小应该只跟文字大小有关系,凡是这种地方,都没有办法“像素级”还原设计稿,我们只能用心调试,去忠实的还原设计意图。其中em是相对单位,相对于父元素的字体大小。

/*使用em单位设置文字间距*/
.item{...;padding: 1.2em;}

总结下来,凡是跟布局无关的地方,其实都不太适合用 rem 单位,这些地方都需要我们认真对待,避免失真,只有所有细节都做好了,才能整体呈现出较高的还原度。

总结

​ 在混合应用的界面开发中,在处理好了页面适配之后,尽可能精细的还原设计稿,对于图片和线段的显示模糊知道如何解决,不同于PC网页,移动端设计稿在还原时因为屏幕尺寸不一,无法做到像素级别还原,这时就需要根据设计意图进行还原。