侃侃----移动端

移动端开发是最流行的,而对于移动端开发者适配是一个值得聊一聊的话题。适配,达到完成工作的目的其实很简单,但如果你想深入的了解其实还是有很多料的。会有很多大神跟你延伸出一堆的知识,我们只是来简单通俗的交流,来稍微深入一些了解相关知识。

开发移动端页面,大家第一步肯定是在head区引入这个标签, ,然后一顿操作,单位有的用px、有的用em、有的会用rem,然后再一点点挪动你从设计稿上量取的值,最后心满意足的发布上线,遇到显示有差异的手机再回来继续挪动的量取的值。

其实,这是一个正经的套路。不过有些问题如果在我们理解之后会更容易上手。我们可以稍微往深入的想想,这个标签是干什么的?

其实,这个meta视口标签只进行了几个简单的操作:设置页面的布局视口设定为理想视口、缩放比例为1、不允许进行缩放操作。注意,不要在页面重复的设置meta视口标签,对于有些安卓系统会出现你想都不敢想的问题。这个标签涉及到的属性:

width: 设置布局视口的宽

init-scale 设置页面的初始缩放程度

minimum-scale设置页面最小缩放程度

maximum-scale设置页面的最大缩放程度

user-scalable  是否允许用户进行缩放操作

我们先来放一个iphone手机的一些具体参数,下面有些不懂得可以进行对照就会清晰很多。

设备            屏幕尺寸            分辨率(pt)          Reader      物理分辨率(px)        PPI(DPI)

iphone4          3.5尺寸        320*480          @1x                320*480                  163

iphone5          4尺寸          320*568            @2x                640*960                  326

iphone6          4.7尺寸        375*667            @2x            750*1334              326

我们这里提到了理想视口、缩放等信息。很好理解,就是理想状态下的视觉窗口、缩大放小的比例规范吗?字面上是这么个意思。但是想要深入理解,我们需要理解几个简单的概念:

一、像素

这个简单,前端最常用的单位了,不过我们这里还是要简单说道说道:

像素本身是指计算机屏幕所能显示的特定颜色的最小区域,但前端开发的像素会包含设备像素和css像素

设备像素,就是设备屏幕的物理像素,数量是固定的。

css像素,可以说是为web开发者创造的抽象概念。

如果你为一个元素设定了1000px的大小,那么这个元素是不是就跨越1000个设备像素呢?

并不一定是的。那么它会跨越多少个设备像素呢?这就要取决于手机屏幕的特性和用户的缩放了。

在早先的移动设备中,屏幕像素密度都比较低,一个css像素是等于一个设备像素的,当设置了width:1000px,1000个CSS像素跨越了1000个设备像素。但随着Retina屏的出现,分辨率提高一倍,而屏幕尺寸却没变,这时的css像素相当于两个物理像素。苹果手机还是比较规范,它的像素密度是普通屏幕的2倍。而安卓就五花八门了,安卓设备根据屏幕像素密度就可分为ldpi、mdpi、hdpi、xhdpi等等不同等级,分辨率更是多种多样。

除此之外,缩放也会引起css像素的变化,比如页面缩小一倍,css像素也会减少一倍。分辨率越大的移动设备,css的1px代表的物理像素就会越多。这是因为分辨率越大,而屏幕尺寸确没有变化,就会让css的1px代表更多的物理像素,devicePixelRatio的值也会越大。

二、视口

在移动端我们会涉及三个视口的概念。可以理解为视口是html元素的父元素,即为初始包含块。

视觉视口

就是我们视觉看到的窗口大小,我们可以缩放的操作,而不会影响布局视口。

布局视口

这个是我们最熟悉的了,移动端css布局的依据视口,即CSS布局会根据布局视口来计算。

移动设备上的viewport就是设备的屏幕上能用来显示我们的网页的那一块区域,但viewport为了兼容桌面浏览器的设计,又不局限于浏览器可视区域的大小,他可能比浏览器的可视区域要大,也可能要小。一般,移动设备的viewport为了兼容电脑显示都要大于浏览器的可视区域的,这就会出现滚动条的显示。不过它也有好处的,就是拿掉了移动端布局对于屏幕宽度的限制。


我们可以通过JS来获取布局视口的宽度和高度(不过存在一丢丢的兼容性,正常情况下都是没问题的):

document.documentElement.clientWidth

document.documentElement.clientHeight

理想窗口

这个可以说是为了我们的适配专门引入的,就是理想状态下的视口宽度。在移动设备中就是指设备的分辨率。换句话说,理想视口或者说分辨率就是给定设备物理像素的情况下,最佳的“布局视口”。比如iphone5理想视口就是320*568。但对于安卓手机理想视口的默认值都很不理想,我们需要meta视口标签进行手动设定。上面说到CSS是根据布局视口来进行计算的,我们将布局视口设为理想口来方便我们进行适配,就是引入的meta视口标签:。而能达到同样的效果。为什么呢?因为缩放就是基于理想视口进行的,当前缩放值 = 理想视口宽度  / 视觉视口宽度。对于同时出现这两种设定,会取宽度结果的最大值。比如你设定width=600px,而按照initial-scale进行缩放之后的值是420px,那么就会取420px。另外,initial-scale的值是越大,缩放得到的结果越小。

