移动端问题解析

276 阅读2分钟

产生原因:

主要是跟一个东西有关,DPR(devicePixelRatio) 设备像素比,它是默认缩放为100%的情况下,设备像素和CSS像素的比值。

window.devicePixelRatio=物理像素 /CSS像素

非视网膜像素屏幕上,屏幕物理像素320像素,独立像素也是320像素,因此,window.devicePixelRatio等于1。

在视网膜屏幕的iphone上,屏幕物理像素640像素,独立像素还是320像素,因此,window.devicePixelRatio等于2.

目前主流的屏幕DPR=2 (iPhone 8),或者3 (iPhone 8 Plus)。拿2倍屏来说,设备的物理像素要实现1像素,而DPR=2,所以css 像素只能是 0.5。一般设计稿是按照750来设计的,它上面的1px是以750来参照的,而我们写css样式是以设备375为参照的,所以我们应该写的0.5px就好了啊! 试过了就知道,iOS 8+系统支持,安卓系统不支持。

场景:高分屏上会把1px宽的边框显示程2px,在dpr为3的设备上,显示边框为3px

解决方案:

  • 边框的图片,border-image

.border-image-1px {
    border-width: 1px 0px;
    -webkit-border-image: url(border.png) 2 0 stretch;
    border-image: url(border.png) 2 0 stretch;
}
  • 背景图片

设置1px的渐变背景,50%有颜色,50%透明

.border {
    background:
    linear-gradient(180deg, black, black 50%, transparent 50%) top    left  / 100% 1px no-repeat,
    linear-gradient(90deg,  black, black 50%, transparent 50%) top    right / 1px 100% no-repeat,
    linear-gradient(0,      black, black 50%, transparent 50%) bottom right / 100% 1px no-repeat,
    linear-gradient(-90deg, black, black 50%, transparent 50%) bottom left  / 1px 100% no-repeat;
}
  • 边框的阴影
.shadow {
        -webkit-box-shadow:0 1px 1px -1px rgba(255, 0, 0, 0.5);
	box-shadow:0 1px 1px -1px rgba(255, 0, 0, 0.5);
}
  • 设置viewport的meta属性(不建议使用)

推荐方案:

1:transform:scale(0.5)

核心思想:使用transform的scale来整体缩放,把原先元素的 border 去掉,然后利用 :before 或者 :after 重做 border ,并 transform 的 scale 缩小一半,原先的元素相对定位,新做的 border 绝对定位。

单条border样式设置:


.scale-1px{
   position: relative;
   border:none;
 } 
.scale-1px:after{
 content: '';
 position: absolute; 
 bottom: 0; 
 background: #000; 
 width: 100%; 
 height: 1px;
 -webkit-transform: scaleY(0.5); 
 transform: scaleY(0.5); 
 -webkit-transform-origin: 0 0; 
 transform-origin: 0 0; 
}

四条border样式设置:


.scale-1px{ 
position: relative; 
margin-bottom: 20px; border:none;
} 
.scale-1px: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; 
}

结合js来代码来判断是否是Retina屏:

if(window.devicePixelRatio && devicePixelRatio >= 2){
	 document.querySelector('div').className = 'scale-1px';
}

2:viewport+rem实现

<span style="font-size:18px;"><html>  
  
    <head>  
        <title>1px question</title>  
        <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">  
        <meta name="viewport" id="WebViewport" content="initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">       
        <style>  
            html {  
                font-size: 1px;  
            }             
            * {  
                padding: 0;  
                margin: 0;  
            }  
              
            .bds_b {  
                border-bottom: 1px solid #ccc;  
            }  
              
            .a,  
            .b {  
                margin-top: 1rem;  
                padding: 1rem;                
                font-size: 1.4rem;  
            }  
              
            .a {  
                width: 30rem;  
            }  
              
            .b {  
                background: #f5f5f5;  
                width: 20rem;  
            }  
        </style>  
        <script>  
          
            var viewport = document.querySelector("meta[name=viewport]");  
            //下面是根据设备像素设置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.3333333333333333, maximum-scale=0.3333333333333333, minimum-scale=0.3333333333333333, user-scalable=no');  
            }  
            var docEl = document.documentElement;  
            var fontsize = 10 * (docEl.clientWidth / 320) + 'px';  
            docEl.style.fontSize = fontsize;  
              
        </script>  
    </head>  
  
    <body>  
        <div class="bds_b a">下面的底边宽度是虚拟1像素的</div>  
        <div class="b">上面的边框宽度是虚拟1像素的</div>  
    </body>  
  
</html></span>