相关源码: https://github.com/any86/5a.c...
什么是"真.1px边框"?
由于现在手机都是"高密度屏幕", 我们写的1px到了手机上会用2/3个物理像素点去显示, 这样1px
边框看起来就会比较粗, 所以如果你也觉得自己的1px边框比较粗, 那么请往下看.
================ 注意 ================
截图因为放大了可能不明显, 你可以用手机打开这2个网址对比效果非常明显:
================ 注意 ================
1种"万金油"的解决办法
其实如果你百度"1px边框"会有很多文章, 大部分都会说有7种方法, 不过其实经过我的测试, 其实我们只要会其中1种就够了, 下面就介绍下这个"万金油"的方法.
先说下原理
- 主要是通过给目标元素添加
position:relative
; - 然后再用其伪类
:after
或者:before
画一个2倍或者3倍宽高的元素; - 然后给伪类元素画一个1px的边框;
- 通过
media query
决定缩放伪类元素到1/2或者1/3; - 给伪类元素增加
pointer-events: none;
, 这样伪类元素可以点击穿透, 也就是能看到, 但是不触发任何默认事件(click等);
代码
函数签名
为了使用方便, 我把他封装成了scss的mixin.
@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.33);
}
}
}
使用
单侧边框
生成.border-top-1px
等4个单侧边框;
@each $dir in (top,right,bottom,left) {
.border-#{$dir}-#{1}px {
@include thinBorder( $dir);
}
}
多侧边框
生成"红色"的多侧边框.border-top-left-red-1px
.border-top-left-red-1px{
@include thinBorder((top,left), red);
}
圆角边框
生成带100px圆角的边框 .border-top-left-round-1px
.border-top-left-red-1px{
@include thinBorder(top, red, 100px);
}
使用:before
去生成边框
.border-top-before{
@include thinBorder(top, red, 0, before);
}
ios支持小数像素
其实ios8及其以上是支持小数像素的, 也可以实现细边框, 比如border-width:0.5px
, 但是安卓不支持, 所以如果你只需要兼容ios, 其实可以直接用小数做单位. 但是我还是建议用上面的mixin, 毕竟省心效果也一样.
总结
上面封装的mixin兼容性非常好, 基本所有手机都兼容, 而且我还做了pc上的兼容, 请大家放心使用.
当然可能还有更好的方法是我不知道的, 如有还请大家多多指正留言, 感谢各位的阅读, 祝大家技术越来越强, 工资越来越多.
相关源码: https://github.com/any86/5a.c...
微信群
感谢大家的阅读, 如有疑问可以加群?, 群里有好多有趣的前端的小伙伴, 让我们共同学习成长吧!
也可加我微信, 我拉你进入微信群(由于腾讯对微信群的100人限制, 超过100人后必须由我拉进去)
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。