移动端开发

以处理Webkit内核浏览器为主,百分比布局,flex布局,rem+less+媒体查询,Bootstrap+媒体查询

1. 基础认知

1.1. 视口

视口就是浏览器显示页面内容的屏幕区域。视口可以分为布局视口,视觉视口和理想视口

1.1.1. 布局视口 layout viewport

  • 一般移动设备的浏览器都默认设置了一个布局视口,用于解决早期的PC端页面在手机上显示的问题。
  • IOS,Android基本都将这个视口分辨率设置为 980px,所以PC上的网页大多都能在手机上呈现,只不过元素看上去很小,一般默认可以通过手机缩放网页

1.1.2. 视觉视口 visual viewport

  • 用户正在看的网站的区域。
  • 可以通过缩放去操作视觉视口,但不影响布局视口,布局视口仍保持原来的宽度。

1.1.3. 理想视口 ideal viewport

  • 使网站在移动端有最理想的浏览和阅读宽度
  • 理想视口,对设备来讲,是最理想的视口尺寸
  • 需要手动添加meta视口标签通知浏览器操作
  • meta视口标签的主要目的:布局视口的宽度应该与理想视口的宽度一致,简单理解就是设备有多宽,布局的视口就多宽

1.2. meta视口标签

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

属性

属性 描述
width 宽度设置的是viewport宽度,可以设置device-width特殊值
initial-scale 初始缩放比,大于0的数字
maximum-scale 最大缩放比,大于0的数字
minimum-scale 最小缩放比,大于0的数字
user-scalable 用户是否可以缩放,yes/no(1/0)

1.3. 物理像素

  • 指屏幕显示的最小颗粒,是屋里真是存在的。是厂商在出厂时就设置好的,比如苹果6/7/8是750*1334
  • PC端开发的1px等于一个物理像素
  • 移动端开发的1px不等于一个物理像素
  • 一个px能显示的物理像素点的个数,称为物理像素比或屏幕像素比
  • Retina视网膜屏幕显示技术的出现,将更多的物理像素点压缩至一块屏幕里,从而达到更高的分辨率,并提高屏幕显示的细腻度
设备 尺寸(英寸) 开发尺寸px 物理像素比dpr
iphone3G 3.5 320*480 1.0
iphone4/4s 3.5 320*480 2.0
iphone5/5s/5c 4.0 320*568 2.0
HTC One M8 4.5 360*640 3.0
iphone6 4.7 375*667 2.0
Nexus 4 4.7 384*640 2.0
Nexus 5x 5.2 411*731 2.6
iphone6 Plus 5.5 414*736 3.0
Samsung Galaxy Note 4 5.7 480*853 3.0
Sony Xperia Z Ultra 6.4 540*960 3.0

1.4. 二倍图

  • 对于一张50pxx50px的图片,在手机Retina屏中打开,按照移动端物理像素比会放大倍数,会造成图片模糊
  • 采取放一个100x00的图片,手动将图片缩小为50x50
1
<img src="img100.jpg" style="width:50px;height:50px;">

切图工具 http://www.cutterman.cn/zh/cutterman

1.5. 移动端开发选择

  • 单独移动端页面(主流)

    网址域名前面加m(mobile)可以打开移动端,通过判断设备,跳转至移动端页面

  • 响应式页面兼容移动端(其次)

    判断屏幕宽度来改变样式,以适应不同终端

    需要花很大精力去调兼容性问题

单独制作移动端页面 响应式页面兼容移动端
京东商城手机版 三星手机官网
淘宝触屏版
苏宁易购手机版

总结 目前市场主流的选择还是单独制作移动端页面

1.6. 移动端技术解决方案

  • 移动端浏览器基本以webkit内核为主,因此就考虑webkit兼容性问题。
  • 可以放心使用h5和css3样式
  • 同时浏览器的私有前缀只需要考虑添加webkit即可

1.7. CSS初始化 normalize.css

优点:

  • 保护了有价值的默认值
  • 修复了浏览器的bug
  • 模块化
  • 拥有详细的文档

http://necolas.github.io/normalize.css/

1.8. 特殊样式

1
2
3
4
5
6
/* 清除点击高亮 */
-webkit-tap-highlight-color: transparent;
/* ios上使按钮和输入框可以自定义样式 */
-webkit-appearance: none;
/* 禁用长按页面时弹出菜单 */
-webkit-touch-callout: none;

1.9. 移动端技术选型

单独制作移动端页面(主流) 响应式页面兼容移动端(其次)
流式布局(百分比布局) 媒体查询
flex弹性布局 bootstarp
less+rem+媒体查询布局
混合布局

