zoukankan      html  css  js  c++  java
  • 移动端1像素边框问题

    学习中发现一个问题,设置一个div的底部边框为1px solid #000,实际表现却是边框线是模糊的,或者是大于1px的.原因是,不同手机的物理像素是不同的,首先,先说下,逻辑像素与物理像素,这两个虽然单位都是px,但是他们的含义是不一样的,UI设计师要求的1px是指设备的物理像素1px,而CSS里记录的像素是逻辑像素,它们之间是存在一个比例关系的,用Javascript中的window.devicePixelRatio来获取,也可以用媒体查询的-webkit-min-devicePixelRatio来获取.比例多少,与相应设备有关.不同的设备的话,物理像素不同,对应的设备像素比不同.比如说,iPhone的devicePixelRatio==2,而border-1 px描述的是设备独立像素,所以,border被放大到物理像素2px显示,在iPhone上就显示的比较粗啦.

      在移动端的开发中.常需要在html的header里添加如下一句话:

     <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">

    这句话,定义了本页面的viewport的宽度为设备宽度,初始缩放照与最大缩放值都为1,并禁止了用户缩放.向上篇博客所具体了这行代码就不赘述了,meta标签中常设置user-scalable也就是禁止用户缩放.如果可缩放的话,会造成显示上的变化,缩放一倍,逻辑像素所代表的物理像素也就缩放了一倍.所以,现在就应该明白为何1px变粗了,viewport的设置与屏幕物理分辨率是按比例而不是相同的,移动端window对象有个devicePixelRatio属性,它表示设备物理像素与CSS像素的比例,在retina屏的iphone手机上,这个值为2或3,CSS里面写的1px长度映射到物理像素上就有2px或者3px那么长了.

    那么,现在来讲述下解决方案.

    1.媒体查询利用设备像素比缩放,设置小数像素.

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

    缺点,对设备有所要求,小数像素目前兼容性较差.

    2.viewport+rem方案

    该方案的话是利用Javascript根据window.devicePixelRatio分别进行判断修改根节点的fontSize,其他元素以rem为单位.

    首先,在页面初始化时,在头部引入原始默认状态:

    <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"> 

    之后,就是js的动态修改缩放比和用rem根元素开实现字体大小的设置.这里再提示下,rem是只想对于根元素html的font-size,即只需要设置根元素的font-size,其他元素使用rem单位设置成相应的百分比即可.

     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;

    缺点而言,就是缩放的话涉及到全局的rem单位,比较适合新项目,老项目的不太建议,因为要涉及到较多的改动.

    3.设置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;
    }

    border-width的话,是指定边框的宽度,可以设定四个值,上下左右.border-image在该例中意为,距离图片上方2(无单位)裁剪边框图片作为上下边框,并展示在宽度为1像素的边框空间里,左右没有边框.

    缺点的话是,需要制作图片,圆角可能出现模糊.

    4.background-image渐变实现

    除了使用图片外,也可以用纯CSS来实现,百度糯米团就是采用的这种方式.

    .border {
          background-image:linear-gradient(180deg, red, red 50%, transparent 50%),
          linear-gradient(270deg, red, red 50%, transparent 50%),
          linear-gradient(0deg, red, red 50%, transparent 50%),
          linear-gradient(90deg, red, red 50%, transparent 50%);
          background-size: 100% 1px,1px 100% ,100% 1px, 1px 100%;
          background-repeat: no-repeat;
          background-position: top, right top,  bottom, left top;
          padding: 10px;
      }

    将原本一个物理像素的边框大小利用线性渐变分割成几个部分,实现小于1像素效果.linear-gradient指定线性渐变,接受大于等于三个参数,第一个为渐变旋转角度,第二个开始为渐变的颜色与到哪个位置(百分比)全部变为该颜色.以上述代码为例子,第一句即为,渐变方向旋转180°,即从上往下(注,默认为0度且从下往上),从红色开始渐变,到百分之五十的位置还是红色,再渐变为继承父元素颜色.

    缺点的话,就是由于每个边框都是线性渐变颜色实现,因此无法实现圆角.

    5.box-shadow方案

    利用阴影来实现代码如下:

    div{
    -webkit-box-shadow: 0 1px 1px -1px rgba(0,0,0,0.5);
    }

    box-shadow: h-shadow v-shadow [blur] [spread] [color] [inset]

    参数分别表示:水平阴影位置,垂直阴影位置,模糊距离,阴影尺寸,阴影颜色,将外部阴影被更改为内部阴影,后四个为可选元素.上述代码中,为何把阴影尺寸设置为负数呢?设置成-1px是为了让阴影尺寸小于div元素尺寸,这样左右两边的阴影就不会暴露出来,实现只有底部一边有阴影的效果,从而实现分割线效果.

    6.transform:scale(0.5)方案

    0.5px并不是所有的设备或浏览器都支持,前两个方案,媒体查询以及rem加viewport方案都使用了,实现0.5px,实际使用transform的话会更好.

    1).设置height:1px,根据媒体查询结合transform缩放为相应尺寸.

    div{
    height:1px;
    background:#000;
    -webkit-transform:scaleY(0.5);
    -webkit-transform-origin:0 0;
    overflow:hidden;}

    2).用::after设置border-bottom:1px solid #000,然后缩放-webkit-transform:scaleY(0.5);可以实现两根边线的需求.

    div::after{
        content:'';width:100%;
        border-bottom:1px solid #000;
        transform: scaleY(0.5);
    }

    3).或者我们使用tranfrom与方案一中的媒体查询的结合,来对方案1来进行优化

    /* 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);
        }
    }
  • 相关阅读:
    如何使用谷歌的网页删除请求工具?
    已有记录表添加特定排序主键ID
    用ASP实现超长内容的word模板替换objDoc.Content.Find.Execute
    内网SMTP发送失败的曲线救国之策
    IIS无法在后台生成WORD文件的故障
    WINDOWS2003进行WindowsFTP设置的一些注意事项
    解决IISASP调用XmlHTTP出现msxml3.dll (0x80070005) 拒绝访问的错误
    [转]Cate:我是如何准备Google面试的
    Ubuntu的启动配置文件grub.cfg(menu.lst)设置指南
    Linux启动过程详解
  • 原文地址:https://www.cnblogs.com/ljylearnsmore/p/14481037.html
Copyright © 2011-2022 走看看