CSS

配合pointer-events实现1px边框

从乔帮主发布Retina设备开始兴起后,移动端的h5就多了一个烦人的1px。然后设计师们对1px格外青睐,设计稿(750尺寸)中各种1px分割线,1px边框。

对于下图中一系列的的1px边框通常的实现方式

1px系列边框

  1. 在最外层A进行transform:scale(0.5)

  2. 给每一个B元素加上transform:scale(0.5)

以上两种方式由于transform:scale(0.5)的影响,在写内部元素的大小时,都需要放大两倍,虽然只是*2,但是算起来还是略烦的。

下面介绍另外一种,pointer-events配合transform:scale(0.5)来实现1px边框的方式:

html:

1
<div class="b-div">

css:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
.b-div {
position: relative
/*
按照正常的布局计算方式来写
*/
}
/*单独的边框*/
.b-div::before {
content: '';
position: absolute;
display: block;
left: 0;
top: 0;
z-index: 10;
pointer-events: none;
box-sizing: border-box;
height: 200%;
width: 200%;
overflow: hidden;
border: 1px solid #fc9153;
transform: scale(0.5);
transform-origin: left top
}

上面通过伪类before来绘制1px边框。 在before上,将pointer-events的属性设置为none,边框元素虽然在b-div上层,但是不会有事件的响应,所有的事件会透到b-div上。如此一来,before伪类就仅仅是能”看到“而已

配合stylus的话,可以将1px边框的实现抽离出来,写成一个单独的mixin

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
border-1px($bordercolor, $bordertopleftradius = 0px, $bordertoprightradius = 0px, $borderbottomleftradius = 0px, $borderbottomrightradius = 0px)
&::before
content: " "
position: absolute
display: block
left: 0
top: 0
z-index: 10
pointer-events: none
box-sizing: border-box
height: 200%
width: 200%
overflow: hidden
border: 1px solid #fc9153
border-top-left-radius: $bordertopleftradius
border-top-right-radius: $bordertoprightradius
border-bottom-left-radius: $borderbottomleftradius
border-bottom-right-radius: $borderbottomrightradius
transform: scale(0.5);
transform-origin: left top

剩下的就是在有1px边框的元素上,设置position,然后css中加入border-1px(),内部元素计算大小时不需要在*2了。

1
2
3
.b-div
position: relative
border-1px(#fc9153)
兼容性

pointer-event的兼容性还是比较好的, 具体参看caniuse

该方法的弊端
  • 采用rem布局时,计算出的div(下面称为b-div)和边框的div(下面称为1px-div)会出现小数,如果b-div设置了overflow:hidden,则在部分安卓机器下会出现右边或者下边边框线消失的问题。

    目前找到的解决方法是b-div不要设置overflow:hidden。

  • 由于1px-div和b-div是两个独立的div,所以如果元素带圆角的话,需要同时设置1px-div和b-div的圆角,并且要一致。

阅读全部