2. 流式布局(百分比布局)

  • 通过盒子的宽度设置成比分比来根据屏幕的宽度来进行伸缩,不受固定像素的限制,内容向两边填充
  • 流式布局方式是移动web开发使用的比较常见的布局方式
  • max-width 最大宽度,max-height最大高度
  • min-width 最小宽度,min-height最小高度
1
2
3
4
5
6
section div{
width: 50%;
height: 400px;
max-width: 980px;
min-width: 320px;
}

2.1. 京东商城

https://m.jd.com/

3. flex布局

3.1. 传统布局 vs flex布局

传统布局 flex弹性布局
兼容性好 操作方便,布局极为简单,移动端应用广泛
布局繁琐 pc端浏览器支持情况较差
局限性,不能在移动端很好的布局 IE 11或更低版本,不支持或仅部分支持

建议:

  1. 如果是PC端页面布局,还是传统布局
  2. 如果是移动端或者不考虑兼容性问题的PC端页面布局,使用flex弹性布局

3.2. 原理

flex是flexible Box的缩写,意为”弹性布局“,用来为盒状模型提供最大的灵活性,任何一个容器都可以指定为flex布局

  • 当我们为父盒子设为flex布局以后,子元素的float,clear,vertical-algin属性将失效
  • 伸缩布局=弹性布局=伸缩盒布局=弹性布局=flex布局
  • 采用flex布局的元素,称为flex容器,它的所有子元素自动称为容器成员,称为flex项目(item),简称项目
  • 体验中div就是flex父容器
  • 体验中span就是子容器flex项目
  • 子容器可以横向排列也可以纵向排列

总结:通过给父盒子添加flex属性,来控制子盒子的位置和排列方式

3.3. 主轴方向 felx-direction

3.3.1. 主轴与侧轴

在flex布局中,是分为主轴和侧轴连个方向,同样的叫法有:行和列,x轴和y轴

  • 默认主轴方向就是x轴方向,水平向右
  • 默认侧轴方向就是y轴方向,水平向下

3.3.2. 属性值

属性决定主轴的方向

看flex-direction设置谁为主轴,剩下的就是侧轴。子元素跟着主轴来排列

属性值 说明
row 从左到右,默认
row-reverse 从右到左
column 从上到下
column-reverse 从下到上

3.4. 主轴上的子元素排列方式 justify-content

使用这个属性之前一定要确定好主轴

属性值 说明
flex-start 默认值,从头部开始,如果主轴是x轴,则从左到右
flex-end 从尾部开始排列
center 在主轴居中对齐
space-around 平分剩余空间
space-between 先两边贴边再平分剩余空间

3.5. 子元素是否换行 flex-wrap

默认情况下,项目都排在一条线上,flex布局中默认不换行

属性值 说明
nowrap 不换行
wrap 换行

3.6. 侧轴上的子元素排列方式(单行) align-items

控制子项在侧轴上的排列方式,子项为单项时使用

属性值 说明
flex-start 默认值,从上到下
flex-end 从下到上
center 挤在一起,垂直居中
stretch 拉伸,不能设置子盒子高度

3.7. 侧轴上的子元素的排列方式 (多行)align-content

设置子项在侧轴上的排列方式,并且只能用于子项出现换行的情况,单行下无效

属性值 说明
flex-start 默认值在侧轴的头部开始排列
flex-end 在侧轴的尾部开始排列
center 在侧轴中间显示
space-around 子项在侧轴平分剩余空间
space-between 子项在侧轴先分布在两头,再平分剩余空间
stretch 设置子项元素高度平分父元素高度

3.8. 复合属性 flex-flow

flex是flex-direction和flex-wrap属性的复合属性

1
flex-flow: row wrap;

3.9. 子项常见属性

3.9.1. flex属性

定义子项目分配剩余空间,用flex来表示占多少份数

1
2
3
4
.item{
/* 默认为0 */
flex: <number>;
}

3.9.1.1. 案例一

两边固定,中间占满

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
<style>
* {
margin: 0;
padding: 0;
}

section {
width: 80%;
height: 150px;
margin: 0 auto;
display: flex;
background-color: azure;
}

section div:nth-child(1) {
background-color: purple;
width: 100px;
height: 150px;
}

section div:nth-child(2) {
background-color: orange;
flex: 1;
}

section div:nth-child(3) {
background-color: red;
width: 100px;
height: 150px;
}
</style>

<section>
<div></div>
<div></div>
<div></div>
</section>

3.9.1.2. 案例二

三块自动分配

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
<style>
* {
margin: 0;
padding: 0;
}

section {
width: 80%;
height: 150px;
margin: 0 auto;
display: flex;
background-color: azure;
}

section div {
flex: 1;
}

section div:nth-child(1) {
background-color: purple;
}

section div:nth-child(2) {
background-color: orange;
}

section div:nth-child(3) {
background-color: red;
}
</style>

<section>
<div></div>
<div></div>
<div></div>
</section>

3.9.2. 控制子项自己在侧轴上的排列方式 align-self

align-self 允许单个项目有与其他项目不一样的对齐方式,可覆盖align-items属性。默认值为auto,表示继承父元素的align-items属性,如果没有父元素,则等同于使用stretch

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
<style>
* {
margin: 0;
padding: 0;
}

section {
width: 80%;
height: 150px;
margin: 0 auto;
display: flex;
background-color: azure;
align-items: flex-end;
}

section div {
width: 100px;
height: 100px;
}

section div:nth-child(1) {
background-color: purple;
}

section div:nth-child(2) {
background-color: orange;
align-self: stretch;
}

section div:nth-child(3) {
background-color: red;
}
</style>
<section>
<div></div>
<div></div>
<div></div>
</section>

3.9.3. 定义项目排列顺序order

数值越小,排列越靠前,默认为0

3.10. 应用

3.10.1. 携程

https://m.ctrip.cn/

3.10.2. 元素水平等分后垂直等分

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
<ul class="local-nav">
<li>
<a href="" title="景点·玩乐">
<span class="local-nav-icon1"></span>
<span>景点·玩乐</span>
</a>
</li>
<li>
<a href="" title="周边游">
<span class="local-nav-icon2"></span>
<span>周边游</span>
</a>
</li>
<li>
<a href="" title="美食林">
<span class="local-nav-icon3"></span>
<span>美食林</span>
</a>
</li>
<li>
<a href="" title="一日游">
<span class="local-nav-icon4"></span>
<span>一日游</span>
</a>
</li>
</ul>

css

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
43
44
45
46
/* 导航栏 */
.local-nav{
height: 64px;
margin: 3px;
border-radius: 8px;
display: flex;
justify-content: flex-end;
}

.local-nav li{
flex: 1;
}

.local-nav li:nth-child(-n+3){
margin-right: 4px;
}

