App 分类
如上图,Native app
是使用原生开发的 app, 优点是性能更好,还能调用系统的 api ,但是发布 app 流程繁琐,而且不跨平台。
而Web app
, 优点是跨平台,修改方便,缺点是不能调用原生的 api, 而且用户体验不如原生 app, 好。
而Hybrid app
, 结合了上面两个的优点,可以说是很 nice。
尺寸相关概念
CSS 像素
又称为设备独立像素、逻辑像素。CSS中使用的一个抽象的概念,单位是 px
。
值是相对的,并不是绝对的,根据 dpr
来确定一个 CSS 像素代表几个物理像素,还有一些情况,例如用户缩放的时候,,dpr
也会跟着变为 2, 此时一个 CSS 像素代表两个物理像素。
注意: 电脑当中的一个设备像素一般是等于一个 CSS 像素。所以我们在 PS 当中的切图大小,一般也代表物理像素表示的大小。
设备像素
又称为物理像素,任何设备屏幕的物理像素的数量自出场开始就是固定不变的,单位是 pt
(点)。一个物理像素即屏幕上一个发光的点。物理像素单个点的大小由厂商决定,大小不固定。
屏幕尺寸
指的是屏幕对角线的长度,单位为英寸,注意英寸是长度单位,不是面积单位。1英寸(inch)=2.54厘米(cm)。
屏幕尺寸=屏幕斜边的像素/PPI。
像素密度 PPI
单位面积上(英寸)像素(设备像素)的数量。它是一个定值,是一个固定的参数。PPI=屏幕斜边的像素/屏幕尺寸。如下:
所以要提高 PPI的话,需要增加水平和竖直方向的像素点数量。因此,同一尺寸(inch)下,PPI提高了一倍,那像素会变为原来的4倍,也就是所 PPI 增加 N 倍,单位面积上的像素点的数量变为原来的 N^N 倍,如下图。查询不同设备的 ppi
PPI 的值越高,代表在一定尺寸的屏幕上像素数量越多,屏幕越清晰。如下同一张图片。
但同时,由于单位面积(英寸)并没有变,由于 PPI 的变大,对应的物理像素点会缩小。和上面的物理像素点的规律相反,PPI 增加 N 倍,单位面积上的像素点的大小将变为原来的 1 / N^N 倍。如下图:
同时对于一张图像,放到比当前 PPI 大的设备上时,也将按照上面的比例变小。例如一个放到一个 PPI 为自己的 2 倍的设备上时,图像将缩小四倍,如下图。
但是在实际当中我们更希望图片保持原有大小,并且最好是也不变模糊,保持原有的清晰度。对于上面的情况,解决方案是设备的 DPR 需要是原来设备的 2 倍,即使一个 CSS 像素需要代表的物理像素点需要变为原来的 2 倍,这就保持了图像的大小未发生改变,同时图片的分辨率也需要变为原来的两倍,这样就保持图像的清晰度未发生改变。
像素比 DPR
DPR=物理像素/css像素。获取:window.devicePixelRatio
。查询1。查询2
它的本质是指一个 CSS 像素代表几个 物理像素。它的意义是为了让图像能够早高清屏上显示。
其实上当像素比超过 2 后,肉眼是识别不出来的。
视口 ViewPort
PC 端的页面直接放到移动端的情况的话,因为移动端一般默认视口的大小为 980px,而一般移动端的 css 像素达不到那么大,所以默认会进行缩小, 使在移动端的页面整体被缩放,所有的东西看起来都很小,为了解决这个问题,需要正确设置 viewport
。移动端一般默认视口的大小为 980px,超出便会出现滚动条,或者直接进行缩放,看手机,我测试的时候, inphone6 是进行缩放, huaweip20 是出现滚动条。
如果要进行缩放,缩放比=物理像素(即设备像素)/ 视口宽度(html 的宽度,默认是 980px, 用document.documentElement.clientWidth
方法获取)。所以在移动端开发的时候,我们需要正确的设置 ViewPort的值,否者页面看上去会变得很小。这个缩放比没什么用,下面的缩放比可以用来设置 viewport 的宽度。
典型的 ViewPort 的设置值为下面这样:
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no">
-
width:
device-width
(设备的实际宽度--即设备的 css 像素)。 - user-scalable: 是否允许用户在设置或者默认的视口宽度上进行页面缩放,值为no或yes,代表不允许与允许。
- initial-scale: 页面初始缩放值,值为一个数字(可以带小数)。大于 1 表示放大。
- minimum-scale: 页面最小能够缩放的比例,值为一个数字(可以带小数)。
- maximum-scale: 页面最大能够缩放的比例,值为一个数字(可以带小数)。
需要注意的是,在移动端,如果不限制缩放,那么为了保证页面全部可见,会对页面整体进行缩放, 缩放的计算方式为: 缩放比(initial-scale)=css像素(设备css像素)/viewport宽度(html宽度)。
initial-scale = 1
,可以达到和 width=device-width
, 一样的效果。如果都设置了,取两者的最大值。
需要注意的是不管 viewport 设置为多少,只要超过 viewport 的宽度,就会进行缩放,比如就算将 width=device-width
设置上,如果不禁止缩放的话,超过 viewport 的宽度的时候,还是会进行缩放, 一般当我们都禁止缩放,如下:
minimum-scale=1,maximum-scale=1,user-scalable=no
当设置了正确的 viewport 和禁止了缩放之后,那么超过视口之后就会出现滚动条,而不会进行缩放。
还需要注意,上面两个缩放比是不一样得到,第一个是指如果 viewport 超过了设备的 css 像素的时候,viewport 如何进行缩放,而第二个是不管 viewport 为多少的时候,当超过 viewport 的时候,如何进行缩放。
一般根据上面的第二个公式,设置了正确的 viewport 后,我们可以通过设置缩放比,动态的设置 viewport 的宽度。
meta
标签
禁止识别电话与邮箱(但是邮箱没效果)
<meta name="format-detection" content="telephone=no,email=no" />
设置添加到主屏后的标题(ios)
<meta name="apple-mobile-web-app-title" content="标题">
添加到主屏幕后,全屏显示,删除苹果默认的工具栏和菜单栏(无用)
<meta name="apple-mobile-web-app-capable" content="yes" />
放在桌面上的logo
<link rel="apple-touch-icon-precomposed" href="iphone_logo.png" />
启动时候的画面(无用)
<link rel="apple-touch-startup-image" href="logo_startup.png" />
设置x5内核浏览器只能竖屏浏览(只有UC有效)
<meta name="x5-orientation" content="portrait" />
设置x5内核浏览器全屏浏览
<meta name="x5-fullscreen" content="true" />
设置UC浏览器只能竖屏浏览
<meta name="screen-orientation" content="portrait">
设置UC浏览器全屏浏览
<meta name="full-screen" content="yes">
如果想屏蔽所有浏览器的横屏的话,需要在后面陀螺仪那章节讲
移动端样式重置
1、禁止用户选中文字,安卓无效(在事件那章解决,包括长按的时候会出菜单,用阻止touchstart后的默认行为搞定)
-webkit-user-select: none;
2、禁止长按弹出系统菜单
-webkit-touch-callout: none;
3、去除android下a/button/input标签被点击时产生的边框 & 去除ios下a标签被点击时产生的半透明灰色背景
-webkit-tap-highlight-color: rgba(0,0,0,0);
4、切换横竖屏或者用户自己通过浏览器设置的话,可以改变字体的大小(需要给body下的所有元素)
-webkit-text-size-adjust: 100%;
5、按钮在ios下都是圆角
-webkit-appearance: none; //button与input都会有个默认背景
border-radius: 0; //input有个默认圆角
6、修改placeholder的样式
input::-webkit-input-placeholder{
color:#000; //默认的样式
}
input:focus::-webkit-input-placeholder{
color:#f00; //点击后的样式
}
7、字体
ios
默认中文字体是Heiti SC
默认英文字体是Helvetica
默认数字字体是HelveticaNeue
无微软雅黑字体
android
默认中文字体是Droidsansfallback
默认英文和数字字体是Droid Sans
无微软雅黑字体
font-family: helvetica;
移动端适配
适配是为了一版设计稿走天下,适配的范围包括字体、宽高、间距、图像
在熟悉了解了前面的概念之后,下面就来介绍移动端的适配几种方式。
百分比适配
根据父级设置宽度。但是有时候百分比不太好算,而且计算的时候需要知道父级的高度。
viewport
缩放适配
根据前面 缩放比 = 设备 css 像素 / viewport 宽度 => viewport 宽度 = 设备 css 像素 / 缩放比。
把所有机型的 css 像素设置成一致的,那么切图的时候只需要切一种尺寸的就可以了。代码如下
(function(){
//获取css像素(viewport没有缩放)
var curWidth=document.documentElement.clientWidth;
var targetWidth=375; // 最终尺寸
var scale=curWidth/targetWidth; // 缩放比
var view=document.getElementById('view');
view.content='initial-scale='+scale+',user-scalable=no,minimum-scale='+scale+',maximum-scale='+scale+''; // 这样设置了以后,所有设备上的 viewport 都为 375了。
})();
注意这里也需要将最大和最小缩放比设置为和初始的值一样,不然如果它们都还是 1 的话,前面的就没有效果了,因为现在还是规定最大最小的缩放比为 1。
缺点:因为现在在任何设备上的viewport的宽度都为固定的宽度,例如 375 的图片放到 大屏幕上,因为宽度是固定的,所以肯定会变得模糊
DPR
缩放适配
根据dpr的值,把视口进行缩放,缩放到物理像素,也就是把css像素的值设置成物理像素,让所有的设备都变成一个css像素对应一个设备像素,方便切图
(function(){
/*
375*2 750
320*2 640
375/?=750 => 375/750=2
1/dpr // 公式
320/scale=640 => scale=320/640 1/2
*/
var meta=document.querySelector('meta[name="viewport"]');
var scale=1/window.devicePixelRatio;
if(!meta){
//这个条件成立说明用户没有写meta标签,我需要创建一个
meta=document.createElement('meta');
meta.name='viewport';
meta.content='width=device-width,initial-scale='+scale+',user-scalable=no,minimum-scale='+scale+',maximum-scale='+scale+'';
document.head.appendChild(meta);
}else{
meta.setAttribute('content','width=device-width,initial-scale='+scale+',user-scalable=no,minimum-scale='+scale+',maximum-scale='+scale+'');
}
})();
rem
适配
rem 是相对于根节点(html
)的字体大小。
它的原理是把所有的设备都分成相同的若干份,再计算元素宽度所占的份数,开发的时候只需要使用一个特定的设备 并且使用rem 那么在其他设备上会自动出现相同的效果即自动适配(很神奇),并且设计稿需要以物理像素为准来设计 例如分辨率宽为 375 drp为2,那么实际针对该机型的设计搞应该为750。
媒体查询方式
即通过媒体查询,对所有范围内的尺寸给定一个 html 根结点字体大小。可参考苏宁易购。
js简单方式
- 计算出每一列的宽度:viewport宽度(css像素)/16(列数),并将其设置为根结点字体大小。
- 根据设计稿量出的实际尺寸除以 dpr,然后再根据换算后的尺寸,除以一列的宽度(1rem),元素占 n 列
- 然后设置元素的宽度为 nrem。
(function(){
var html=document.documentElement; //html
var width=html.clientWidth; //css像素
// 方式一
html.style.fontSize=width/16+'px'; //把屏幕分成了16列,以iphone为例得出一个列的值为整数
// 方式二
html.style.fontSize= 16 * clientWidth / 375 + 'px'; // 以iphone6 为基准,当大于 iphone6 的尺寸时,字体大小大于 16px, 同理小于时,字体小于 16px。
})();
js经典方式
相比于上面的普通方式,经典方式省掉了,根据设计稿量出的实际尺寸除以 dpr 这一步,直接将设计稿当中量出来的尺寸除以 100 然后单位为 rem。下面依然以 iphone6 为例。
(function(doc, win, designWidth) {
const html = doc.documentElement;
const refreshRem = () => {
const clientWidth = html.clientWidth;
if (clientWidth >= designWidth) { //给宽度一个最大值,如果设备的宽度已经超过设计稿的尺寸了,统一按一个值去算(传的第三个参数)
html.style.fontSize = '100px';
} else {
html.style.fontSize = 100 * (clientWidth / designWidth) + 'px'; // 这种方式是我们在切图的时候不需要手动去除dpr, 已经帮我们处理好来,但是我们在计算的时候还是必须使用1rem = 100px来计算
}
};
//dom加载完的一个事件
doc.addEventListener('DOMContentLoaded', refreshRem);
})(document, window, 750);
vw
适配
vw 将页面分为 100 份,相关单位如下:
- vw Viewport's width的简写,1vw等于视口宽度的1%
- vh Viewport's height的简写,1vh等于视口高度的1%
- vmin 取vw和vh中最小的值
- vmax 取vw和vh中最大的值
兼容性如下:
- >=ios 8
- >=Android 4.4
并且 vw、vh分别代表水平和竖直方向,和横竖屏没有关系,会自动根据横竖屏来计算得到每一份的宽度,如图:
有两种使用 vw 方式
方式一
通篇使用 vw, 和前面 rem 部分提到的 js 简单部分差不多,只不过省略了计算每一份的过程,浏览器自动帮我们计算 1vw 是多少。注意切图的使用还是要除以 dpr。可以采用 scss 等 css 预处理语言来简化这个过程。
方式二
通过 vw 设置根节点字体大小,页面里的尺寸依然使用rem。但是前提是你要知道页面当中根节点的字体大小,根节点字体的大小的计算参考前面 rem 布局部分的 js 经典方式。
移动端存在的几个问题
固定定位
在 ios 下面,如果页面里有一个固定定位(fixed)的元素以及一个 input 元素的时候,用户但凡点击input调出键盘的时候,固定定位元素就会不起作用。解决方式:
- 将需要滚动的元素放到一个容器里面,容器超出就滚动,这样容器和固定定位元素就会在一个页面,就算失效了,也在一个页面内可见。
1px
问题
在移动端 dpr, 往往是 2 及其以上,所以 1px 往往代表多个物理像素,这就是 1px 问题, 解决办法:
- dpr 缩放适配不存在这个问题,因为 dpr 缩放适配是
1px = 1pt
- 可以使用 css3 提供的 scale 来缩放边框为 0.5 倍, 下面是创建了一个伪类,并缩放它的边框来达到缩放的目的.
section::after{
content: '';
position: absolute;
left: 0;
top: 0;
border: 1px solid #000;
box-sizing: border-box;
width: 100%;
height: 100%;
transform-origin: 0 0;
transform: scale(0.5);
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。