移动端1px边框解决方案

前端开发
2022年04月27日
1341

移动端 1px 边框问题通用解决方案:scss mixin 版本

注意:本方案采用伪元素 + transform 的解决方案,在设置边框的元素有交互动作时,请设置子元素定位以及 z-index 值。

border.scss

css
@mixin genBorderRaidus ($radius: null, $ratio: 1) { @if ($radius != null) { @if (type-of($radius) == list) { border-radius: nth($radius, 1)*$ratio nth($radius, 2)*$ratio nth($radius, 3)*$ratio nth($radius, 4)*$ratio; } @else { border-radius: $radius*$ratio; } } } @mixin genBorderRules ($rule: width, $directions: null, $values: null) { // 默认 border-style 为 solid @if ($rule == style and $values == null) { $values: solid; } @if ($values != null) { // directions 为列表,分别设置 top/right/bottom/left 等位置的样式 @if (type-of($directions) == list) { $dirMap: ( top: 1, right: 2, bottom: 3, left: 4 ); @if (type-of($values) == list) { @each $dir in $directions { border-#{$dir}-#{$rule}: nth($values, map-get($dirMap, $dir)); } } @else { @each $dir in $directions { border-#{$dir}-#{$rule}: $values; } } } // dierections 为 null,默认为全边框 @else if ($directions == null) { @if (type-of($values) == list) { border-#{$rule}: nth($values, 1) nth($values, 2) nth($values, 3) nth($values, 4); } @else { border-#{$rule}: $values; } } // directions 其余情况为单边设置 @else { @if (type-of($values) == list) { border-#{$directions}-#{$rule}: nth($values, 1) nth($values, 2) nth($values, 3) nth($values, 4); } @else { border-#{$directions}-#{$rule}: $values; } } } } @mixin genBorder ( $directions: null, $style: solid, $color: null, $radius: null, $position: after ) { @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) { @include genBorderRules(width, $directions, 1px); @include genBorderRules(style, $directions, $style); @include genBorderRules(color, $directions, $color); @include genBorderRaidus($radius, 1); } @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) { & { position: relative; // 移除 border 采用伪类实现 border: 0; border-radius: 0; } &::#{$position} { content: ''; display: block; position: absolute; left: 0; top: 0; width: 200%; height: 200%; transform-origin: 0 0; transform: scale(0.5); @include genBorderRules(width, $directions, 1px); @include genBorderRules(style, $directions, $style); @include genBorderRules(color, $directions, $color); @include genBorderRaidus($radius, 2); } } @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) { & { position: relative; // 移除 border 采用伪类实现 border: 0; border-radius: 0; } &::#{$position} { content: ''; display: block; position: absolute; left: 0; top: 0; width: 300%; height: 300%; transform-origin: 0 0; transform: scale(0.33333); @include genBorderRules(width, $directions, 1px); @include genBorderRules(style, $directions, $style); @include genBorderRules(color, $directions, $color); @include genBorderRaidus($radius, 3); } } }

测试代码

index.html

html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no"> <title>1px border</title> <link rel="stylesheet" href="./index.scss" /> </head> <body> <div class="wrapper"> <div class="border"></div> <div class="border-left"></div> <div class="border-left-right"></div> <div class="border-top-right"></div> <div class="border-top-right-bottom"></div> <div class="border-left-right-radius-10"></div> <div class="border-tob-bottom-blue-radius-10"></div> <div class="border-blue"></div> <div class="border-dashed-red"></div> <div class="border-red-radius-10"></div> </div> </body> </html>

css

css
@import './border.scss'; .wrapper { display: flex; justify-content: center; align-items: center; flex-wrap: wrap; width: 100%; color: orange; > * { width: 50px; height: 50px; margin: 10px; background-color: #f8f8f8; } .border { @include genBorder(); } .border-left { @include genBorder(left); } .border-left-right { @include genBorder((left,right)); } .border-top-right { @include genBorder((top,right)); } .border-top-right-bottom { @include genBorder((top,right,bottom)) } .border-left-right-radius-10 { @include genBorder((left,right), solid, null, 10px) } .border-tob-bottom-blue-radius-10 { @include genBorder((top,bottom), solid, blue, 10px) } .border-blue { @include genBorder(null, solid, blue); } .border-dashed-red { @include genBorder(null, dashed, red); } .border-red-radius-10 { @include genBorder(null, solid, red, 10px); } }