.local-nav a{
margin-top: 8px;
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
align-items: center;

}
.local-nav a span{
font-size: 12px;
flex: 1;
}
.local-nav a span[class^="local-nav-icon"]{
width: 32px;
height: 32px;
background-size: 32px auto;
}
.local-nav-icon1{
background: url(../images/tabbar.png) 0 0;
}
.local-nav-icon2{
background: url(../images/tabbar.png) 0 -32px;
}
.local-nav-icon3{
background: url(../images/tabbar.png) 0 -64px;
}
.local-nav-icon4{
background: url(../images/tabbar.png) 0 -96px;

4. less+rem+媒体查询布局

4.1. em

em是父元素字体大小的倍数

1
2
3
4
5
6
7
8
div{
height: 14px;
}

div a{
/* 7px */
height: .5em;
}

4.2. rem基础

root em 是一个相对单位,rem的基准是相对于html的字体大小,可以通过修改html里面的文字来改变页面中元素大小,从而控制页面整体元素

1
2
3
4
5
6
7
8
9
10
html{
height: 14px;
}
div{
height: 10px;
}
div a{
/* 7px */
height: .5rem;
}

4.3. 媒体查询 @media

4.3.1. 介绍

Media Query是CSS3新语法。

  • 使用 @media 查询,可以针对不同的媒体类型定义不同的样式
  • 重置浏览器大小的过程中,页面也会根据浏览器的宽度和高度重新渲染页面
  • 目前针对很多苹果手机,安卓手机,平板等设备都用到媒体查询

4.3.2. 语法

1
2
3
@media mediatype and|not|only (media feature){
css-code;
}

4.3.2.1. 媒体类型 mediatype

说明
all 所有设备
print 打印机和打印预览
screen 电脑屏幕,平板电脑,智能手机等

4.3.2.2. 关键字 and|not|only

关键字 说明
and 多个媒体类型连接到一起,相当于且
not 排除某个媒体类型,相当于非
only 指定某个特定媒体类型

4.3.2.3. 媒体特性 media feature

说明
width 定义输出设备中页面可见区域的宽度
min-width 定义输出设备中页面最小可见区域宽度≥
max-width 定义输出设备中页面最大可见区域宽度≤
min-height 定义输出设备中页面最小可见区域高度≤
max-height 定义输出设备中页面最小可见区域高度≥

4.3.2.4. 实现

  1. 按照从大到小或者从小到发的思路
  2. 有最大值max-width和最小值min-width都是包含等于的
  3. 当屏幕小于540像素,背景颜色变为蓝色
  4. 当屏幕大于等于540像素并且小于等于969像素的时候背景颜色为绿色
  5. 当屏幕大于等于970像素的时候,背景颜色为红色
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
<style>
div{
width: 400px;
height: 400px;
margin: 0 auto;
}

@media screen and (max-width:539px){
div{
background-color: blue;
}
}
@media screen and (min-width:540px) {
div{
background-color: green;
}
}
@media screen and (min-width:970px) {
div{
background-color: red;
}
}
</style>

<div></div>

实现两个div,320px≤宽度≤640px时,两行显示;宽度≥640px时,一行显示

1
2
3
<link rel="stylesheet" href="common.css">
<link rel="stylesheet" href="index320.css" media="screen and (min-width: 320px)">
<link rel="stylesheet" href="index640.css" media="screen and (min-width: 640px)">

ommon.css

1
2
3
4
5
6
7
*{
margin: 0;
padding: 0;
}
div{
box-sizing: border-box;
}

index320.css

1
2
3
4
5
div{
width: 100%;
height: 44px;
border: 1px solid blue;
}

index640.css

1
2
3
4
5
6
div{
float: left;
width: 50%;
height: 44px;
border: 1px solid blue;
}

4.4. Less

Leaner Style Sheets

CSS扩展语言,CSS预处理器。

它在CSSDE语法基础之上,引入了变量,Mixin,运算以及函数登功能,大大简化了CSS的编写,并且降低了CSS的维护成本。

http://lesscss.cn/

常见的CSS预处理器:Sass,Less,Stylus

本质上,Less包含一套自定义的语法及一个解析器,用户根据这些语法定义自己的样式规则,这些规则最终会通过解析器,编译生成对应的CSS 文件。因此,可以把less 文件编译成css文件。

4.4.1. 安装less

  1. 下载node

    https://nodejs.org/en/

  2. 安装less

    1
    $ npm install -g less
  3. 检查是否安装

    1
    $ lessc -v
  4. vscode安装Easy LESS插件

  5. vscode中新建xx.less

    1
    2
    3
    4
    @color: #333;
    div{
    background-color: @color;
    }
  6. 保存后文件夹下自动出现对应xx.css

    1
    2
    3
    div {
    background-color: #333;
    }

4.4.2. Less基础

4.4.2.1. 变量

1
@变量值: 值;

命名规范:

  1. 必须有@为前缀
  2. 不能包含特殊字符
  3. 不能以数字开头
  4. 大小写敏感

4.4.2.2. 嵌套

  1. 子元素直接写在父元素内

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    #header .logo{
    width: 300px;
    }

    /* less写法 */
    #header{
    .logo{
    width: 300px;
    }
    }
  2. 如果遇到 交集|伪类|伪元素选择器

    • 内层选择器的前面没有&符号,则它被解析为附息债券的后代
    • 如果有&符号,它就被解析为父元素自身或父元素的伪类
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    /* less */
    div{
    background-color: @color;
    &:hover{
    font-size: 12px;
    }
    }

    /* css */
    div {
    background-color: #333;
    }
    div:hover {
    font-size: 12px;
    }

4.4.2.3. 运算

任何数字,颜色或者变量都可以参与运算,less提供给了+-*/运算

  • 运算符中间左右有个空格隔开
  • 对于两个不同的单位的值之间的运算,运算结果的值取第一个值的单位
  • 如果两个值之间只有一个值有单位,则运算结果就取该单位
1
2
3
4
@size 15px + 5
div{
font-size: @size;
}

less除法运算失效

less4.0版本后,除法运算符如果在括号外面就不执行除法运算,只有在括号内才能看做是除法运算。使用 ./ 也可进行强制除法运算。

解决

1
2
3
4
5
6
7
8
9
@size: (82rem / 5px);
div{
width: @size;
}

//======css========
div {
width: 16.4rem;
}

4.5. rem适配方案

  1. 让一些不能等比例自适应的元素,达到当设备尺寸发生改变的时候,等比例适配当前设备
  2. 使用媒体查询根据不同设备按比例设置html的字体大小,然后页面元素使用rem做尺寸单位,当html字体大小变化元素尺寸也会发生变化,从而达到等比缩放的适配

4.5.1. 适配方案

  1. 按照设计稿与设备宽度的比例,动态计算(媒体查询)并设置html根标签的font-size大小
  2. css中,设计稿元素的宽,高,相对位置等取值,按照同等比例换算为rem单位的值

4.5.2. 技术使用

技术方案1 技术方案2(推荐)
less flexible.js
媒体查询 rem
rem

4.5.3. 设计稿常见尺寸宽度

