有些时候 UI 给切的背景,并不能适配所有长宽比的元素,这个时候就需要一个非常强大的 CSS 属性:border-image
,下面先翻译border-image
相关的W3C 规范草案,再举例说明如何应用到元素背景中。
草案翻译
开发者可以指定用来替代 border-style
的图像。在这种情况下,border
取自 border-image-source
指定的图像的边缘和角落,这些图像的碎片可以通过各种方式进行切片、缩放和拉伸,以适应边框图像区域的大小。 边框图像属性不影响布局: 盒的布局、内容和环绕内容仅基于 border-width
和 border-style
属性的影响。
示例 26:
这个例子创建了一个顶部和底部的 border
,border
中包含大量的橙色钻石,左右 border
是一个单一的拉伸钻石,border
的四个角是不同颜色的钻石。 平铺开的图像如下所示,除了钻石以外,其余部分都是透明的:
这个图像是 81 × 81
像素,被分成 9
个大小相等的部分。 因此,样式规则可以如下:
1 | div { |
把上述样式应用到 12×5em
的 DIV 上,结果如下所示:
示例 27:
这个示例展示了一个更复杂的情况,演示了边框图像如何对应到预备的 border-style
并且可以扩展到边框区域之外。边框图像是一个带有四角突出效果的绿色波浪边框:
border-image-source
属性对应的图像,使用 4
个 124px
的 border-image-slice
属性分割图像,将图像分成了 9
个部分。
然后,其余的 border
属性相互作用,按照以下方式布局:
上图展示了所有的 border-image
属性的相互作用,并且展示了是否使用 border-image
属性对渲染结果的影响。
在本示例中,即使 border-width
是 12px
,border-image-width
依然会计算为 124px
。这个边框图像在 border
外 31px
处开始,并且进入了 margin
区域。如果 border-image
加载失败(或者浏览器不支持 border-images
) ,预备渲染将使用绿色双实线样式的 border
。
示例 28:
注意:边框样式简写“border
”的将重置 border-image
。 这样可以很容易地关闭或重置所有边框效果:
1 | .notebox { |
图像来源:border-image-source 属性
名称 | border-image-source |
---|---|
值 | none |image |
默认值 | none |
适用范围 | 所有元素,除了 border-collapse 为 collapse 的内部 table 元素 |
继承 | 无 |
百分比 | 不适用 |
计算值 | 关键字 none 或者 image 计算值 |
动画类型 | 离散 |
指定一个图像用于替代 border-style
属性的渲染结果,如果在 border-image-slice
中给定 fill
关键字,则把图像也用作元素的附加图像背景。 如果值为 none
或者图像无法显示(或者属性未时使用) ,则使用 border
样式;否则不绘制元素的 border-style
样式边框,而按照下面部分所述绘制边框图像。
图像切片:border-image-slice 属性
名称 | border-image-slice |
---|---|
值 | number|percentage,fill |
默认值 | 100% |
适用范围 | 所有元素,除了 border-collapse 为 collapse 的内部 table 元素 |
继承 | 无 |
百分比 | 参考边框图像的大小 |
计算值 | 4 个数字或者百分比,如果 fill 指定还需要加上 fill |
动画类型 | 按照计算值来实现 |
此属性指定图像上、右、下和左边缘向内的偏移量,并将其划分为九个区域:四个角、四条边和一个中间区域。 除非 fill
关键字出现,否则中间图像部分将被丢废弃(视为完全透明)。 (中间部分是在背景上绘制的; )
当四个属性指定了以后,就按照上右下左顺序设置偏移量。如果左偏移缺失,和右偏移相等;下偏移缺失,和上偏移相等;右偏移缺失,和上偏移相等。
-
百分比值与图像的大小有关: 水平偏移量参照图像宽度,垂直偏移量参照图像高度
-
数字表示图像中的像素(如果图像是位图)或矢量坐标(如果图像是矢量图)。
-
fill 关键字如果存在,则保留边框图像的中间部分。 (默认情况下不使用 fill)。
负值是无效的。大于图像尺寸的计算值被解释为 100%
。
由 border-image-slice
指定的区域可以重叠。但是如果左右偏移的宽度之和大于等于图像宽度,则上中,下中和最中间位置处的图像为空,与这三个部分指定了非空的透明图像效果相同。上下偏移宽度和大于图像高度时结果是类似的。
如果必须对图像进行大小调整才能确定切片(例如,没有内置大小的 SVG 图像),则使用默认尺寸调整算法设置图像大小,并将边框图像区域作为默认对象尺寸。
上图展示了按照 25% 30% 12% 20%切割图像的示意。
绘图范围:border-image-width 属性
名称 | border-image-width |
---|---|
值 | number|length-percentage|auto |
默认值 | 1 |
适用范围 | 所有元素,除了 border-collapse 为 collapse 的内部 table 元素 |
继承 | 无 |
百分比 | 参考边框图像范围的 width/height |
计算值 | 4 个值,每一个都可以是数字,关键字 auto 或长度百分比计算值 |
动画类型 | 按照计算值来实现 |
边框图像是在一个称为边框图像区域的范围内绘制的。 默认情况下,边界与边框盒对应。
border-image-width
的四个值指定用于将边框图像区域分为九个部分的偏移量。 它们分别表示从该区域的上、右、下和左侧向内的距离。 如果左宽度缺失,和右宽度相等; 如果下宽度缺失,和上宽度相等; 如果右宽度缺失,和上宽度相等。 值有以下含义:
-
百分比参考的是边框图像区域的大小: 水平偏移量参考区域宽度,垂直偏移量参考区域高度。
-
数字表示相应
border-width
计算值的倍数。 -
如果指定了
auto
,则边框图像宽度是相对应图像切片的内部宽度或高度。 如果图像没有所需的内部宽高,那么用相对应的border-width
计算值来代替。
任何 boder-image-width
值都不允许使用负值。
如果两个相反的 border-image-width
偏移量大到以至于重叠,那么所有 border-image-width
偏移量的使用值都会按比例减少,直到它们不再重叠。
边缘超出:border-image-outset 属性
名称 | border-image-outset |
---|---|
值 | length|number |
默认值 | 0 |
适用范围 | 所有元素,除了 border-collapse 为 collapse 的内部 table 元素 |
继承 | 无 |
百分比 | 不适用 |
计算值 | 4 个值,每一个都可以是数字或绝对长度 |
动画类型 | 按照计算值来实现 |
border-image-outset
的四个值用于指定边框图像区域超出边框盒的距离。 它们分别表示从该区域的上、右、下和左侧超出的距离。 如果左距离缺失,和右距离相等;如果下距离缺失,和上距离相等;如果右距离缺失,和上距离相等。 值有以下含义:
注意:即使
border-image-outset
从未引起滚动机制,但超出部分的图像仍然可能被上级元素或视窗给剪掉。
图片平铺:border-image-repeat 属性
名称 | border-image-repeat |
---|---|
值 | stretch|repeat|round|space |
默认值 | stretch |
适用范围 | 所有元素,除了 border-collapse 为 collapse 的内部 table 元素 |
继承 | 无 |
百分比 | 不适用 |
计算值 | 两个关键词,每个轴一个 |
动画类型 | 按照计算值来实现 |
此属性指定如何缩放和平铺边框图像中的边缘和中间部分的图像。 第一个关键字适用于顶部、中部和底部的水平缩放和平铺,第二个关键字适用于左部、中部和右部的垂直缩放和平铺。 如果缺失第二个关键字,则假定它与第一个关键字相同。 值有以下含义:
stretch
.图像被拉伸以填充区域
repeat
将图像平铺(重复)以填充区域
round
将图像平铺(重复)以填充区域。 如果没有将整个区域填满,则对图像进行重新缩放以使其填满。
space
将图像平铺(重复)以填充该区域。 如果它没有将整个区域填满瓷砖,那么额外的空间将分布在瓦片周围
下面一节给出了缩放和平铺 border-image
部分的确切过程。
绘制边框图像
将由 border-image-source
提供的 border-image
使用 border-image-slice
进行切片后,将生成的 9
个瓦片按 4
个步骤进行缩放、定位和拼接到相应的 border-image
区域:
关于
border-image-width
的缩放使上和下的两个边缘图像分别与上边缘和下边缘图像区域一样高,同时同比例缩放宽度。
使左和右的两个边缘图像分别与左边缘和右边缘图像区域一样宽,同时同比例缩放高度。
四个角图像被缩放成与它们所属的两个边框图像边缘一样的宽高。
中间图像的宽度按照与顶部图像相同的比例进行缩放,除非该比例为零或无穷大,在这种情况下,底部的缩放比例被替换,如果达不到这一点,则不进行缩放。 中间图像的高度将按照与左图像相同的比例进行缩放,除非该比例为零或无穷大,在这种情况下,右图像的缩放比例将被替换,如果达不到这一点,高度将不进行缩放。
关于
border-image-repeat
的缩放- 如果第一个关键字是
stretch
,那么顶部、中部和底部的图像将进一步缩放,使其与边框图像区域的中间部分一样宽。 高度不再改变。 - 如果第一个关键字是
round
,那么顶部、中间和底部的图像就会在宽度上调整大小,这样它们的整个数量就恰好适合于边框图像区域的中间部分,与background-repeat
属性中的round
完全一样。 - 如果第一个关键字是
repeat
或space
,则顶部、中间和底部图像不会进一步更改。 - 第二个关键字的
stretch
、round
、repeat
和space
的效果是类似的,它们作用于左、中、右图像的高度。
- 如果第一个关键字是
定位第一块瓦片
- 如果第一个关键字是
repeat
,则顶部、中间和底部的图像将在各自区域中水平居中。 否则,图像被放置在边界图像区域各自部分的左边缘。 - 如果第二个关键字是
repeat
,则左图、中图和右图在各自的区域垂直居中显示。 否则,图像被放置在边界图像区域各自部分的顶部边缘。
- 如果第一个关键字是
平铺和绘制
- 然后将图像平铺以填充各自的区域。
- 在
space
的情况下,任何局部瓦片都被丢弃,并且额外的空间分布在瓦片前、间、后(即平衡第一个瓦片之前的间隙、最后一个瓦片之后的间隙以及瓦片之间的间隙)。 这可能导致边框图像边缘区域是空的。 - 图像是在与正常
border
相同的层次级别上绘制的:直接绘制在背景图层的上面。 - 除非为
border-image-source
指定了 fill,否则不绘制中间图像。
边框图像简写:border-image 属性
名称 | border-image |
---|---|
值 | border-image-source|| border-image-slice [ / border-image-width / border-image-width ? [ border-image-outset] ?|| border-image-repeat |
默认值 | 见各自属性 |
适用范围 | 见各自属性 |
继承 | 无 |
百分比 | 不适用 |
计算值 | 见各自属性 |
动画类型 | 见各自属性 |
这是设置 border-image-source
、border-image-slice
、border-image-width
、border-image-outset
和 border-image-repeat
的简化属性。 省略的值设置为它们各自的初始值。
对表格的影响
border-image
属性可以应用于 border-collapse
设置为 collapse
的表格和行内表格的 border
。但是,此规范没有定义如何渲染这样的图像边框。 尤其是规范没有定义图像边界如何与表格边缘的单元格、行和行组的边界的相互作用(请参见中的边界冲突解决方法)。
预计未来的规范将定义渲染规则。 建议在此之前,浏览器不要将边框图像应用于边框已折叠的表格。
实际应用
首先说明一点,实验中发现 Chrome80 浏览器中的 border-image-width
支持 px
单位,注意1px
有时候与倍数1
的区别。
普通用法
给出一个 button
的背景图片如下,像素数是 300×128
。
如果使用普通的 background
,应用到 1400×200
的 button 上,由于长宽比不同,就会出现拉伸的情况,代码和结果如下所示:
1 | button { |
这个时候最适合 border-image
完成这个任务,首先测量下图片的细节尺寸:
接下来把 background
设置为透明,由于边框图像的横纵宽度都是 25px
,所以先给 border
设置 25px
宽度来开启边框。然后设置 border-image
,border-image-source
就是背景图,border-image-slice
上下左右都是 25
,并且添加关键字 fill
来填充最中间的瓦片,后面的 border-image-outset
、border-image-width
和 border-image-repeat
三个值默认即可。
1 | button { |
结果如下,button 按钮可以随便改变宽高比也不会使背景拉伸。
升级用法
下面说一些更延伸的使用方式,再给出一个 button 的背景图片如下,像素数为400×128
,仍然想把它给1400×200
的 button 当背景:
这次的背景图与上一个的区别主要在两个地方,第一个是圆角幅度特别大,已经组成了两个半圆,所以在纵向上没有可以 stretch
或 repeat
的空间;第二个是右侧有一个圆包着“¥”符号,而且符号比较靠内而不贴近边缘,在横向上左右不对称。
虽然情况稍微复杂,但是强大的 border-image
仍然可以解决,继续分割一下图片:
这次的分割并没有把图片分割成 9
份,而是去掉了中间一行分割成了 6
份,半圆的半径是 64px
,“¥”符号的整体距离右侧 120px
。具体实现的想法就是在横向上让最中间一行的高度为 0
,纵向上“¥”符号整体作为最右侧一列边框部分,再使用 border-image-width
将边框向内拉伸合并起来。
第一步先用 CSS 把背景图像分割,注意 border
的宽度设为 2px
做一个基本量:
1 | button { |
此时的效果如下,可以发现中间一行已经为空,上下是宽度为 2px
的 border
:
第二步,使用 border-image-width
属性,将边框向内部入侵,注意,由于分割的时候是按照 64 120 64 64
,所以向内放大入侵时也应该按照相同的比例,一直放大到上下边框图像合并(64×2px,120×2px,64×2px,64×2px
,规范中规定上下边框图像重叠后会自动调整为不重叠),伪造出一种背景图片填充的效果。
1 | button { |
最终效果如下: