移动端1px像素问题

1px 问题

border-image

需要单独准备图片,而且圆角不是很好处理,但是可以应对大部分场景。

基于 media查询判断不同的设备像素比给定不同的 border-image:

.border_1px {
  border-bottom: 1px solid #000;
}
@media only screen and (-webkit-min-device-pixel-ratio: 2) {
  .border_1px {
    border-bottom: none;
    border-width: 0 0 1px 0;
    border-image: url(../img/1pxline.png) 0020 stretch;
  }
}

background-image

需要单独准备图片,而且圆角不是很好处理,但是可以应对大部分场景。

和 border-image类似,准备一张符合条件的边框背景图,模拟在背景上。

.border_1px {
  border-bottom: 1px solid #000;
}
@media only screen and (-webkit-min-device-pixel-ratio: 2) {
  .border_1px {
    background: url(../img/1pxline.png) repeat-x left bottom;
    background-size: 100% 1px;
  }
}

svg

借助 PostCSS的 postcss-write-svg我们能直接使用 border-image和 background-image创建 svg的 1px边框:

@svg border_1px {
    height: 2px;
    @rect {
        fill: var(--color, black);
        width: 100%;
        height: 50%;
    }
}

.example {
    border: 1px solid transparent;
    border-image: svg(border_1px param(--color #00b1ff)) 2 2 stretch; 
}

伪类 + transform

基于 media查询判断不同的设备像素比对线条进行缩放:

.border_1px:before {
  content: '';
  position: absolute;
  top: 0;
  height: 1px;
  width: 100%;
  background-color: #000;
  transform-origin: 50% 0%;
}
@media only screen and (-webkit-min-device-pixel-ratio: 2) {
  .border_1px:before {
    transform: scaleY(0.5);
  }
}
@media only screen and (-webkit-min-device-pixel-ratio: 3) {
  .border_1px:before {
    transform: scaleY(0.33);
  }
}

伪类 + transform(升级版)

原理:

  1. 主要是通过给目标元素添加position:relative;
  2. 然后再用其伪类:after或者:before画一个2倍或者3倍宽高的元素;
  3. 然后给伪类元素画一个1px的边框;
  4. 通过media query决定缩放伪类元素到1/2或者1/3;
  5. 给伪类元素增加pointer-events: none;, 这样伪类元素可以点击穿透, 也就是能看到, 但是不触发任何默认事件(click等);
封装

经过 scss 封装后:

@mixin thinBorder($directionMaps: bottom, $color: #ccc, $radius:(0, 0, 0, 0), $position: after)
  • $directionMaps: 是个list类型可以传入多个方向, 也就是可以生成多个防线边框, 默认值为bottom, 你可以根据需要传入(top, left, bottom, right) 4个方向;
  • $color: 边框的颜色, 默认#ccc;
  • $radius: 圆角半径, 默认0;
  • $position是一个高级设置, 一般都不需要改动, 由于细边框的实现使用了css的伪类, 所以为了规避可能出现的样式冲突, 我们可以自己指定使用:after还是:before, 默认after;
@mixin thinBorder($directionMaps: bottom, $color: #ccc, $radius:(0, 0, 0, 0), $position: after) {
    // 是否只有一个方向
    $isOnlyOneDir: string==type-of($directionMaps);

    @if ($isOnlyOneDir) {
        $directionMaps: ($directionMaps);
    }

    @each $directionMap in $directionMaps {
        border-#{$directionMap}: 1px solid $color;
    }

    // 判断圆角是list还是number
    @if(list==type-of($radius)) {
        border-radius: nth($radius, 1) nth($radius, 2) nth($radius, 3) nth($radius, 4);
    }

    @else {
        border-radius: $radius;
    }

    @media only screen and (-webkit-min-device-pixel-ratio: 2) {
        & {
            position: relative;

            // 删除1像素密度比下的边框
            @each $directionMap in $directionMaps {
                border-#{$directionMap}: none;
            }
        }

        &:#{$position} {
            content: "";
            position: absolute;
            top: 0;
            left: 0;
            display: block;
            width: 200%;
            height: 200%;
            transform: scale(0.5);
            box-sizing: border-box;
            padding: 1px;
            transform-origin: 0 0;
            pointer-events: none;
            border: 0 solid $color;

            @each $directionMap in $directionMaps {
                border-#{$directionMap}-width: 1px;
            }

            // 判断圆角是list还是number
            @if(list==type-of($radius)) {
                border-radius: nth($radius, 1)*2 nth($radius, 2)*2 nth($radius, 3)*2 nth($radius, 4)*2;
            }

            @else {
                border-radius: $radius*2;
            }

        }
    }

    @media only screen and (-webkit-min-device-pixel-ratio: 3) {
        &:#{$position} {

            // 判断圆角是list还是number
            @if(list==type-of($radius)) {
                border-radius: nth($radius, 1)*3 nth($radius, 2)*3 nth($radius, 3)*3 nth($radius, 4)*3;
            }

            @else {
                border-radius: $radius*3;
            }

            width: 300%;
            height: 300%;
            transform: scale(0.3333);
        }
    }
}
使用
  • 单侧边框
    @each $dir in (top,right,bottom,left) {
        .border-#{$dir}-#{1}px {
            @include thinBorder( $dir);
        }
    }
    
  • 多侧边框
    .border-top-left-red-1px{
        @include thinBorder((top,left), red);
    }
    
  • 圆角边框
    .border-top-left-red-1px{
        @include thinBorder(top, red, 100px);
    }
    
  • 使用:before去生成边框
    .border-top-before{
        @include thinBorder(top, red, 0, before);
    }
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
移动开发中,实现1像的效果是为了解决高分辨率屏幕下的线条模糊或者过粗的问题。下面是一些常见的实现方式: 1. 使用 CSS3 的 transform 进行缩放:可以使用 `scale` 属性将元缩放到所需的大小,例如 `scale(0.5)` 即为缩放到原来的一半大小。然后再将元的实际大小设置为 2 像,这样在高分辨率屏幕上显示时,就会以 1 像的精度显示。 2. 使用 viewport 的 meta 标签:在 HTML 文件的头部添加如下 meta 标签,可以将屏幕的物理像与 CSS 像进行等比缩放匹配,从而实现1像的效果。 ```html <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no"> ``` 3. 使用 CSS3 的 border-image:可以使用 `border-image` 属性为元的边框设置一张1像的图片作为边框样式,从而实现1像的效果。例如: ```css .border-1px { border-width: 1px; border-style: solid; border-image: url(border.png) 2 repeat; } ``` 4. 使用 CSS3 的伪类和 transform 进行缩放:可以使用 `::after` 伪类为元添加一个宽度为1像的伪元,然后使用 `scale` 属性将其缩放到所需的大小。例如: ```css .border-1px::after { content: ''; display: block; width: 200%; height: 1px; background: #000; transform: scale(0.5); transform-origin: top left; } ``` 这些方法都可以用来实现移动的1像效果,具体选择哪种方法,可以根据实际情况和需求来决定。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值