设备 宽度
iphone 4/5 640px
iphone 6/7/8 750px
常见320px,360px,384px,400px,414px,500px,720px,大部分4.7~5寸的安卓设备为720px

一般情况下,以一套或两套效果适应大部分的屏幕,放弃极端屏,牺牲一些效果现在基本以750为准

4.5.4. 动态设置html标签font-size大小

  1. 假设设计稿是750px
  2. 假设把整个屏幕划分为15等价,划分标准不一,可以是20份也可以是10等分
  3. 每一份作为html字体大小,就是15px
  4. 那么在320px设备的时候,字体大小为320/15=21.33px
  5. 用页面的大小除以不同的html字体大小会发现他们比例还是相同的
  6. 以750为标准设计稿
  7. 一个100x100像素的页面元素在750屏幕下,就是100/50转换为rem是2remx2rem比例是1:1
  8. 320屏幕下,html字体大小为21.33,则2rem=42.66,此时宽和高都是42.66,但是宽和高的比例还是1:1
  9. 但是已经能实现不同屏幕下,页面元素盒子等比例缩放的效果

4.5.5. 元素大小取值

  1. 页面元素的rem值=页面元素值 /(屏幕宽度/划分的份数)
  2. 屏幕宽度/划分的份数就是html的font-size大小
  3. 或者:页面元素的rem值=页面元素值/html的font-size大小

4.5.6. flexible.js

手机淘宝团队出的间接高效移动端适配库

不再需要写不同屏幕的媒体查询,js已处理

它的原理是把当前设备划分为10等份,不同设备下,比例还是一致的

因此只需要确定好当前设备的html文字大小

比如:设计稿是750px,只需要确定html文字大小为 750/10=75px

rem值=页面元素px值/75

剩余的就交给flexible.js来算

https://github.com/amfe/lib-flexible

修改默认字体大小

1
2
3
4
5
@media screen and (min-width:750px){
html{
font-size: 75px!important;
}
}

4.5.7. vscode安装插件cssrem

cssrem可以自动转换px为rem

修改其默认font-size: 16px

打开设置,在搜索设置中直接输入cssroot,把16更改为自己想要的默认HTML字体大小

效果

4.6. 苏宁易购

4.6.1. 技术选型

  • 单独制作移动页面方案
  • 布局采取rem适配布局(less+rem+媒体查询)
  • 采用750px设计尺寸

4.6.2. 设置公共common.less文件

  1. 设置常见屏幕尺寸,利用媒体查询设置不同的html字体大小
  2. 尺寸有320px,360px,375px,384px,400px,414px,424px,480px,540px,720px,750px
  3. 划分为15等分
  4. 默认html字体大小为50px,这句话写在最上面

4.6.3. 新建index.less

  • 用于写首页的样式

  • 引入common.less到index.less

    1
    @import "common";
  • 自动生成的index.css中自动加入了common.css的代码

  • 首页index.html中引入index.css

    1
    <link rel="stylesheet" href="css/index.css">

4.6.4. body width

1
2
3
body{
width: 15rem;
}

设计图为750px,分15份,html的font-size为50px,则width=750/50=15rem

5. 响应式开发

5.1. 原理

设备划分 尺寸区间
超小屏幕(手机) <786px
小屏设备(平板) ≥768px~992px
中等屏幕(桌面显示器) ≥992px~<1200px
宽屏设备(大桌面显示器) ≥1200px

5.2. 布局容器

需要一个父级作为布局容器,来配合子级元素来实现变化效果。

在不同屏幕下,通过媒体查询来改变这个布局容器的大小,再改变里面子元素的排列方式和大小,从而实现不同屏幕下,看到不同的页面布局和样式变化。

5.3. 尺寸划分

  • 超小屏幕(手机,<768px):设置宽度为100%
  • 小屏幕(平板,≥768px):设置宽度为750px
  • 中等屏幕(桌面显示器,≥992px):设置宽度为970px
  • 大屏幕(大桌面显示器,≥1200x):设置宽度为1170px
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/* 超小屏幕(手机,<768px):设置宽度为100% */
@media screen and (max-width:767px) {
.container{
width: 100%;
}
}
/* 小屏幕(平板,≥768px):设置宽度为750px */
@media screen and (min-width:768px) {
.container{
width: 750px;
}
}
/* 中等屏幕(桌面显示器,≥992px):设置宽度为970px */
@media screen and (min-width:992px) {
.container{
width: 970px;
}
}
/* 大屏幕(大桌面显示器,≥1200x):设置宽度为1170px */
@media screen and (min-width:1200px) {
.container{
width: 1170px;
}
}

