css伪元素一像素问题,移动端1px问题解决方案

这是我第25篇简书。

一、产生原因

DPR(devicePixelRatio) 设备像素比 = 物理像素 / css像素 ,它是默认缩放为100%的屏幕下,设备像素和css像素的比值。

目前比较主流的设备的DPR=2或3,所以:

当我们的DPR为2,也就是2倍屏时,当物理像素(设备像素)为1px的时候,我们的css像素应该是0.5px。

当DPR=3,物理像素为1px时,css像素应该为1/3px。

而一般情况下,设计稿是按照750来设计的,而我们写css的样式是参考375的屏,所以我们写的css像素应该为设计稿的像素的一半。

设计图为1px,我们css像素应该为0.5px,再考虑到设备的像素比,我们写的css则是0.25px。

二、解决方案

(一)利用 css 的 伪元素::after + transfrom 进行缩放

优点:全机型兼容,实现了真正的1px,而且可以圆角。适用于老项目。

缺点:暂用了after 伪元素,可能影响清除浮动。

cell

.cell {

width: 100px;

height: 100px;

}

.border-1px:after {

content: '';

position: absolute;

box-sizing: border-box;

top: 0;

left: 0;

width: 200%;

height: 200%;

border: 1px solid #000;

border-radius: 4px;

-webkit-transform: scale(0.5);

transform: scale(0.5);

-webkit-transform-origin: top left;

}

.border-1px-top:before {

content: "";

position: absolute;

top: 0;

left: 0;

right: 0;

border-top: 1px solid red;

transform: scaleY(.5);

transform-origin: left top;

}

(二)设置viewport的scale值

优点:全机型兼容,直接写1px不能再方便。

缺点:适用于新的项目,老项目可能改动大。

1px question

html {

font-size: 1px;

}

* {

padding: 0;

margin: 0;

}

.top_b {

border-bottom: 1px solid #E5E5E5;

}

.a,.b {

box-sizing: border-box;

margin-top: 1rem;

padding: 1rem;

font-size: 1.4rem;

}

.a {

width: 100%;

}

.b {

background: #f5f5f5;

width: 100%;

}

var viewport = document.querySelector("meta[name=viewport]");

//下面是根据设备像素设置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.3333333333333333, maximum-scale=0.3333333333333333, minimum-scale=0.3333333333333333, user-scalable=no');

}

var docEl = document.documentElement;

var fontsize = 32* (docEl.clientWidth / 750) + 'px';

docEl.style.fontSize = fontsize;

下面的底边宽度是虚拟1像素的
上面的边框宽度是虚拟1像素的

(三)通过@media手写border

.min-device-pixel-ratio(@scale2, @scale3) {

@media screen and (min-device-pixel-ratio: 2), (-webkit-min-device-pixel-ratio: 2) {

transform: @scale2;

}

@media screen and (min-device-pixel-ratio: 3), (-webkit-min-device-pixel-ratio: 3) {

transform: @scale3;

}

}

.border-1px(@color: #DDD, @radius: 2PX, @style: solid) {

&::before {

content: "";

pointer-events: none;

display: block;

position: absolute;

left: 0;

top: 0;

transform-origin: 0 0;

border: 1PX @style @color;

border-radius: @radius;

box-sizing: border-box;

width: 100%;

height: 100%;

@media screen and (min-device-pixel-ratio: 2), (-webkit-min-device-pixel-ratio: 2) {

width: 200%;

height: 200%;

border-radius: @radius * 2;

transform: scale(.5);

}

@media screen and (min-device-pixel-ratio: 3), (-webkit-min-device-pixel-ratio: 3) {

width: 300%;

height: 300%;

border-radius: @radius * 3;

transform: scale(.33);

}

}

}

.border-top-1px(@color: #DDD, @style: solid) {

&::before {

content: "";

position: absolute;

left: 0;

top: 0;

width: 100%;

border-top: 1Px @style @color;

transform-origin: 0 0;

.min-device-pixel-ratio(scaleY(.5), scaleY(.33));

}

}

