在进入正文之前,我们需要先了解一些viewport相关的概念。
viewport
一般来说,我们在代码的最开始会写上这么一句
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
移动端浏览器可以在一个比屏幕更宽的虚拟”窗口“中渲染页面,从而无需将所有页面都压缩进小屏幕里(那样会把很多没有针对移动端进行优化的站点打乱)。用户可以通过平移和缩放来浏览页面的不同区域。比如我们把一个页面的宽度写成了10000px,那么我们照样可以通过平移缩放来看到这个页面,当然这是不可取的,所以我们就需要以上代码,将viewport的width设置为设备的宽度,缩放的倍数是1,且不让用户进行缩放(这个可以根据实际业务场景来设置)。经过以上设置,我们就可以开始进入愉快写代码的第一步了~
- 物理像素DP(device pixels)和css像素
物理像素一般在设备出厂的时候就被设置好了,也叫设备像素,单 位是pt(point)
,pt
是一个物理单位,指的是组成显示器屏幕的绝对长度。我们买电视机的时候,会说,我买个70寸的电视机。
1英寸=72pt
px(pixel)是一个虚拟的单位,也是一个相对的单位。根据《CSS权威指南》的像素理论中的解释:
显示器上的小色框是像素
CSS2.1 建议采用96ppi(pixels per inch),这是Windows机器常用的度量。Mac系统下用的是72ppi。
摘录来自: Eric Meyer. “CSS权威指南第三版”。 iBooks.
1px=1/ppi英寸
通过inch就可以连接器pt和px的关系。
- 设备独立像素DIP(Device independent Pixel)
设备独立像素,也称为逻辑像素,也叫css像素。我们可以通过screen.width或者screen.height输出。比如iPhone的css像素就是375px*667px,iPhone 6 则采用了750×1334分辨率的屏幕,PPI值为326。
物理像素和css像素的计算公式是:
DPR = 物理像素/CSS像素
css reset样式重置
为什么要进行css reset操作?
css reset主要是因为html标签在浏览器中都有各自的默认样式。
比如: p 标签有上下边距,strong标签有字体加粗样式,em标签有字体倾斜样式。不同浏览器的默认样式之间也会有差别,例如ul默认带有缩进的样式,在IE 下,它的缩进是通过margin实现的,而Firefox下,它的缩进是由padding实现的。在切换页面的时候,浏览器的默认样式往往会给我们带来麻烦,影响开发效率。所以解决的方法就是一开始就将浏览器的默认样式全部去掉,更准确说就是通过重新定义标签样式。
常用的适配方案
- flex
<div class="content">
<div class="con">
<div class="a"></div>
</div>
<div class="con">
<div class="a"></div>
</div>
<div class="con">
<div class="a"></div>
</div>
</div>
.content{
display: flex;
}
.con{
display: flex;
justify-content:center;
align-items:center;
flex:1;
height: 300px;
background: #999;
color:#fff;
border:1px solid #000;
}
.a{
width: 30px;
height: 30px;
background: #f00;
}
-
媒体查询media query
一个媒体查询由一个可选的媒体类型和零个或多个使用媒体功能的限制了样式表范围的表达式组成,例如宽度、高度和颜色。媒体查询,添加自CSS3,允许内容的呈现针对一个特定范围的输出设备而进行裁剪,而不必改变内容本身。
我们把上面flex的css换掉其中a的样式,来看一下media query的作用。
.a{
background:#f00;
}
@media (max-width: 800px) {
.a {
width:50px;
height:50px;
font-size:12px;
color:#2e9900;
}
}
@media (min-width:801px) and (max-width:1000px) {
.a {
width:200px;
height:200px;
font-size:20px;
color:blue;
}
}
@media (min-width: 1001px) {
.a {
width:450px;
height:450px;
font-size:40px;
}
}
- transform-scale
其实我自己觉得transform-scale
是一个不错的适配方式,简单明了,而且暂时也没有遇到过什么适配方面的大坑,相对而言还比较精确。
处理方式很简单,样式完全按照设计稿的px
来写。然后在js中计算当前页面的宽度与设计稿的宽度的比,直接对body
进行transform-scale
的缩放。
如果非要说有什么问题的话,那就是如果需要考虑横屏受众,那就得针对一些横屏的状态做一些特殊处理。还有就是transform-scale
缩小没有问题,放大的话,会导致页面模糊。
这个方案就看自己业务需求来选择了。
- rem
rem算是一个使用很广泛的适配方案了。
实现的方式就是给html根节点设置一个font-size,作为页面计算的基准。一般这个基准会根据设计稿来定。
假设设计稿的宽度是750px,那最初我们可以将font-size设为75px,页面宽度就是10rem。
然后在页面中用js动态获取一下当前页面宽度,计算出页面宽度与750px的比例,获取当前页面根节点上应该带上多大的font-size,假设当前页面宽度是375px,那么根节点上带上的font-size应该是37.5px。
这个方案是一个与dpr无关的方案,就是说完全依赖的是设备独立像素而不是设备的物理像素,这样就会存在一个问题,在dpr较大的高清屏上,可能导致模糊。
当然,我们也是可以加上dpr来计算根节点的font-size的。
- flexible.js
flexible是手淘的一套解决方案,这是一套dpr
相关的解决方案。
实现的原理是:
flexible将页面分成100份,即100a,10a=1rem。比如,页面宽度为750px,那么一份为75px,1rem=75px。
通过js动态获取当前页面的dpr和设备独立像素。拿iPhone 8 plus举例,得到dpr是3,设备独立像素是414px。那么html上写的font-size的大小是这么计算的:
dpr * 414 / 10
最终得到的font-size值是124.2px,然后在meta的initial-scale里会根据dpr再进行一下页面缩放,这就可以保证页面的精细程度。
但是如果在meta viewport中手动设置了initial-scale,那么不管js获取到的dpr是多少,都会强制认为dpr是手动设置的值;
手淘处理文字的方式,并没有采用rem,因为rem计算出的小数,在对小数敏感度不一样的机型上会导致展示误差,且小于12px的文字并不会正常被渲染。也会导致一些line-height的问题。
- vm
随着前端技术的演进,vw这个单位又走上了历史的舞台。
在CSS Values and Units Module Level 3中和Viewport相关的单位有四个,分别为vw
、vh
、vmin
和vmax
。
- `vw`:是Viewport's width的简写,`1vw`等于`window.innerWidth`的`1%`
- `vh`:和`vw`类似,是Viewport's height的简写,`1vh`等于`window.innerHeihgt`的`1%`
- `vmin`:`vmin`的值是当前`vw`和`vh`中较小的值
- `vmax`:`vmax`的值是当前`vw`和`vh`中较大的值
常见的屏幕适配问题和解决方案
- line-height
一般客户端的webview会有一个默认的line-height,大概会是在22px的样子。我们有可能会遇到一个问题就是,在我们设置好一个line-height之后,但是渲染出来的文字相对于我们预想的是偏上的。导致这个问题的原因是,我们设置的line-height是小于webview预设的最小line-height的,这样我们设置的那个值会被忽略。
解决的方案是:
尽量保证font-size是大于12px的,将line-height设置为1,使用上下padding使文字居中。在一些必须需要font-size小于12px的地方,可以先放font-size大于12px,再用transform:scale去缩小。
但是这一点从实际经验来看,我更偏爱手淘的方案,根据dpr或者mediaquery设置一个固定的字体,这就需要和设计同学定下一个设计规范。 - 中英文的字号一样,但是实际高度却不一样
文字的大小,取决于设计文字的人,就像我们前几天遇到的英文比中文同字号小的问题,如果光靠上下的padding来写的话,那就可能会出现纯英文或者数字那块会比较矮。 - 1像素问题
产生原因:因为dpr高的设备下,写的1像素,实际是比1的dpr倍。
解决方案:1)如果整体缩放页面的话,1像素的线也会被一起缩放
2)可以将线条所在元素用transform-scale缩小 - 如果设计师在设计稿上使用的文字很细,比如华文细黑这样的,那前端为了适配更完美,可以用一个样式-webkit-font-smoothing: antialiased;
- 在移动端我们写了overflow:scroll;之后,滑动可能并不能像我们预料中的那么顺畅,可以使用样式-webkit-overflow-scrolling: touch;
- 如果input或button的有怪异的默认样式,尝试appearance:none;(-webkit-appearance:none;)