5.4. 案例

  1. 屏幕≥768px时,布局容器container宽度为750px
  2. container里面包含8个li盒子,每个盒子的宽度为93.75(750/8)px
  3. 屏幕缩放,宽度<768px时,宽度修改为100%
  4. 此时8个li盒子宽度修改为33.33%

index.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 lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="index.css">
</head>
<body>
<div class="container">
<ul>
<li>1</li>
<li>1</li>
<li>1</li>
<li>1</li>
<li>1</li>
<li>1</li>
<li>1</li>
<li>1</li>
</ul>
</div>
</body>
</html>

index.css

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
ul{
list-style: none;
}
.container{
height: 44px;
background-color: aqua;
margin: 0 auto;
}

.container ul li{
float: left;
width: 12.5%;
height: 30px;
border: 1px solid purple;
}
/* 超小屏幕(手机,<768px):设置宽度为100% */
@media screen and (max-width:767px) {
.container{
width: 100%;
}
.container ul li{
width: 33.33%;
}
}
/* 小屏幕(平板,≥768px):设置宽度为750px */
@media screen and (min-width:768px) {
.container{
width: 750px;
}
}
/* 中等屏幕(桌面显示器,≥992px):设置宽度为970px */
@media screen and (min-width:992px) {
.container{
width: 970px;
}
}
/* 大屏幕(大桌面显示器,≥1200x):设置宽度为1170px */
@media screen and (min-width:1200px) {
.container{
width: 1170px;
}
}

5.5. Bootstrap

5.5.1. 简介

来自Twitter,是目前最受欢迎的前端框架,Bootstrap是基于html,css,JavaScript的,简洁灵活,使得web开发更加快捷

优点:

  • 标准化的html+css编码规范
  • 提供了一套简洁,直观,强悍的组件
  • 有自己的生态圈,不断的更新迭代
  • 让开发更简单,提高了开发的效率

5.5.2. 版本

  • 2.x.x:停止维护,兼容性好,代码不够简洁,功能不够完善
  • 3.x.x:目前使用最多,稳定但是放弃了IE6-IE7。对IE8支持,但是界面效果不好,偏向于用于开发响应式布局,移动设备优先的web项目
  • 4.x.x:最新版,目前不流行

5.5.3. <meta>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<!-- 要求当前网页使用IE浏览器最高版本的内核来渲染 -->
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">

<!--
width=device-width 显示窗口宽度等于设备宽度
initial-scale=1.0 窗口默认不缩放
user-scalable=no 用户不可缩放
maximum-scale=1.0 最大缩放值
-->
<meta name="viewport" content="width=device-width,initial-scale=1.0,user-scalable=no,maximum-scale=1.0">

<!--[if lt IE 9]>
<!-- 解决IE9以下浏览器对html5新增标签的不识别,并导致css不起作用的问题 -->
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
<!-- 解决IE9以下浏览器对css3Media Query的不识别 -->
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
<![endif]-->

5.5.4. 布局容器

Bootstrap 需要为页面内容和栅格系统包裹一个 .container 容器

注意,由于 padding 等属性的原因,这两种容器类不能互相嵌套

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

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

container类 container-fluid类
超小屏(<768px):设置宽度为auto 流式布局容器,auto
小屏(≥768px):设置宽度为750px 占据全部视口(viewport)的容器
中屏(≥992px):设置宽度为970px 适合于单独做移动端开发
大屏(≥1200x):设置宽度为1170px

5.5.5. 栅格系统

Bootstrap 提供了一套响应式、移动设备优先的流式栅格系统,随着屏幕或视口(viewport)尺寸的增加,系统会自动分为最多12列

栅格系统用于通过一系列的行(row)与列(column)的组合来创建页面布局,内容就可以放入这些创建好的布局中

5.5.5.1. 栅格参数

通过下表可以详细查看 Bootstrap 的栅格系统是如何在多种屏幕设备上工作的。

超小屏幕 手机 (<768px) 小屏幕 平板 (≥768px) 中等屏幕 桌面显示器 (≥992px) 大屏幕 大桌面显示器 (≥1200px)
栅格系统行为 总是水平排列 开始是堆叠在一起的,当大于这些阈值时将变为水平排列 开始是堆叠在一起的,当大于这些阈值时将变为水平排列 开始是堆叠在一起的,当大于这些阈值时将变为水平排列
.container 最大宽度 None (自动) 750px 970px 1170px
类前缀 .col-xs- .col-sm- .col-md- .col-lg-
列(column)数 12 12 12 12
  • “行(row)”必须包含在 .container (固定宽度)中
  • 列的平均划分需要给列添加类前缀
  • xs-extra small:超小;sm-small:小;md-medium:中等;lg-large:大;
  • 列大于12,多余的列所在元素被作为一个整体另起一行排列
  • 每一列默认有左右15px的padding
  • 可以同时为一列指定多个设备的类名,以便划分不同份数,故可以为class=”col-md-4 col-sm-6”

