# 移动端1px的问题

在移动端web开发中,UI设计稿中设置边框为1像素,前端在开发过程中如果出现border:1px,测试会发现在某些机型上,1px会比较粗,即是较经典的 移动端1px像素问题。

  • 物理像素:移动设备出厂时,不同设备自带的不同像素,也称硬件像素;
  • 逻辑像素:即css中记录的像素。

在开发中,为什么移动端CSS里面写了1px,实际上看起来比1px粗;了解设备物理像素和逻辑像素的同学应该很容易理解,其实这两个px的含义其实是不一样的,UI设计师要求的1px是指设备的物理像素1px,而CSS里记录的像素是逻辑像素,它们之间存在一个比例关系,通常可以用 javascript 中的 window.devicePixelRatio 来获取,也可以用媒体查询的 -webkit-min-device-pixel-ratio 来获取。当然,比例多少与设备相关。

  1. 媒体查询利用设备像素比缩放,设置小数像素; 优点:简单,好理解 缺点:兼容性差,目前之余IOS8+才支持,在IOS7及其以下、安卓系统都是显示0px。(oppoR15X手机本地测试不是0px2020-03-31)

IOS8+下已经支持带小数的px值,media query 对应 devicePixelRatio 有个查询值 -webkit-min-device-pixel-ratio;

1.)css可以写成这样:

@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 }
}

2.)js 可以写成这样:

<body><div id="main" style="border: 1px solid #000000;"></div></body>
<script type="text/javascript">
    if (window.devicePixelRatio && devicePixelRatio >= 2) {
        var main = document.getElementById('main');
        main.style.border = '.5px solid #000000';
    }
</script>

二者任选其一;

  1. box-shadow
-webkit-box-shadow: inset 0px 1px 1px -1px rgba(0, 0, 0, 0.5);
  1. viewport + rem 该方案是对上述方案的优化,整体思路就是利用viewport + rem + js 动态的修改页面的缩放比例,实现小于1像素的显示。 缺点:以为缩放涉及全局的rem单位,比较适合新项目,对于老项目可能要涉及到比较多的改动。 在页面初始化时,在头部引入原始默认状态如下:
<meta name="viewport" id="WebViewport" content="initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
var viewport = document.querySelector("meta[name=viewport]")
if (window.devicePixelRatio == 1) {
    viewport.setAttribute('content', 'width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no')
} 
if (window.devicePixelRatio == 2) {
    viewport.setAttribute('content', 'width=device-width, initial-scale=0.5, maximum-scale=0.5, minimum-scale=0.5, user-scalable=no')
} 
if (window.devicePixelRatio == 3) {
    viewport.setAttribute('content', 'width=device-width, initial-scale=0.333333333, maximum-scale=0.333333333, minimum-scale=0.333333333, user-scalable=no')
} 
var docEl = document.documentElement;
var fontsize = 10 * (docEl.clientWidth / 320) + 'px';
docEl.style.fontSize = fontsize;
  1. transform: scale(0.5) 方案 - 推荐: 很灵活

实现方式

height:1px;
-webkit-transform: scaleY(0.5);
-webkit-transform-origin:0 0;
overflow: hidden;

优点

圆角无法实现,hack代码多,实现4条边框比较闹心

缺点

只能单独使用,如果嵌套,scale的作用也会对包含的元素产生,不想要的影响,所以此种方案配合:after和:before独立使用较多,比如画一个商品的边框四条线,容器的after和before可以画2条线,利用容器的父元素的after、before再画2条线。

.after-scale{
  position: relative;
}
.after-scale:after{
  content:"";
  position: absolute;
  bottom:0px;
  left:0px;
  right:0px;
  border-bottom:1px solid #c8c7cc;
  -webkit-transform:scaleY(.5);
  -webkit-transform-origin:0 0;
}

  1. @media+transform
/* 2倍屏 */
@media only screen and (-webkit-min-device-pixel-ratio: 2.0) {
    .border-bottom::after {
        -webkit-transform: scaleY(0.5);
        transform: scaleY(0.5);
    }
}
/* 3倍屏 */
@media only screen and (-webkit-min-device-pixel-ratio: 3.0) {
    .border-bottom::after {
        -webkit-transform: scaleY(0.33);
        transform: scaleY(0.33);
    }
}
最后更新: 4/9/2020, 10:43:01 AM