导致原因
在PC端,CSS的1px一般对应着电脑屏幕的1个物理像素,但在移动端,CSS的1px等于
几个物理像素是和屏幕像素密度有关的。由于不同的手机有不同的像素密度,如
果移动显示屏的分辨率始终是普通屏幕的2倍,那1px 的边框在 设备像像素比(dpr)为 2
的移动屏下会显示成 2px,所以在高清屏下看着1px总是感觉更粗
这里涉及到几个概念:
- 物理像素:也被称为设备物理像素,显示屏上最小的物理显示单元(像素颗粒)
- 设备独立像素:也被称为CSS像素,这个点代表一个可以由程序使用的虚拟像素, 有时也说是逻辑像素,然后由相关系统转换为物理像素
- 设备像素比(dpr) = 物理像素 / 设备独立像素(px)
解决办法
-
当设备像素比为 2 时,使用 0.5px
优点:简单 缺点:但是并不是所有手机浏览器都能识别到 border: 0.5px
-
伪类 + transform 实现: 把原生元素的border去掉,然后用:before或者:after重做border,并且使用transform 的 scale 属性缩小一半,原先的元素相对定位,新做的border绝对定位
优点: 所有场景都能满足,支持圆角 缺点: 对于已经使用伪类的元素,可能需要多层嵌套
.element { position: relative; border: none; } // 下边框 .element:after { content: ""; position: absolute; bottom: 0; left: 0; background: steelblue; transform: scaleY(.5); }
-
viewport + rem 实现
优点: 这种兼容方案相比比较完美,所有场景都能满足,一套代码,可以兼容基本所有布局 缺点: 适合新的项目,老的项目修改成本过大
function resetRemUnit(){ // 获得设备像素比 var radio = window.devicePixelRatio; // 处理设备像素比,只能是1,2,3 radio = radio >= 3 ? 3 : (radio >= 2 ? 2 : 1); // 判断是否有meta标签 var viewportDOM = document.querySelector('meta[name=viewport]'); if(!viewportDOM){ viewportDOM = document.createElement('meta'); viewportDOM.setAttribute('name', 'viewport'); } // 计算页面缩放比例 var scale = 1 / radio; var content = 'width=device-width, initial-scale='+scale+', maximum-scale='+scale+', minimum-scale='+scale+', user-scalable=no'; viewportDOM.setAttribute('content', content); // 添加meta标签 document.head.appendChild(viewportDOM); // 控制计算rem的最大最小适配页面 var min = 320 * radio; var max = 540 * radio; var width = document.documentElement.clientWidth || window.innerWidth || document.documentElement.getBoundingClientRect().width; if(width < min){ width = min; }else if(width > max){ width = max; } // 计算rem document.documentElement.style.fontSize = (width * 100 / 640) + 'px'; } resetRemUnit(); window.onresize = resetRemUnit;
-
使用 box-shadow模拟边框
利用 css 对阴影处理的方式实现0.5px 的效果 优点: 代码量少,可以满足所有场景 缺点: 边框有阴影,颜色变浅
.element { box-shadow: inset 0px -1px 1px -1px steelblue; }
-
媒体查询 + transform 实现
/* 2倍屏 */ @media only screen and (-webkit-min-device-pixel-ratio: 2) { .border-bottom::after { -webkit-transform: scaleY(0.5); transform: scaleY(0.5); } }