5.5.5.2. 嵌套列

为了使用内置的栅格系统将内容再次嵌套,可以通过添加一个新的 .row 元素和一系列 .col-sm-* 元素到已经存在的 .col-sm-* 元素内。被嵌套的行(row)所包含的列(column)的个数不能超过12(其实,没有要求你必须占满12列)

嵌套中加入一个row就可以取消父元素的padding值而且高度自动和父级一样高

1
2
3
4
5
6
7
8
9
10
11
12
13
<div class="row">
<div class="col-sm-9">
Level 1: .col-sm-9
<div class="row">
<div class="col-xs-8 col-sm-6">
Level 2: .col-xs-8 .col-sm-6
</div>
<div class="col-xs-4 col-sm-6">
Level 2: .col-xs-4 .col-sm-6
</div>
</div>
</div>
</div>

5.5.5.3. 列偏移

使用 .col-md-offset-* 类可以将列向右侧偏移。这些类实际是通过使用 * 选择器为当前元素增加了左侧的边距(margin)。例如,.col-md-offset-4 类将 .col-md-4 元素向右侧偏移了4个列(column)的宽度

5.5.5.4. 列排序

通过使用 .col-md-push-*.col-md-pull-* 类就可以很容易的改变列(column)的顺序

push-往右

pull-往左

1
2
3
4
<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>

5.5.5.5. 不同设备中隐藏或显示元素

.hidden-*

.visible-*

6. 触屏事件touch

触屏事件 说明
touchstart 手指触摸到一个DOM元素时触发
touchmove 手指在一个DOM元素上滑动时触发
touchend 手指从一个DOM元素上移开时触发

6.1. 触摸事件

触摸列表 说明
touches 正在触摸屏幕的所有手指的一个列表
targetTouches 正在触摸当前DOM元素上的手指的一个列表
changedTouches 手指状态发生了改变的列表,从无到有,从有到无变化

6.2. 移动端拖动元素

⚠️ Added non-passive event listener to a scroll-blocking 'touchstart' event. Consider marking event handler as 'passive' to make the page more responsive.

解决

div.addEventListener("监听的事件",function,{passive:false});

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
43
44
45
46
47
48
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
div{
width: 100px;
height: 100px;
background-color: pink;
}
</style>
</head>
<body>
<div></div>
<script>
var div = document.querySelector("div");
//手指原始坐标
var startX;
var startY;
//盒子原来的距离
var x;
var y;
div.addEventListener("touchstart",function(e){
console.log(e);
startX = e.targetTouches[0].pageX;
startY = e.targetTouches[0].pageY;

x = this.offsetWidth;
y = this.offsetHeight;

});
div.addEventListener("touchmove",function(e){
//阻止屏幕滚动默认行为
e.preventDefault();
//手指移动距离=手指移动之后的距离-手指初始坐标
var moveX = e.targetTouches[0].pageX - startX;
var moveY = e.targetTouches[0].pageY - startY;
//移动盒子 = 盒子原来的位置+手指移动的距离
this.style.left = x +moveX+'px';
this.style.top = y + moveY+'px';

});
</script>
</body>
</html>

7. 轮播图

7.1. 代码

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
<!-- 轮播图 -->
<div class="focus">
<ul>
<li>
<a href=""><img src="uploads/back4.jpg" alt=""></a>
</li>
<li>
<a href=""><img src="uploads/back1.jpg" alt=""></a>
</li>
<li>
<a href=""><img src="uploads/back2.jpg" alt=""></a>
</li>
<li>
<a href=""><img src="uploads/back3.png" alt=""></a>
</li>
<li>
<a href=""><img src="uploads/back4.jpg" alt=""></a>
</li>
<li>
<a href=""><img src="uploads/back1.jpg" alt=""></a>
</li>
</ul>
<ol>
<li class="active"></li>
<li></li>
<li></li>
<li></li>
</ol>

</div>

css

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
43
44
45
46
47
/* 轮播图 */

.focus {
position: relative;
width: 100%;
height: 129px;
max-width: 540px;
min-width: 320px;
overflow: hidden;
margin-top: 55px;
}

.focus ul {
margin-left: -100%;
width: 600%;
}


.focus li {
float: left;
width: 16.66%;
}

.focus li a img {
width: 100%;
height: 129px;
}

.focus ol{
position: absolute;
bottom: 5px;
right: 5px;
list-style: none;
}
.focus ol li{
float: left;
width: 10px;
height: 10px;
border-radius: 50%;
background-color: #fff;
margin: 0 5px;
transition: .2s;
}
.focus ol li.active{
width: 20px;
border-radius: 5px;
}

