适配要达到何种效果?
在不同尺寸的手机设备上,页面要能够良好的展示, 不会出现错位变形(自适应), 或者保持统一效果的等比缩放。
设计稿尺寸
第一个问题就是选用多大的设计稿尺寸,如果按照320px的设计稿切图,在retina屏幕下,图片会失真。因为在retina屏幕上以 ipone4(320*480)为例,其实际像素点个数为 640*960。
贴一张图帮助理解
如上图所示,普通屏幕(左图)和 retina屏幕(右图)1个css像素所对应的物理像素是不一致的。
在普通屏幕下, 1个css像素 对应 1个物理像素 (1:1)
在 retina 屏幕下,1个css像素 对应 4个物理像素 (1:4)
理论上来说,一个图片上的像素对应一个物理像素,图片才能得到完美展示。
在普通屏幕下没有问题,但是在 retina 屏幕下就会出现图片像素点不够,从而导致图片模糊。
贴一张图帮助理解
如上图:对于dpr=2的retina屏幕而言,1个位图像素对应于4个物理像素,由于单个位图像素不可以再进一步分割,所以只能就近取色,从而导致图片模糊(注意上述的几个颜色值)。
因此,对于图片失真问题,解决办法就是采用 两倍大小的图片
但是如果在普通屏幕下,也采用 两倍图片,会怎么样呢?
如左图,1个物理像素对应4个图片像素,结果是因此色差。
综上:处理图片在高清屏下1倍大小的图片的失真和普通屏下2倍图片色差的问题,应该准备两套图片,通过媒体查询或者来引入相应的图片url
retina下,border:1px问题
由于在retina屏幕上1个css像素对应2个物理像素,也就是说它的最小显示单元为0.5个css像素,如果我们设置如下css
border: 1px solid #000;
在普通屏和retina屏幕上的效果是这样的
也就是说,我们无法写出只占一个物理像素的边框样式,因为设置0.5px 在某些系统中会被当成0px。
网上的解决办法是
.scale{ position: relative; } .scale:after{ content:""; position: absolute; bottom:0px; left:0px; right:0px; border-bottom:1px solid #ddd; -webkit-transform:scaleY(.5); -webkit-transform-origin:0 0; }
用 :after 来偏移出另外的0.5像素, 这种 hack 不够通用,无法处理圆角等.
另外一种是处理方案是 对于 dpr=2 的屏幕添加如下meta标签
<meta name="viewport" content="width=640,initial-scale=0.5,maximum-scale=0.5, minimum-scale=0.5,user-scalable=no">
设置 viewport 的初始缩放比例为 0.5, 这样整个页面的 1px 边框都会变成 0.5px, 适用于所有场景
但是缩放整个页面也会带来一定的问题:
1、字体大小也会被缩放,在普通屏和高清屏下无法显示一致
2、页面布局也会被缩放
适配布局
网上有很多种布局方案,这里只写一致认为比较好的方案,rem布局
原理: 根据不同手机尺寸和 dpr 动态改变根节点<html>的 font-size 大小,页面其他元素以此为基准进行计算
直接贴代码
var docEl = document.documentElement, metaEl = document.querySelector(‘meta[name="viewport"]‘), styleEl = document.createElement(‘style‘), dpr = win.devicePixelRatio || 1, rem = docEl.clientWidth * dpr / 10, scale = 1 / dpr; // 动态是指 viewport 的缩放比例 metaEl.setAttribute(‘content‘, ‘width=device-width, initial-scale=‘ + scale + ‘, maximum-scale=‘ + scale + ‘, minimum-scale=‘ + scale + ‘, user-scalable=no‘); // 设置data-dpr属性, 留作 css hack 之用 docEl.setAttribute(‘data-dpr‘, dpr); // 动态写入样式 docEl.firstElementChild.appendChild(styleEl); styleEl.innerHTML = ‘html{ font-size: ‘+ rem +‘px !important; }‘;
计算 rem 说明
1. 乘以 dpr ,规避缩放对布局和字体大小的影响
2. 除以16,我也不知道,据说为了换算出一个较小的基准值,也可以设置为10,或者任何你想要设置的值
通过计算的html的font-size为:
iphone3gs: 320px / 10 = 32px
iphone4/5: 320px * 2/ 10 = 64px
iphone6: 375px * 2 / 10 = 75px
如何在css编码中还原视觉稿的真实宽高?
对于宽度为 640px的设计稿, 如果一个div的宽高为 300*320px 如何转换成rem
用 sass 封装一个 mixin
// 例如 toRem(height, 300) $ppr: 640px / 10 * 1rem; // pixel per rem
@mixin toRem($property, $values...){ $max: length($values); $remValues: ‘‘; @for $i from 1 through $max{ $value: nth($values, $i) / $ppr; $remValues: #{$remValues + $value}; @if $i < $max{ $remValues: #{$remValues + " "}; } } #{$property}: $remValues; }
所以对于宽高为 300*320px 的div,可以这样写
@include toRem(width, 300px); @include toRem(height, 320px);
得到的css代码为
width: 4.6875rem; height: 5rem;
字体大小问题
不同的dpr会导致不同的缩放比例,字体也会被缩放,由于字体不能使用rem,所以需要对不同的dpr屏幕应用不同的字体大小,也可以封装一个mixin,我还不知道如何封装,等我知道了再来补全 ^_^
参考网站:移动端高清,多屏适配,移动端页面使用rem布局