背景
业务需求开发时,UI 提供的设计图,有一个边框是用双色的虚线实现的,类似下图的效果。
本文总结这种边框实现的几种方式。
基础结构
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的,如右图所示。
所以这个方案是不可行的。
伪元素+背景图
使用伪元素在 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;
}
}
效果如下:
需要注意的有2点:
- 父级元素
content必须要加overflow: hidden,因为父盒子有圆角,需要保证伪元素添加的背景图与圆角是适配的 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;
}
}
效果如下:
接下来解释这段代码,关键逻辑在于使用两个线性渐变(linear-gradient)来创建重复的图案。每个渐变都是 45 度角的线性渐变。
第一个渐变:
- 从 0% 到 35% 是透明的。
- 从 35% 到 65% 是颜色 #CFF9EA。
- 从 65% 到 100% 又是透明的。
- 这个渐变的起始位置是 (0, 0)。
第二个渐变:
- 从 0% 到 35% 是透明的。
- 从 35% 到 65% 是颜色 #FDD1CA。
- 从 65% 到 100% 又是透明的。
- 这个渐变的起始位置是 (40px, 0),相对于第一个渐变向右偏移了 40 像素。
这个方法使用 linear-gradient ,其实是相对复杂的,没有办法很好的还原设计图中平行四边形尺寸,只能大致适配。所以在可选择的情况下,尽量使用方法二 伪元素+背景图实现