css伪类实现0.5px边框

658 阅读4分钟

在实现UI稿设计时,经常有需要实现0.5px边框的场景,但浏览器最低只可以支持1px的边框,如果要实现0.5px边框,一般有两种方法:css阴影shadow和transform缩放,下面将使用csstransform缩放的方式来实现0.5px边框。

试一试

实现效果

image.png

实现代码

<script setup>
</script>

<template>
  <div class="container">
    <fieldset>
      <legend>1px</legend>
      <div class="box border">
        <div class="text">兄弟干一杯</div>
      </div>
    </fieldset>

    <fieldset>
      <legend>0.5px</legend>
      <div class="box half-border">
        <div class="text">兄弟干一杯</div>
      </div>
    </fieldset>
    <fieldset>
      <legend>0.5px上边框</legend>
      <div class="box half-border-top">
        <div class="text">兄弟干一杯</div>
      </div>
    </fieldset>

    <fieldset>
      <legend>0.5px下边框</legend>
      <div class="box half-border-bottom">
        <div class="text">兄弟干一杯</div>
      </div>
    </fieldset>
  </div>
</template>

<style scoped>
.container {
  .box {
    display: inline-flex;
    align-items: center;
    padding: 0 6px;
    height: 24px;
    background-color: #e6effe;
    border-radius: 6px;
    position: relative;

    .text {
      font-size: 12px;
      color: #3981f4;
    }

    &.border {
      border: 1px solid rgba(57, 129, 244, 1);
    }

    &.half-border {
      &::before {
        content: ' ';
        position: absolute;
        left: 0;
        top: 0px;
        width: 200%;
        height: 200%;
        transform-origin: 0 0;
        transform: scale(0.5);
        box-sizing: border-box;
        pointer-events: none;
        z-index: 1;
        border: 1px solid rgba(57, 129, 244, 1);
        border-radius: 12px;
      }
    }

    &.half-border-top {
      &::before {
        content: ' ';
        position: absolute;
        left: 0;
        top: 0px;
        width: 200%;
        height: 200%;
        transform-origin: 0 0;
        transform: scale(0.5);
        box-sizing: border-box;
        pointer-events: none;
        z-index: 1;
        border-top: 1px solid rgba(57, 129, 244, 1);
        border-radius: inherit;
      }
    }

    &.half-border-bottom {
      &::before {
        content: ' ';
        position: absolute;
        left: 0;
        top: 0px;
        width: 200%;
        height: 200%;
        transform-origin: 0 0;
        transform: scale(0.5);
        box-sizing: border-box;
        pointer-events: none;
        z-index: 1;
        border-bottom: 1px solid rgba(57, 129, 244, 1);
        border-radius: inherit;
      }
    }
  }
}
</style>

下面是代码的详细解析:

模板部分

模板部分包括一个容器,其中包含多个字段集,每个字段集中显示一个具有不同边框样式的盒子:

<template>
  <div class="container">
    <fieldset>
      <legend>1px</legend>
      <div class="box border">
        <div class="text">兄弟干一杯</div>
      </div>
    </fieldset>

    <fieldset>
      <legend>0.5px</legend>
      <div class="box half-border">
        <div class="text">兄弟干一杯</div>
      </div>
    </fieldset>
    <fieldset>
      <legend>0.5px上边框</legend>
      <div class="box half-border-top">
        <div class="text">兄弟干一杯</div>
      </div>
    </fieldset>

    <fieldset>
      <legend>0.5px下边框</legend>
      <div class="box half-border-bottom">
        <div class="text">兄弟干一杯</div>
      </div>
    </fieldset>
  </div>
</template>

样式部分

样式部分定义了容器和不同类型盒子的样式:

