前端实现边框不同颜色图案线条

271 阅读5分钟

背景

业务需求开发时,UI 提供的设计图,有一个边框是用双色的虚线实现的,类似下图的效果。

1

本文总结这种边框实现的几种方式。

基础结构

html 结构

<div class="wrapper">
  <div class="content"></div>
</div>

CSS

在这里为了方便,直接使用 SCSS 语法书写了

.wrapper {
  height: 100%;
  background: #f5f7fa;
  padding: 32px;
  .content {
    background: oldlace;
    border-radius: 50px;
    height: 500px;
    padding: 32px;
  }
}

border-image

(不可行方案)

因为出现的问题是边框, 所以很容易第一个想到的是用边框实现。

先复习一下 border-image 的属性,作用是在给定元素的周围绘制图像,取代元素的常规边框。

border-image: <border-image-source> <border-image-slice> <border-image-width> <border-image-outset> <border-image-repeat>

例如:

/* source | slice | width | outset | repeat */
border-image: url("/images/border.png") 27 23 / 50px 30px / 1rem round space;

属性详解:

border-image-slice:用于将源图像分割为多个区域,最多可以指定四个值。切分过程会将图像分割为 9 个区域:四个角、四个边(edge)以及中心区域。四条切片线,从它们各自的侧面设置给定距离,控制区域的大小。

border-image-width:边框图像的宽度,最多可以指定四个值。如果本属性值大于元素的 border-width,边界图像将会向 padding 边缘延展。

border-image-outset:边框图像到元素外部边缘的距离。最多可以指定四个值。

border-image-repeat:定义图片如何填充边框。或为单个值,设置所有的边框;或为两个值,分别设置水平与垂直的边框。

border-image-repeat: stretch | repeat | round | space

stretch:拉伸图片以填充边框。

repeat:平铺图片以填充边框。

round:平铺图像。当不能整数次平铺时,根据情况放大或缩小图像。

space:平铺图像。当不能整数次平铺时,会用空白间隙填充在图像周围(不会放大或缩小图像)

那么按照这个思路尝试一下:

.content {
  border-bottom: 8px solid;
  border-image: url(@/assets/img/color_line.png) 8;
}

却发现效果是这样的:(为了效果清晰,将背景调整成了黑色),因为有圆角边框的存在,无法按照设计图那样,将边框图片和盒子融合,如左图所示。如果去掉圆角会发现边框是 OK的,如右图所示。

23

所以这个方案是不可行的。

伪元素+背景图

使用伪元素在 content 下添加一个高度固定的元素,并且使用给定图片作为背景,并设置必要的样式。

.content {
  position: relative;
  overflow: hidden; /* 必须要加,使图案超出盒子的部分被隐藏 */
  &::after {
    content: '';
    position: absolute;
    bottom: 0;
    left: 0;
    width: 100%;
    height: 8px;
    background: url(@/assets/img/color_line.png) no-repeat center;
    background-size: cover;
  }
}

效果如下:

1

需要注意的有2点:

  1. 父级元素 content 必须要加 overflow: hidden,因为父盒子有圆角,需要保证伪元素添加的背景图与圆角是适配的
  2. background-size 值设定 ,这个属性的作用是规定背景图片的尺寸。由下面的属性详细解释可以很清晰的明白,使用 cover 是最合适的。
background-size: contain | cover | width-value,height-value;;
属性
contain缩放背景图片以完全装入背景区,可能背景区部分空白。contain 尽可能的缩放背景并保持图像的宽高比例(图像不会被压缩)。该背景图会填充所在的容器。当背景图和容器的大小的不同时,容器的空白区域(上/下或者左/右)会显示由 background-color 设置的背景颜色。
cover缩放背景图片以完全覆盖背景区,可能背景图片部分看不见。和 contain 值相反,cover 值尽可能大的缩放背景图像并保持图像的宽高比例(图像不会被压扁)。该背景图以它的全部宽或者高覆盖所在容器。当容器和背景图大小不同时,背景图的 左/右 或者 上/下 部分会被裁剪。
width-value,height-value写死;auto就是以背景图片的比例缩放背景图片。当只有一个值时,指 width ,而height 是 auto

纯CSS实现

.content {
  position: relative;
  overflow: hidden; /* 必须要加,使图案超出盒子的部分被隐藏 */
  &::after {
    content: '';
    position: absolute;
    bottom: 0;
    left: 0;
    width: 100%;
    height: 8px;
    background: 
      linear-gradient(135deg, 
        transparent 0%,
        transparent 35%,
        #CFF9EA 35%,
        #CFF9EA 65%,
        transparent 65%,
        transparent 100%
      ) 0 0,
      linear-gradient(135deg,
        transparent 0%,
        transparent 35%,
        #FDD1CA 35%,
        #FDD1CA 65%,
        transparent 65%,
        transparent 100%
      ) 40px 0;
    background-size: 80px 8px;
    background-repeat: repeat-x;
  } 
}

效果如下:

4

接下来解释这段代码,关键逻辑在于使用两个线性渐变(linear-gradient)来创建重复的图案。每个渐变都是 45 度角的线性渐变。

第一个渐变:

  • 从 0% 到 35% 是透明的。
  • 从 35% 到 65% 是颜色 #CFF9EA。
  • 从 65% 到 100% 又是透明的。
  • 这个渐变的起始位置是 (0, 0)。

第二个渐变:

  • 从 0% 到 35% 是透明的。
  • 从 35% 到 65% 是颜色 #FDD1CA。
  • 从 65% 到 100% 又是透明的。
  • 这个渐变的起始位置是 (40px, 0),相对于第一个渐变向右偏移了 40 像素。

这个方法使用 linear-gradient ,其实是相对复杂的,没有办法很好的还原设计图中平行四边形尺寸,只能大致适配。所以在可选择的情况下,尽量使用方法二 伪元素+背景图实现