Skip to content

在CSS边框上做文章

在CSS2.1时代,边框只能是纯色的。但是在CSS3时代,可以通过border-image定制边框颜色

border-image

所有与装饰有关的CSS属性都能从其他设计软件中找到对应的功能,如背景描边阴影,甚至滤镜混合模式 ,但是唯独borderimage属性是CSS这门语言独有的,就算其他软件有边框装饰,也不是border-image这种表现机制

但是存在3个问题:

  • 心智负担高
  • 最终的效果与UI并不完全相符
  • 4个角的怪异行为

语法

text
border-image =
  <'border-image-source'>                             ||
  <'border-image-slice'> [ / <'border-image-width'> | / <'border-image-width'>? / <'border-image-outset'> ]?  ||
  <'border-image-repeat'>
  • source: 边框图像的路径(可以是URL,也可以是渐变)
  • slice: 将图像分割为9个区域的偏移量(1-4个值,可以是数字百分比
  • width: 边框图像的宽度(可选,默认值为1),可以设置值,为border-width的倍数
  • outset: 边框图像超出边框盒的量(可选),可以设置值,为border-width的倍数
  • repeat: 定义中间部分和边缘部分如何重复或拉伸(可选,值:stretch, repeat, round, space)
    • stretch:(默认)会拉伸边片以填满边长,
    • repeat:会重复平铺(可能截断)
    • round:平铺图案并且“整齐恰好填满”(常用于图案无缝平铺),
    • space:会把重复项之间留空隙以填满整条边

理解

源图片的原始尺寸为162x162,每个方块的尺寸为54

img.png

九宫格

img.png

将一张图片分割成9个区域:

  • 四个角(corner):对应边框的四个角,不会缩放
  • 四个边(edge):对应边框的四个边,可以拉伸重复铺满
  • 一个中心(middle):默认不显示,除非设置fill关键字。

border-image-slice

通过border-image-slice划分源图形,将图像分割为9个区域的偏移量(1-4个值,可以是数字百分比

text
border-image-slice: <number-percentage>{1,4} && fill?

用于指定4个方向上相对于边的偏移量,方向为:上、右、下、左。

例如:

css
.box {
  border-image-slice: 20;
}

表示在距离源图像上方20px、距离源图像右侧20px、距离源图像下方20px、距离源图像左侧20px的地方进行划分


默认情况下,源图像划分的中心位置是不参与填充的。如果想要有填充效果,可以额外使用fill关键字

border-image-width

边框图像的宽度(可选,默认值为1),可以设置值,为border-width的倍数

img.png


css
.box {
  border-image: url('/imgs/base/css/chapter-3-3.svg') 54 fill / 1 / 0;
}
  • 边框图片:/imgs/base/css/chapter-3-3.svg
  • slice:距离源文件边的距离为54px
  • 边框图像的宽度为边框宽度的1倍,即与边框宽度保持一致
  • 超出边框宽度为0

border-image-outset

边框图像超出边框盒的量(可选),可以设置值,为border-width的倍数

border-image-repeat

定义控制九宫格上、右、下、左4个区域(对应的区域序号是5~8,我称这几个区域为平铺区)图形的平铺规则(可选,值:stretch, repeat, round, space)

  • stretch:让源图像拉伸以充满显示区域
  • repeat:让源图像紧密相连平铺,保持原始比例,平铺单元在边界位置处可能会被截断
  • round:让源图像紧密相连平铺,适当伸缩,以确保平铺单元在边界位置处不会被截断
  • space:让源图像保持原始尺寸,平铺时彼此保持适当的等宽间隙,以确保平铺单元在边界位置处不会被截断

WARNING

  • border-image 会替换原始边框(即边框线颜色/样式会被图片替换)。
  • border-radius 对 border-image 没作用——边框图像不会被圆角裁剪(MDN 给出了解决方案,如在 background 上做两层图)。如果想要圆角效果,最好在图片本身或使用背景/clip 技巧实现。
  • border-image-width 并不会影响border-width,只是影响border-image的宽度,但是在最终渲染出来的效果中看着像是改变了border-width。

注意

  • outset、inset:只能对应单向扩展,仅支持正值。例如:box-shadow、text-shadow
  • offset:扩展的方向既能向外也能向内,反映在属性值上就是offset既支持正值也支持负值 。例如:outline-offset、text-underline-offset等CSS属性

妙用

自定义虚线框

使用border定义的虚线框在不同的浏览器中展示样式不同,可以通过border-image自定义的虚线框保持样式相同

1:1的虚线

border-image属性最适合模拟宽度为1px的虚线边框。

如果边框宽度比较大,实线的端点就会有明显的斜边,此时建议使用background-image属性和线性渐变语法进行模拟,或者干脆使用SVG元素配合stroke- dasharray实现更灵活的边框效果

带圆角的见边框

  • 通过父元素的border-radius、overflow: hidden实现(需要在外层包括一层div)
html
<div class="w-full h-100px rounded-8px overflow-hidden">
  <div
    class="w-full h-full"
    style="border-style: solid;
    border-image: linear-gradient(deepskyblue, deeppink) 20 / 10px;"
  ></div>
</div>
  • 通过clip-path实现
text
<inset()> =
  inset( <length-percentage>{1,4} [ round <'border-radius'> ]? )

模拟轮廓

CSS中有3个属性可以实现对布局没有任何影响的轮廓:outline、box-shadow、border-image

属性支持渐变支持模糊支持圆角间隙控制方位控制
outline
box-shadow
border-image

INFO

border属性不能写在border-image属性的下方。

工具

  1. box-image生成器