<style scoped>
.container {
  .box {
    display: inline-flex;
    align-items: center;
    padding: 0 6px;
    height: 24px;
    background-color: #e6effe;
    border-radius: 6px;
    position: relative;

    .text {
      font-size: 12px;
      color: #3981f4;
    }

    &.border {
      border: 1px solid rgba(57, 129, 244, 1);
    }

    &.half-border {
      &::before {
        content: ' ';
        position: absolute;
        left: 0;
        top: 0px;
        width: 200%;
        height: 200%;
        transform-origin: 0 0;
        transform: scale(0.5);
        box-sizing: border-box;
        pointer-events: none;
        z-index: 1;
        border: 1px solid rgba(57, 129, 244, 1);
        border-radius: 12px;
      }
    }

    &.half-border-top {
      &::before {
        content: ' ';
        position: absolute;
        left: 0;
        top: 0px;
        width: 200%;
        height: 200%;
        transform-origin: 0 0;
        transform: scale(0.5);
        box-sizing: border-box;
        pointer-events: none;
        z-index: 1;
        border-top: 1px solid rgba(57, 129, 244, 1);
        border-radius: inherit;
      }
    }

    &.half-border-bottom {
      &::before {
        content: ' ';
        position: absolute;
        left: 0;
        top: 0px;
        width: 200%;
        height: 200%;
        transform-origin: 0 0;
        transform: scale(0.5);
        box-sizing: border-box;
        pointer-events: none;
        z-index: 1;
        border-bottom: 1px solid rgba(57, 129, 244, 1);
        border-radius: inherit;
      }
    }
  }
}
</style>

主要内容

  • 1px边框: .border 类应用一个标准的1px实线边框。
  • 0.5px边框: .half-border 类使用 ::before 伪元素,通过缩放一个1px的边框来创建0.5px边框的效果。
  • 0.5px上边框: .half-border-top 类使用缩放的伪元素应用0.5px的上边框。
  • 0.5px下边框: .half-border-bottom 类使用缩放的伪元素应用0.5px的下边框。

原理解释

通过使用伪元素和变换(scale(0.5)),可以创建看起来是0.5px宽的边框,这在需要实现更精细的边框样式时非常有用,因为浏览器的标准渲染可能不直接支持0.5px的边框

分步拆解

  • 创建两倍尺寸的伪元素,并设置边框为1px,因为html流式布局的原因,伪元素的position必须设置成absolute才能让元素不占用位置,同时父元素要设置positionrelative,让伪元素相对于父元素的左上角开始布局:left: 0top: 0px
  • 将伪元素的尺寸设置成两倍、边框设置成1px,如果父元素有设置border-radius,则伪元素的border-radius也要设置成两倍,因为尺寸变成了两倍。
.container {
  .box {
    display: inline-flex;
    align-items: center;
    padding: 0 6px;
    height: 24px;
    background-color: #e6effe;
    border-radius: 6px;
    position: relative;
    .text {
      font-size: 12px;
      color: #3981f4;
    }

    &.half-border {
      &::before {
        content: ' ';
        position: absolute;
        left: 0;
        top: 0px;
        width: 200%;
        height: 200%;
        transform-origin: 0 0;
        box-sizing: border-box;
        pointer-events: none;
        z-index: 1;
        border: 1px solid rgba(57, 129, 244, 1);
        border-radius: 12px;
      }
    }
  }
}
</style>

  • 将伪元素缩小一倍

使用transform: scale(0.5)将伪元素缩小一倍,就能实现0.5px边框的效果。

.container {
  .box {
    display: inline-flex;
    align-items: center;
    padding: 0 6px;
    height: 24px;
    background-color: #e6effe;
    border-radius: 6px;
    position: relative;
    .text {
      font-size: 12px;
      color: #3981f4;
    }

    &.half-border {
      &::before {
        content: ' ';
        position: absolute;
        left: 0;
        top: 0px;
        width: 200%;
        height: 200%;
        transform-origin: 0 0;
        transform: scale(0.5);
        box-sizing: border-box;
        pointer-events: none;
        z-index: 1;
        border: 1px solid rgba(57, 129, 244, 1);
        border-radius: 12px;
      }
    }
  }
}
</style>