.border-bottom-1px(@color: #DDD, @style: solid) {

&::after {

content: "";

position: absolute;

left: 0;

bottom: 0;

width: 100%;

border-bottom: 1Px @style @color;

transform-origin: 0 0;

.min-device-pixel-ratio(scaleY(.5), scaleY(.33));

}

}

.border-left-1px(@color: #DDD, @style: solid) {

&::before {

content: "";

position: absolute;

left: 0;

top: 0;

height: 100%;

border-left: 1Px @style @color;

transform-origin: 0 0;

.min-device-pixel-ratio(scaleX(.5), scaleX(.33));

}

}

一般情况下,我们采用移动端新写的项目都采用viewport的scale方法来实现1px的边框,兼容性好。老项目的话建议还是采用伪元素加transform这种方式。

开源库的解决方案:

如果有用这些ui库,则不用考虑1px问题了。

(四)vant 组件库

.hairline-common() {

position: absolute;

box-sizing: border-box;

content: ' ';

pointer-events: none;

}

.hairline(@color: @border-color) {

.hairline-common();

top: -50%;

right: -50%;

bottom: -50%;

left: -50%;

border: 0 solid @color;

transform: scale(0.5);

}

(五)ant-design-mobile 组件库

这里 PX 大写,为了防止插件将 px 转成 rem 等单位:

.scale-hairline-common(@color, @top, @right, @bottom, @left) {

content: '';

position: absolute;

background-color: @color;

display: block;

z-index: 1;

top: @top;

right: @right;

bottom: @bottom;

left: @left;

}

.hairline(@direction, @color: @border-color-base) when (@direction = 'top') {

border-top: 1PX solid @color;

html:not([data-scale]) & {

@media (min-resolution: 2dppx) {

border-top: none;

&::before {

.scale-hairline-common(@color, 0, auto, auto, 0);

width: 100%;

height: 1PX;

transform-origin: 50% 50%;

transform: scaleY(0.5);

@media (min-resolution: 3dppx) {

transform: scaleY(0.33);

}

}

}

}

}

.hairline(@direction, @color: @border-color-base) when (@direction = 'right') {

border-right: 1PX solid @color;

html:not([data-scale]) & {

@media (min-resolution: 2dppx) {

border-right: none;

&::after {

.scale-hairline-common(@color, 0, 0, auto, auto);

width: 1PX;

height: 100%;

background: @color;

transform-origin: 100% 50%;

transform: scaleX(0.5);

@media (min-resolution: 3dppx) {

transform: scaleX(0.33);

}

}

}

}

}

.hairline(@direction, @color: @border-color-base) when (@direction = 'bottom') {

border-bottom: 1PX solid @color;

html:not([data-scale]) & {

@media (min-resolution: 2dppx) {

border-bottom: none;

&::after {

.scale-hairline-common(@color, auto, auto, 0, 0);

width: 100%;

height: 1PX;

transform-origin: 50% 100%;

transform: scaleY(0.5);

@media (min-resolution: 3dppx) {

transform: scaleY(0.33);

}

}

}

}

}

.hairline(@direction, @color: @border-color-base) when (@direction = 'left') {

border-left: 1PX solid @color;

html:not([data-scale]) & {

@media (min-resolution: 2dppx) {

border-left: none;

&::before {

.scale-hairline-common(@color, 0, auto, auto, 0);

width: 1PX;

height: 100%;

transform-origin: 100% 50%;

transform: scaleX(0.5);

@media (min-resolution: 3dppx) {

transform: scaleX(0.33);

}

}

}

}

}

.hairline(@direction, @color: @border-color-base, @radius: 0) when (@direction = 'all') {

border: 1PX solid @color;

border-radius: @radius;

html:not([data-scale]) & {

@media (min-resolution: 2dppx) {

position: relative;

border: none;

&::before {

content: '';

position: absolute;

left: 0;

top: 0;

width: 200%;

height: 200%;

border: 1PX solid @color;

border-radius: @radius * 2;

transform-origin: 0 0;

transform: scale(0.5);

box-sizing: border-box;

pointer-events: none;

// @media (min-resolution: 3dppx) {

// width: 300%;

// height: 300%;

// border-radius: @radius * 3;

// transform: scale(0.33);

// }

}

}

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值