三、设备像素比(DPR)

1、Device Pixel Ratio

window对象的devicePixelRatio属性,官方定位为,设备物理像素和设备独立像素的比例,但是有些浏览器对这个属性是有兼容问题的。DPR=物理像素/分辨率,可以理解为设备像素比DPR = 设备像素个数/理想视口CSS像素个数(device-width)

// 注:前提是缩放比是1,在不缩放的情况下,一个css像素就对应一个dpr。

设备像素比对于不同的设备是不同的,比如早先的iphone的设备像素是320px,理想视口也是320px,

所以早先的iphone的DPR是1,而后来的iphone的设备像素是640px,理想视口还是320px,

所以后来的iphone的DPR是2.

现在主流手机显示屏是2 or 3,高密度桌面显示屏是2.

简单介绍一下倍图

有一张图片,你设置了宽高都是50px。

你在普通屏幕下打开是完全没问题的,但是如果在高清屏下打开,按照逻辑分辨率渲染(这时的devicePixelRatio=2)就会变得模糊,这时你会需要使用@2x甚至@3x来避免图片失真。这个@2x和@3x就是所谓的几倍图(这里需要用到CSS3的image-set的CSS属性或是html5的srcset)。

2、缩放

缩小或放大的CSS像素

缩放就是基于理想视口进行的,当前缩放值 = 理想视口宽度  / 视觉视口宽度。

3、meta标签

meta视口标签

width:    设置布局视口的宽

init-scale    设置页面的初始缩放程度

minimum-scale设置页面最小缩放程度

maximum-scale设置页面的最大缩放程度

user-scalable  是否允许用户进行缩放操作

四、js动态设置viewport的方案

目前最好的解决方案。

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');

作用是直接将理想视口设定与设备像素的相同,直接按设计稿的尺寸不需要进行换算,然后在其他尺寸的手机中,

我们进行等比缩放就ok了。

我们知道,一般我们获取到的视觉稿大部分是iphone6的,所以我们看到的尺寸一般是双倍大小的,

在使用rem之前我们一般自觉的将标注/2,其实完全可以按照视觉稿的尺寸来设置。

1).设计给的稿子双倍的原因是iphone6这种屏幕属于高清屏,即设备的像素比dpr比较大,

所以显示的像素较为清晰。

2).一般手机的dpr是1,iphone4和5是2,iphone6s plus这种是3,可以通过window.devicePixelRatio来获取当前设备的dpr,所以iphone6的视觉稿大小是(*2)750*1334了。

3).拿到了dpr之后,我们就可以在viewport meta头里,取消让浏览器自动缩放页面,

而自己去设置viewport的content例如(这里之所以要设置viewport是因为我们要实现border1px的效果,在scale的影响下,高清屏会显示成0.5px的效果)

五、实现方式

1、百分比

其实在高度上并没有很好的自适应。会出现一些比较奇怪的问题。

还有一个比较明显的问题就是:

在任何机型上我们的按钮的高度是不会变化自适应的,宽发生变化但是高度没有变化,所以小屏手机我们的按钮看起来很臃肿

2、媒体查询

响应式设计的基础:

检测媒体的类型,比如screen,tv等

检测布局视口的特性,比如视口的宽到分辨率等

特性相关查询,比如检测浏览器是否支持某某特性(无用)

语法:

@media 媒体类型 and (视口特性阈值) {

// 满足条件的样式

}

eg.

@media all and (min-width: 321px) and (max-width: 400px) {

.bx {

xxx

}

}

缺点:

相对于代码要重复很多

可能存在闪屏的问题出现

常用的临界点:

1199px

991px

767px

480px

375px

320px

五、一些常用单位的概念简析

px

相对长度单位。是相对于显示器屏幕分辨率而言的(也就是跟物理设备有关)。

高清屏和普通屏对比就是普通屏的1个像素就是1个物理像素,而高清屏的是4个

物理像素点。

em

相对长度单位。相对于当前对象内文本的字体尺寸。

如当前对行内文本的字体尺寸未被人为设置,则相对于浏览器的默认字体尺寸。

em单位特点:

1.em的值并不是固定的

2.em会继承父级元素的字体大小

rem

相对长度单位。CSS3新增的一个相对单位,这个单位引起了广泛的关注。与em的

区别在于rem为元素设定字体大小时,仍是相对大小,但相对的只是HTML根元素。

这个单位可谓集相对大小和绝对大小的优点于一身,通过它既可以做到只修改根

元素就成比例地调整所有字体大小,又可以避免字体大小逐层复合的连锁反应。

缺点

IE不支持,PC端使用次数不多

