0.5px边框及子元素背景色遮盖问题解决办法

593 阅读3分钟
1、结论先行
(1)0.5px边框代码实现如下
<html>
<div class="parent">
  <div class="child"></div>
</div>
<html>

<style>
.parent{
  width:200px;
  height:200px;
  position:relative;
}
.child{
  height:100%;
}
.parent:before{
  content:"";
  position:absolute;
  border: 1px solid blue;
  width:200%;
  height:200%;
  transform:scale(.5);
  left:-50%;
  bottom:-50%;
}
<style>

效果如下:0.5px边框完美展示。

image.png

(2)简单解决背景覆盖问题:

父元素的伪类增加box-sizing:border-box;

(3)子元素相对定位,解决背景覆盖问题:
.parent{
  width:200px;
  height:200px;
  position:relative;
}
.child{
  height:100%;
  background: red;
  position:relative;
}
.parent:before{
  content:"";
  position:absolute;
  border: 1px solid blue;
  width:calc(200% + 2px);
  height:calc(200% + 2px);
  transform:scale(.5);
  left:calc(-50% - 1px);
  bottom:calc(-50% - 1px);
  box-sizing:border-box;
}

image.png

2、原理解释

我们实现用伪元素实现0.5px边框的原理,首先,用伪元素制造一个父元素二倍宽高的元素, 再用scale(0.5)缩小它,这样1px的border, 也会被缩小为0.5px。

.parent{
  width:200px;
  height:200px;
  position:relative;
}
.child{
  height:100%;
  background: red;
}
.parent:before {
  content: "";
  position: absolute;
  border: 1px solid blue;
  width: 200%;
  height: 200%;
  transform: scale(.5);
  
} 

image.png

然后通过绝对定位将伪元素已移动到正确位置

.parent{
  width:200px;
  height:200px;
  position:relative;
}
.child{
  height:100%;
  background: red;
}
.parent:before {
  content: "";
  position: absolute;
  border: 1px solid blue;
  width: 200%;
  height: 200%;
  transform: scale(.5);
  left: -50%;
  bottom: -50%;
} 

image.png

然后我们发现, 有背景颜色的子元素与边框不能完全重合,这是因为,盒子原型默认是content-box,原本1px的边框会完全包裹住子元素,,我们把伪元素等比例缩小0.5后,边框变成0.5px,那么就会与子元素之间有0.5px的缝隙。而且div默认的布局方式会落在父元素的左下角,因此会展示出如上图效果。

解决方式:父元素的伪元素增加box-sizing属性。

image.png

目前看似已经完美解决了问题, 但是实际生产环境的页面元素复杂, 子元素也需要相对定位的情况呢? 我们给子元素增加position:relative 属性,问题又来了。

image.png

经过上面的操作, 伪元素与子元素的宽高严丝合缝一样大,所以当子元素relative时,脱离了正常文档流,只是留存了原本的位置,子元素的层级会提升, 因此就会盖在伪元素的上方。

那么如何解决这个问题呢?用计算属性。

.parent{
  width:200px;
  height:200px;
  position:relative;
}
.child{
  height:100%;
  background: red;
  position: relative;
}
.parent:before{
  content:"";
  position:absolute;
  border: 1px solid blue;
  width:calc(200% + 2px);
  height:calc(200% + 2px);
  transform:scale(.5);
  left:calc(-50% - 1px);
  bottom:calc(-50% - 1px);
  box-sizing:border-box;
}

效果如下:

image.png

原因如下:

父元素为100宽高,伪元素的width和height属性设置为200%+2px, 缩小0.5后, 也就是101px宽高, 这个数值, 就是100的content和两个0.5px的border,因此这种方式,能够做到伪元素边框是真正的包在子元素的外圈。

对于left和bottom的操作,是因为伪元素要向左,向下移动一半也就是-50%,伪元素宽高变为200%+2px后,这个值变成 -50% +(-1px)。

至此,0.5像素边框问题完美解决。