[CSS]使用transform实现1px边框遇到的问题
前言
由于移动端屏幕的像素密度都非常高,css中的1px
呈现在屏幕中,往往不止1个物理像素,看起来比较粗,设计师很难满意。这和devicePixelRatio
有关。
用transform
实现看起来比较细的边框是一个很简单的方案,在移动端兼容性也非常好,不需要多余的资源,当然,肯定要多些几行代码。
实现
实现一条横向的分隔线,一般这样写:
<!-- HTML -->
<div></div>
/* CSS */
div {
position: relative;
}
div::after {
content: '';
position: absolute;
left: 0;
right: 0;
bottom: 0;
border-bottom: 1px solid blue;
transform: scaleY(.5);
}
其中的关键就是transform: scaleY(.5);
,一条水平方向,高度是1px(不是物理像素)的线,由于Y
方向压缩了一半,当然就变细了。如果要实现的是竖线,就使用scaleX
缩放X
方向。
如何实现边框呢?可以把before
或者after
伪元素先设置为父元素的200%
,然后再缩小为原来的一半。代码如下:
<!-- HTML -->
<div></div>
/* CSS */
div {
position: relative;
}
div::after {
content: '';
position: absolute;
left: 0;
bottom: 0;
height: 200%;
width: 200%;
border: 1px solid blue;
transform-origin: 0 0;
transform: scaleY(.5);
}
问题
如果没有背景颜色,效果看起来很完美(上面代码省略了无关紧要的内容):
但如果你想给按钮添加一个hover
样式,在按下去的时候,添加一个背景颜色:
div:active {
background-color: blue;
}
这时就会发现,边框有点偏移:
为啥呢?因为边框也占用空间,给伪元素设置了宽高后,伪元素的宽高是它的宽高+边框的宽度
,在缩放了一半之后,宽高并不等于父元素的宽高的一半。咋解决呢?如下:
div::after{
...
transform: translate(-.5px, -.5px) scaleY(.5);
...
}
因为scale
先于translate
执行,所以偏移量只有1px缩放一半后的0.5px
。(transform
的执行顺序,请搜索transform: matrix
,了解矩阵
) 问题完美解决:
更简单的方法是使用box-sizing
:
div::after{
...
box-sizing: border-box;
...
}
效果和上面一样,稳稳的,很贴心。
注意点
使用伪元素作为边框,尤其是after
伪元素,可能会遮盖整个父元素,如果父元素的正常子元素有click
等鼠标事件,要设置正确的z-index
。
如果有疑问或者问题请留言或联系。