数据量大,所有的图片、盒子都需要精准的值完成适配

弱网条件下会出现可能会出现闪屏:

(解决闪屏就是要在CSS渲染的时候,就让HTML显示正常,在开始的时候就进行font-size的计算,

@media (min-width: 320px){html{font-size: 42.6667px;} }

@media (min-width: 360px){html{font-size: 48px;} }

@media (min-width: 375px){html{font-size: 50px;} }

@media (min-width: 384px){html{font-size: 51.2px;} }

@media (min-width: 414px){html{font-size: 55.2px;} }

@media (min-width: 448px){html{font-size: 59.7333px;} }

@media (min-width: 480px){html{font-size: 48px;} }

@media (min-width: 512px){html{font-size: 68.2667px;} }

@media (min-width: 544px){html{font-size: 72.5333px;} }

@media (min-width: 576px){html{font-size: 76.8px;} }

@media (min-width: 608px){html{font-size: 81.0667px;} }

@media (min-width: 640px){html{font-size: 85.3333px;} }

@media (min-width: 750px){html{font-size: 100px;} })

注:

任意浏览器的默认字体大小都是16PX。所有未经调整的浏览器都符合:1rem=16px.

那么12px=0.75rem;为了简化font-size的换算,需要在css中的html选择器中声明

font-size=62.5%,这就是使rem值变为16px*62.5%=10px,这样12px=1.2rem,也

就是说只需要将原来的px数值除以10,然后换上rem作为单位就行。

在使用rem的时候比较麻烦的就是px和rem换算的问题。上面的除10方案是比较简单

的。但是根据基准值的不同换算方法也不一样。如果我们使用scss来写我们的样式

表的话,解决方法就比较简单了,代码如下:

@function px2rem($px){

@return ($px/10)/2+rem;  //相当于$px/20 +rem

}

width:px2rem(100px);  //5rem

height:px2rem(200px);  //10rem

为什么使用rem作单位

对于设计稿中展示的商品的坑位的宽高比是固定的。为了在不同屏幕上达到最佳的

显示效果,需要保持宽度和高度一致。而百分比对于高度是没有办法控制的。目前

最优的解决方案就是rem。

为什么将计算根元素的font-size值的js放在head标签中

设置根节点font-size值的方法

一是使用css的Media queries

eg:

@media(min-device-width:375px)and(max-device-width:667px)and(-webkit-min-device-pixel-ratio:2){

html{font-size:37.5px;}

}

这种方法的一个很明显的问题font-size是在一个屏幕宽度的区间上有一个基准值。对于屏幕大小很多,该方法很鸡肋。

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

将rem设定为body屏幕宽度的十分之一。

二是JS根据当前屏幕的宽度动态计算font-size值

可以保证屏幕宽度连续变化时,font-size基准值也是连续变化的。

注:为了保证不发生不必要的重绘或者是重排,所以放在head区。

使用rem布局的情况和注意问题

1.整体的布局还是使用百分比。

2.使用rem的最佳场所是,遇到例如多列带有图片的列表,常常需要图片固定宽高比

3.对字体一般使用px(防止出现13.7172727px这种在)

4.出现1px的地方仍旧使用px

点5像素的由来

高清屏可以识别0.5像素的效果。

实现点5像素的方法

伪元素+css3的缩放巧妙实现

1.设置目标元素定位参照

2.给目标元素添加一个为元素before或者after,并设置绝对定位

3.给伪元素添加上1px的边框

4.设置伪元素的宽高为目标元素的两倍

5.缩小0.5倍

6.使用border-box把border包进来

.item4, .item5 {

width: 200px;

height: 100px;

position: relative;

}

.item4 {

border: 1px solid #000;

}

.item5::before {

content: '';

position: absolute;

width: 200%;

height: 200%;

border: 1px solid #000;

transform-origin: 0 0;

transform:scale(0.5, 0.5);

box-sizing: border-box;

}

测试用的边框

测试用的边框

六、实现方法和具体步骤

第一种修改meta标签

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值

body{

margin: 0;

padding: 0;

}

.box{

width: 2.66666667rem;

height: 2.66666667rem;

background: red;

}

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

//---------------------------------------

测试

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

})();

html {

height: 100%;

width: 100%;

overflow: hidden;

font-size: 16px;

}

div {

height: 0.5rem;

widows: 0.5rem;

border: 0.01rem solid #19a39e;

}

........

第二种不修改meta标签,按照1:1的比例进行:

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

2、动态设置html标签的font-size值:

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

如iPhone6的设计图就是:

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

iPhone5的设计图就是:

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

这样,无论在什么设备下,我们页面的总宽度都是7.5rem,所以我们直接在设计图上测量px单位的尺寸,然后除以100转换成rem单位后直接使用就可以了

3、做页面是测量设计图的px尺寸除以100得到rem尺寸。

4、和淘宝的做法一样,文字字体大小不要使用rem换算。

你可能感兴趣的:(侃侃----移动端)