移动端适配1px的问题终极方案

解决移动端1px在一些屏幕会变粗的原因

一、起因

为什么移动端css里面写了1px, 实际看起来比1px粗. 其实原因很好理解:这2个’px’ 的含义是不一样的. 移动端 html 的 header 总会有一句
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
这句话定义了本页面的 viewport 的宽度为设备宽度,初始缩放值和最大缩放值都为1,并禁止了用户缩放. viewport 通俗的讲是浏览器上可用来显示页面的区域, 这个区域是可能比屏幕大的。

首先,我们了解devicePixelRatio这个东西

在window对象中有一个devicePixelRatio属性,他可以反应css中的像素与设备的像素比。然而1px在不同的移动设备上都等于这个移动设备的1px,这是因为不同的移动设备有不同的像素密度。有关这个属性,它的官方的定义为:设备物理像素和设备独立像素的比例,也就是

devicePixelRatio = 物理像素 / 独立像素 1px变粗的原因:
viewport的设置和屏幕物理分辨率是按比例而不是相同的. 移动端window对象有个devicePixelRatio属性,
它表示设备物理像素和css像素的比例, 在retina屏的iphone手机上, 这个值为2或3,
css里写的1px长度映射到物理像素上就有2px或3px那么长

二、终极解决方案
1.用小数来写px值 (不推荐)

IOS8下已经支持带小数的px值, media query 对应 devicePixelRatio 有个查询值 -webkit-min-device-pixel-ratio, css可以写成这样
通过-webkit-min-device-pixel-ratio设置。

.border { border: 1px solid #999 }
@media screen and (-webkit-min-device-pixel-ratio: 2) {
    .border { border: 0.5px solid #999 }
}
@media screen and (-webkit-min-device-pixel-ratio: 3) {
    .border { border: 0.333333px solid #999 }
}

如果使用less/sass的话只是加了1句mixin
缺点: 安卓与低版本IOS不适用, 这个或许是未来的标准写法, 现在不做指望

2、flexible.js

这是淘宝移动端采取的方案, github的地址:https://github.com/amfe/lib-flexible. 前面已经说过1px变粗的原因就在于一刀切的设置 viewport 宽度, 如果能把 viewport 宽度设置为实际的设备物理宽度, css 里的 1px 不就等于实际 1px 长了么. flexible.js 就是这样干的.
<meta name=”viewport”>里面的 scale 值指的是对 ideal viewport 的缩放, flexible.js 检测到 IOS 机型, 会算出 scale = 1/devicePixelRatio, 然后设置viewport

metaEl = doc.createElement('meta');
metaEl.setAttribute('name', 'viewport');
metaEl.setAttribute('content', 'initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no');

devicePixelRatio=2时输出meta如下, 这样viewport与ideal viewport的比是0.5, 也就与设备物理像素一致

<meta name="viewport" content="initial-scale=0.5, maximum-scale=0.5, minimum-scale=0.5, user-scalable=no">
3、伪类+transform实现

对于解决1px边框问题,我个人觉得最完美的解决办法还是伪类+transform比较好。
原理:是把原先元素的 border 去掉,然后利用 :before 或者 :after 重做 border ,并 transform 的 scale 缩小一半,原先的元素相对定位,新做的 border 绝对定位。

<!DOCTYPE html> 
<html> 
 <head> 
 <meta charset="UTF-8"> 
 <title>test</title> 
 </head> 
 <body> 
<div class="box-shadow-1px scale">box-shadow-1px</div>
<style>
.box-shadow-1px {
    height: 200px;
    width: 200px;
    text-align: center;
}
.scale{
  position: relative;
  margin-bottom: 20px;
  border:none;
}
.scale:after{
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  border: 1px solid #000;
  -webkit-box-sizing: border-box;
  box-sizing: border-box;
  width: 200%;
  height: 200%;
  -webkit-transform: scale(0.5);
  transform: scale(0.5);
  -webkit-transform-origin: left top;
  transform-origin: left top;
}
</style>
 <script> 
console.log(typeof ('a'+1))
 </script> 
 </body> 
</html>

参考引用:
《移动前端开发之viewport的深入理解》

  • 0
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值