移动端1px产生原因及解决方案
在retina
屏中,像素比为2
(iPhone6/7/8
)或3
(iPhone6Plus/7Plus/8Plus
),1px
的边框看起来比真的1px
更宽。
本文默认你已经对视口、物理像素、逻辑像素、设备像素比、css像素等移动端基本概念已经解。
产生原因
- 设备像素比:
dpr
=window.devicePixelRatio
= 物理像素 / 逻辑像素。 - 在
retina
屏的手机上,dpr
为2
或3
,css
里写的1px
宽度映射到物理像素上就有2px
或3px
那么宽。 - 如
iPhone6
的dpr
为2
,物理像素750
(x轴),则它的逻辑像素为375
。 也就是说,1个逻辑像素,在x
轴和y
轴方向,需要2个物理像素来显示,即:dpr=2时,表示1个CSS像素由4个物理像素点组成,如下图:
需要给.tab添加1px的底部边框
<div> <!-- 头部 --> <v-headers></v-headers> <div class="tab border-1px-bottom"> <div class="tab-item"> <router-link to='/goods'>商品</router-link> </div> <div class="tab-item"> <router-link to='/ratings'>评论</router-link> </div> <div class="tab-item"> <router-link to='/sellers'>商家</router-link> </div> </div> <!-- 路由组件显示 --> <router-view></router-view> <div class="footer">我是尾部</div> </div>
在vue项目中解决方式
我们在assets公共资源文件夹中新建stylus, 新建mixin.stylus, 利用伪类编写1px的边框, 并且对不同的设备像素比进行适配
// 伪类+transform // 原理:把原先元素的border去掉,然后利用:before或者:after重做border,并 transform的scale缩小一半, // 原先的元素相对定位,新做的border绝对定位。 $color = blue .border-1px-bottom, .border-1px-top,.border-1px-left,.border-1px-right position: relative // 边框一像素,利用伪类设置一像素 .border-1px::after content: ""; box-sizing: border-box; position: absolute; left: 0; top: 0; width: 100%; height: 100%; border: 1px solid $color // 下边框 .border-1px-bottom::after position :absolute left: 0 bottom: 0 width: 100% border-bottom: 1px solid $color content: ' ' // 上边框 .border-1px-top::before position :absolute left: 0 top: 0 width: 100% border-top: 1px solid $color content: ' ' // 左边框 .border-1px-left::before position :absolute left: 0 top: 0 height: 100% border-left: 1px solid $color content: ' ' // 右边框 .border-1px-right::after position :absolute right: 0 top: 0 height: 100% border-right: 1px solid $color content: ' ' /*设备像素比*/ /*显示屏最小dpr为1.5*/ @media (-webkit-min-device-pixel-ratio: 1.5),(min-device-pixel-ratio: 1.5) .border-1px-bottom::after,.border-1px-top::before // Y轴压缩0.7, 1.5*0.7 约等于1 -webkit-transform: scaleY(0.7) transform: scaleY(0.7) .border-1px-left::before,.border-1px-right::after // X轴压缩0.7, 1.5*0.7 约等于1 -webkit-transform: scaleX(0.7) transform: scalexX(0.7) .border-1px::after width: 150%; height: 150%; transform: scale(0.7); transform-origin: 0 0; @media (-webkit-min-device-pixel-ratio: 2),(min-device-pixel-ratio: 2) .border-1px-bottom::after,.border-1px-top::before // Y轴压缩0.5, 2*0.5 等于1 -webkit-transform: scaleY(0.5) transform: scaleY(0.5) .border-1px-left::before,.border-1px-right::after // X轴压缩0.5, 2*0.5 等于1 -webkit-transform: scaleX(0.5) transform: scaleX(0.5) .border-1px::after width: 200%; height: 200%; transform: scale(0.5); transform-origin: 0 0; @media (-webkit-min-device-pixel-ratio: 3),(min-device-pixel-ratio: 3) .border-1px-bottom::after,.border-1px-top::before -webkit-transform: scaleY(0.333) transform: scaleY(0.5) .border-1px-left::before,.border-1px-right::after -webkit-transform: scaleX(0.333) transform: scaleX(0.333) .border-1px::after width: 300%; height: 300%; transform: scale(0.333); transform-origin: 0 0;
// 去除边框 //
border-none()
&:after
display: none
然后在vue组件中的样式中引入
@import './assets/stylus/mixin.stylus'
在.tab的div中,添加border-1px-bottom类名即可
<div class="tab border-1px-bottom">
如果要清除边框,在样式中调用该函数
.info-item padding: 16px 12px line-height: 16px font-size: 12px &:last-child border-none()