js

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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
window.addEventListener("load",function(){
var focus = document.querySelector(".focus");
var ul = focus.querySelector("ul");
var ol = focus.querySelector("ol");
var width = focus.offsetWidth;
var num = 0;
function move(){
num++;
ul.style.transition='all .5s';
ul.style.transform = 'translateX('+-num*width+'px)';

}
var timer = setInterval(move,2000);

//监听过渡事件
ul.addEventListener("transitionend",function(){
if(num==ul.children.length-2){
num=0;
ul.style.transition='none';
ul.style.transform = 'translateX(0px)';
}
else if(num<0){
num=ul.children.length-3;
ul.style.transition='none';
ul.style.transform = 'translateX('+-num*width+'px)';
}

//小圆点
//选出ol中所有带有active类的元素,去掉类名active
ol.querySelector(".active").classList.remove("active");
ol.children[num].classList.add("active");
});

//手指拖动
var startX = 0;
var flag = false;
ul.addEventListener("touchstart",function(e){
clearInterval(timer);
startX = e.targetTouches[0].pageX;
},{passive:false});
var moveX=0;
ul.addEventListener("touchmove",function(e){

moveX = e.targetTouches[0].pageX - startX;
//移动距离=盒子原来的距离+手指移动距离
var translatex = -num*width + moveX;
ul.style.transition='none';
ul.style.transform = 'translateX('+translatex+'px)';
flag = true;
e.preventDefault();
},{passive:false});
ul.addEventListener("touchend",function(e){
if(flag){
if(Math.abs(moveX)>100){
if(moveX>0){
num--;

}else{
num++;
}

}
ul.style.transition='all .5s';
ul.style.transform = 'translateX('+-num*width+'px)';
timer = setInterval(move,2000);
}

},{passive:false});
});

7.2. 移动端插件

7.2.1. swiper插件

https://www.swiper.com.cn/

7.2.2. superslide

http://www.superslide2.com/

7.2.3. iscroll

https://github.com/cubiq/iscroll

7.2.4. zy.media.js

zyMedia是掌阅科技开源的一款基于HTML5的、轻量级的、实现移动端全平台统一UI的多媒体播放器,该播放器已经在千万级设备上适配使用

https://github.com/ireaderlab/zyMedia

https://gitcode.net/mirrors/ireaderlab/zyMedia

8. click延时解决方案

移动端click事件会有300ms的延时,原因是移动端屏幕双击会缩放页面

  1. 禁止缩放

    <meta name="viewport" content="user-scalable=no">

  2. 利用touch事件自己封装解决

    • 当手指触摸屏幕,记录当前触摸时间

    • 手指离开屏幕,离开的时间减去触摸时间

    • 如果事件小于150ms,并且没有滑过屏幕,定义为点击

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      function tap(obj,callback){
      var isMove = false;
      var startTime = 0;
      obj.addEventListener("touchstart",function(e){
      //记录触摸时间
      startTime = Date.now();
      });
      obj.addEventListener("touchmove",function(e){
      //是否有滑动,有滑动算拖拽,不算点击
      isMove=true;
      });
      obj.addEventListener("touchend",function(e){
      //手指触摸和离开时间小于150ms算点击
      if(!isMove && (Date.now()-startTime<150)){
      callback&&callback();
      }
      //重置
      isMove=false;
      startTime=0;
      });
      }
      //调用
      tap(div,function(){});
  3. 插件 fastclick.js

    https://github.com/ftlabs/fastclick

    https://www.aliyundrive.com/s/XSQzVFYaCYu

    Include fastclick.js in your JavaScript bundle or add it to your HTML page like this:

    1
    <script type='application/javascript' src='/path/to/fastclick.js'></script>

    The script must be loaded prior to instantiating FastClick on any element of the page.

    To instantiate FastClick on the body, which is the recommended method of use:

    1
    2
    3
    4
    5
    if ('addEventListener' in document) {
    document.addEventListener('DOMContentLoaded', function() {
    FastClick.attach(document.body);
    }, false);
    }

    Or, if you’re using jQuery:

    1
    2
    3
    $(function() {
    FastClick.attach(document.body);
    });

9. 前端框架

Bootstrap,Vue,Angular,React等,既能开发PC端,也能开发移动端

本文结束  感谢您的阅读
  • 本文作者: Wang Ting
  • 本文链接: /zh-CN/2019/08/21/移动端开发/
  • 发布时间: 2019-08-21 08:48
  • 更新时间: 2023-04-15 16:16
  • 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!