移动端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: "\0020";
    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 {
        width: 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 {
        width: 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

原文地址:https://www.cnblogs.com/Youngly/p/9322693.html

时间: 2024-08-26 17:42:53

移动端1像素边框问题与CSS媒体查询的相关文章

移动端1像素解决方法,根据媒体查询transform缩放

.borderOnePx{ position: relative; } .borderOnePx::after { content: ''; height:1px; background:#000; -webkit-transform: scaleY(0.5); -webkit-transform-origin:0 0; overflow: hidden; } /* 2倍屏 */ @media only screen and (-webkit-min-device-pixel-ratio: 2.

【H5开发基础】移动端1像素边框问题的解决方案

自从乔帮主提出retina屏以来.可练就了不少前端兄弟的像素眼,有强迫症的伙伴们日子可就煎熬了.为了画出真正的1像素边框,前端猿们也是受尽各浏览器的虐待了. 关于什么是移动端1像素边框问题,先上两张图,大家就明白了. 图1 图2 实现1PX边框的方法有很多,各有优缺点,比如通过背景图片实现.通过transform: scale(0.5)实现.本次实现的是通过VIEWPORT+rem实现的,优点是可以自适应已知的各类手机屏幕,且不存在其它方法存在的变颜色困难.圆角阴影失效问题.缺点嘛,这方法适全新

CSS 媒体查询 响应式

媒体查询 从 CSS 版本 2 开始,就可以通过媒体类型在 CSS 中获得媒体支持.如果您曾经使用过打印样式表,那么您可能已经使用过媒体类型.清单 1 展示了一个示例. 清单 1. 使用媒体类型 <link rel="stylesheet" type="text/css" href="site.css" media="screen" /> <link rel="stylesheet" ty

CSS媒体查询:菜鸟笔记

CSS媒体查询 媒体查询包含了一个媒体类型和至少一个使用如高度.宽度和颜色等媒体属性来限制样式表范围的表达式.CSS3加入的媒体查询使得无需修改内容便可以使样式应用于某些特定的设备范围. 语法 媒体查询包含了一个媒体类型和如css3规范中描述的包含了一个或多个表达式的媒体属性,这些媒体属性会被解析成真或假.如果媒体查询中的媒体类型与文档要展示的设备相符则查询结果为真,并且媒体查询中的所有表达式为真. <!--link元素中的css媒体查询--> <link rel="style

使用 CSS 媒体查询创建响应式网站

来自:http://www.ibm.com/developerworks/cn/web/wa-cssqueries/ 适用于所有屏幕大小的设计 固定宽度的静态网站很快被灵活的响应式设计所取代,该设计可以根据屏幕大小进行上扩和下扩.利用响应式设计,无论您采用什么设备或屏幕来访问网站,都可以呈现一个可用的界面.响应式设计可以响应各种屏幕大小,因此也成为了 “前瞻性” 的网站,屏幕将随着新的智能手机和平板电脑的问世而快速演变.实现响应式设计的主要途径是使用 CSS 媒体查询.在本文中,我们将了解如何将

CSS媒体查询总结

1媒体查询概念 一个媒体查询由一个可选的媒体类型和零个或多个使用媒体功能限制样式表范围的表达式组成, 例如 宽度,高度和颜色.在CSS3中添加的媒体查询,允许内容的呈现针对一个特定范围的输出设备而定制,而不必改变内容本身. 2媒体查询的两种引入方式 <!-- link元素中的CSS媒体查询 --> <link rel="stylesheet" media="(max-width: 800px)" href="example.css&quo

ie浏览器不兼容css媒体查询的解决办法

考虑到在不同分辨率下,网站页面依然能显示一致,除了通过js来控制,css媒体查询更为方便,而痛点在于ie8不支持. 我们可以通过respond.js库来解决,这个插件的原理很简单: 将head中所有外部引入的css文件路径取出来存储在一个数组中,遍历数组,并一个个发送AJAX请求,AJAX回调后,分析response中的media query的min-width和max-width语法,它仅仅支持min-width和max-width,分析出viewport变化区间对应相应的css块,页面初始化

巧妙使用CSS媒体查询(Media Queries)和JavaScript判断浏览器设备类型的好方法

有无数的理由要求我们在任何时候都应该知道用户是使用的什么设备浏览我们的网站——宽屏,普通屏,平板,手机?知道这些特征,我们web应用的CSS和JavaScript才能同步做相应的操作.在给Mozilla Developer Networks改版设计的过程中,我发现使用CSS媒体查询(media queries)虽然非常的有效,但有时,JavaScript却不能及时知道用户浏览设备的状态.浏览网站的用户使用的是桌面电脑,还是平板,还是手机?这对于CSS来说很容易,但CSS却无法将这些信息告诉Jav

css媒体查询:响应式网站

css媒体查询:响应式网站 媒体查询 包含了一个媒体类型和至少一个使用如宽度.高度和颜色等媒体属性来限制样式表范围的表达式.CSS3加入的媒体查询使得无需修改内容便可以使样式应用于某些特定的设备范围. 参考文章:https://developer.mozilla.org/zh-CN/docs/Web/Guide/CSS/Media_queries