• 移动端1像素边框问题与CSS媒体查询


    做移动端页面开发时,我们是按照UI设计图上的尺寸来做的。

    比如说,UI给的图是750x1344(Iphone6标准),我们在浏览器做适配时,按照375x667来裁切,设计图上30像素的高度,开发时使用的是15px,这是因为Iphone6的设备像素比为2,css中的1px在设备中的像素为2px。当我们需要实现设计图中1px高度的边框时,在css中的1px实际上变成了2px边框,由此产生了1像素边框问题。

    1、window.devicePixelRatio设备像素比

    定义:

    window.devicePixelRatio是设备上物理像素和设备独立像素(device-independent pixels (dips))的比例。
    公式表示就是:window.devicePixelRatio = 物理像素 / dips

    引用自张鑫旭大神的文档

    用于描述整个渲染环境在硬件设备上的缩放程度,在程序中可以通过window.devicePixelRatio属性来得到这个值。

    与之相关的概念如下:

    物理像素(physical pixel):设备能控制显示的最小单位。
    设备独立像素(DIP,device-independent pixel,density-independent pixel):独立于设备的用于逻辑上衡量像素的单位。
    每英寸像素量(PPI,pixels per inch):一英寸长度上可以并排的像素数量。

    正常人眼可以识别的分辨率为300PPI,而现在很多设备的分辨率都超过了300PPI。如果设备总是以满分辨率来显示东西就可能造成文字太小,人们看不清。因此像浏览器这样的软件就会对内容做一次放大后再进行渲染,也就是降低分辨率。要降低分辨率就需要让像素这个单位变大,因此PPI的计算不再使用物理像素,而改用设备独立像素。那么设备独立像素和物理像素之间就存在一个比例差异,这就是设备像素比。
    单位dppx(dots per pixel)表示每个DIP占用几个物理像素。可以理解为,CSS中的单位px在屏幕上占用了多少物理像素。

    引用自https://www.web-tinker.com/article/20590.html

     2、常用解决方案

    2-1、border.css方案

    在添加border样式的元素上设置:before和:after样式,然后在媒体查询中根据device-pixel-ratio的值来缩放对应宽度和高度,来达到边框大小为物理像素1px

    @charset "utf-8";
    .border,
    .border-top,
    .border-right,
    .border-bottom,
    .border-left,
    .border-topbottom,
    .border-rightleft,
    .border-topleft,
    .border-rightbottom,
    .border-topright,
    .border-bottomleft {
        position: relative;
    }
    .border::before,
    .border-top::before,
    .border-right::before,
    .border-bottom::before,
    .border-left::before,
    .border-topbottom::before,
    .border-topbottom::after,
    .border-rightleft::before,
    .border-rightleft::after,
    .border-topleft::before,
    .border-topleft::after,
    .border-rightbottom::before,
    .border-rightbottom::after,
    .border-topright::before,
    .border-topright::after,
    .border-bottomleft::before,
    .border-bottomleft::after {
        content: "020";
        overflow: hidden;
        position: absolute;
    }
    /* border
     * 因,边框是由伪元素区域遮盖在父级
     * 故,子级若有交互,需要对子级设置
     * 定位 及 z轴
     */
    .border::before {
        box-sizing: border-box;
        top: 0;
        left: 0;
        height: 100%;
        width: 100%;
        border: 1px solid #eaeaea;
        transform-origin: 0 0;
    }
    .border-top::before,
    .border-bottom::before,
    .border-topbottom::before,
    .border-topbottom::after,
    .border-topleft::before,
    .border-rightbottom::after,
    .border-topright::before,
    .border-bottomleft::before {
        left: 0;
        width: 100%;
        height: 1px;
    }
    .border-right::before,
    .border-left::before,
    .border-rightleft::before,
    .border-rightleft::after,
    .border-topleft::after,
    .border-rightbottom::before,
    .border-topright::after,
    .border-bottomleft::after {
        top: 0;
        width: 1px;
        height: 100%;
    }
    .border-top::before,
    .border-topbottom::before,
    .border-topleft::before,
    .border-topright::before {
        border-top: 1px solid #eaeaea;
        transform-origin: 0 0;
    }
    .border-right::before,
    .border-rightbottom::before,
    .border-rightleft::before,
    .border-topright::after {
        border-right: 1px solid #eaeaea;
        transform-origin: 100% 0;
    }
    .border-bottom::before,
    .border-topbottom::after,
    .border-rightbottom::after,
    .border-bottomleft::before {
        border-bottom: 1px solid #eaeaea;
        transform-origin: 0 100%;
    }
    .border-left::before,
    .border-topleft::after,
    .border-rightleft::after,
    .border-bottomleft::after {
        border-left: 1px solid #eaeaea;
        transform-origin: 0 0;
    }
    .border-top::before,
    .border-topbottom::before,
    .border-topleft::before,
    .border-topright::before {
        top: 0;
    }
    .border-right::before,
    .border-rightleft::after,
    .border-rightbottom::before,
    .border-topright::after {
        right: 0;
    }
    .border-bottom::before,
    .border-topbottom::after,
    .border-rightbottom::after,
    .border-bottomleft::after {
        bottom: 0;
    }
    .border-left::before,
    .border-rightleft::before,
    .border-topleft::after,
    .border-bottomleft::before {
        left: 0;
    }
    @media (max--moz-device-pixel-ratio: 1.49), (-webkit-max-device-pixel-ratio: 1.49), (max-device-pixel-ratio: 1.49), (max-resolution: 143dpi), (max-resolution: 1.49dppx) {
        /* 默认值,无需重置 */
    }
    @media (min--moz-device-pixel-ratio: 1.5) and (max--moz-device-pixel-ratio: 2.49), (-webkit-min-device-pixel-ratio: 1.5) and (-webkit-max-device-pixel-ratio: 2.49), (min-device-pixel-ratio: 1.5) and (max-device-pixel-ratio: 2.49), (min-resolution: 144dpi) and (max-resolution: 239dpi), (min-resolution: 1.5dppx) and (max-resolution: 2.49dppx) {
        .border::before {
             200%;
            height: 200%;
            transform: scale(.5);
        }
        .border-top::before,
        .border-bottom::before,
        .border-topbottom::before,
        .border-topbottom::after,
        .border-topleft::before,
        .border-rightbottom::after,
        .border-topright::before,
        .border-bottomleft::before {
            transform: scaleY(.5);
        }
        .border-right::before,
        .border-left::before,
        .border-rightleft::before,
        .border-rightleft::after,
        .border-topleft::after,
        .border-rightbottom::before,
        .border-topright::after,
        .border-bottomleft::after {
            transform: scaleX(.5);
        }
    }
    @media (min--moz-device-pixel-ratio: 2.5), (-webkit-min-device-pixel-ratio: 2.5), (min-device-pixel-ratio: 2.5), (min-resolution: 240dpi), (min-resolution: 2.5dppx) {
        .border::before {
             300%;
            height: 300%;
            transform: scale(.33333);
        }
        .border-top::before,
        .border-bottom::before,
        .border-topbottom::before,
        .border-topbottom::after,
        .border-topleft::before,
        .border-rightbottom::after,
        .border-topright::before,
        .border-bottomleft::before {
            transform: scaleY(.33333);
        }
        .border-right::before,
        .border-left::before,
        .border-rightleft::before,
        .border-rightleft::after,
        .border-topleft::after,
        .border-rightbottom::before,
        .border-topright::after,
        .border-bottomleft::after {
            transform: scaleX(.33333);
        }
    }

    2-2、 lib-flexible.js-淘宝移动端方案

    根据当前设备的window.devicePixelRatio,来设置viewport中的缩放比例,以达到设备物理像素=css像素

    if (!dpr && !scale) {
        var isAndroid = win.navigator.appVersion.match(/android/gi);
        var isIPhone = win.navigator.appVersion.match(/iphone/gi);
        var devicePixelRatio = win.devicePixelRatio;
        if (isIPhone) {
            // iOS下,对于2和3的屏,用2倍的方案,其余的用1倍方案
            if (devicePixelRatio >= 3 && (!dpr || dpr >= 3)) {                
                dpr = 3;
            } else if (devicePixelRatio >= 2 && (!dpr || dpr >= 2)){
                dpr = 2;
            } else {
                dpr = 1;
            }
        } else {
            // 其他设备下,仍旧使用1倍的方案
            dpr = 1;
        }
        scale = 1 / dpr;
    }
    ......
    var metaEl = doc.createElement('meta');
    var scale = isRetina ? 0.5:1;
    metaEl.setAttribute('name', 'viewport');
    metaEl.setAttribute('content', 'initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no');
    if (docEl.firstElementChild) {
        document.documentElement.firstElementChild.appendChild(metaEl);
    } else {
        var wrap = doc.createElement('div');
        wrap.appendChild(metaEl);
        documen.write(wrap.innerHTML);
    }

    引用https://www.w3cplus.com/mobile/lib-flexible-for-html5-layout.html

    3、用到的css媒体查询

    @media (max--moz-device-pixel-ratio: 1.49),
         (-webkit-max-device-pixel-ratio: 1.49),
         (max-device-pixel-ratio: 1.49), 
        (max-resolution: 143dpi), 
        (max-resolution: 1.49dppx)
    max-device-pixel-ratio:设备像素比
    max--moz-device-pixel-ratio:可以用于兼容版本号低于16的Firefox浏览器
    -webkit-max-device-pixel-ratio:基于webkit的浏览器不支持dppx
    max-resolution:指定输出设备的分辨率(像素密度),可替换老旧的 (max-device-pixel-ratio: 2)。分辨率可以用每英寸(dpi)或每厘米(dpcm)的点数来表示。此处表示最大分辨率
    @media (-webkit-min-device-pixel-ratio: 2), /* Webkit-based browsers */
           (min--moz-device-pixel-ratio: 2),    /* Older Firefox browsers (prior to Firefox 16) */
           (min-resolution: 2dppx),             /* The standard way */
           (min-resolution: 192dpi)             /* dppx fallback */

    引用https://developer.mozilla.org/zh-CN/docs/Web/Guide/CSS/Media_queries

     

  • 相关阅读:
    back-不忘初心,方得始终。讲讲我主场3个月的经历。题外话。
    js中event事件对象的兼容问题以及坐标属性-(clientX clientY;pageX,pageY,offsetX,offsetY)
    布局(左边的div随着右边div的高度变化而变化)
    事件委托如何实现的原理
    寄生组合式继承方法的实现以及原理总结
    封装判断一个字符的后缀名和前缀的方法
    经典的面试题如果不通过其他任何变量实现两个数值类型的变量互相更换值。
    【十次方基础教程(后台)】Dockerfile脚本完成镜像的构建
    【十次方基础教程(后台)】安装并启动RabbitMQ
    【十次方基础教程(后台)】docker下安装head插件来进行Elasticsearch的操作
  • 原文地址:https://www.cnblogs.com/Youngly/p/9322693.html
Copyright © 2020-2023  润新知