border-image-slice详细介绍
border-image-slice 是 CSS border-image 系列属性里最关键、也最容易让人懵的一个属性。
它的作用可以简单理解为:
把一张图片切成九宫格,然后决定哪几块用来绘制元素的边框。
它通常和这些属性一起使用:
border-image-source: url("./button.png");
border-image-slice: 20;
border-image-width: 20px;
border-image-repeat: stretch;
或者简写成:
border-image: url("./button.png") 20 / 20px stretch;
其中 border-image-slice 决定“怎么切图”。
**一、****border-image**是什么?
普通的 border 只能画纯色边框:
border: 2px solid red;
但有时候我们想用图片作为边框,比如:
- 游戏按钮边框
- 像素风 UI
- 复古窗口
- 聊天气泡
- 卡牌边框
- 花纹装饰框
- 九宫格按钮背景
这时候就可以用 border-image。
例如一张按钮图片长这样:
┌───────────────┐
│ │
│ button │
│ │
└───────────────┘
我们希望按钮变宽时,四个角不要变形,中间和边缘可以拉伸。
这就是 border-image 的经典用途。
**二、****border-image-slice**的核心思想:九宫格切图
假设有一张图片:
+-----------------------+
| |
| |
| |
| |
| |
+-----------------------+
设置:
border-image-slice: 20;
意思是:
从图片的上、右、下、左四个方向,各切进去 20 个单位。
于是图片会被切成九块:
+---------+-------------+---------+
| 左上角 | 上边 | 右上角 |
+---------+-------------+---------+
| 左边 | 中间 | 右边 |
+---------+-------------+---------+
| 左下角 | 下边 | 右下角 |
+---------+-------------+---------+
这九块分别有不同用途:
区域 | 作用 |
|---|---|
四个角 | 放到元素边框的四个角,通常不拉伸 |
上下边 | 横向拉伸或重复,铺满上/下边框 |
左右边 | 纵向拉伸或重复,铺满左/右边框 |
中间区域 | 默认丢弃,除非加 |
三、基本语法
border-image-slice: <number> | <percentage> [fill]?;
它可以写 1 到 4 个值,规则和 margin、padding 类似。
1. 一个值
border-image-slice: 20;
等价于:
border-image-slice: 20 20 20 20;
意思是:
上:20
右:20
下:20
左:20
从图片四个方向都切 20。
2. 两个值
border-image-slice: 20 30;
等价于:
border-image-slice: 20 30 20 30;
意思是:
上、下:20
左、右:30
3. 三个值
border-image-slice: 20 30 40;
等价于:
border-image-slice: 20 30 40 30;
意思是:
上:20
左、右:30
下:40
4. 四个值
border-image-slice: 10 20 30 40;
意思是:
上:10
右:20
下:30
左:40
顺序是:
上 右 下 左
也就是 CSS 经典的顺时针顺序。
**四、****number和percentage**的区别
border-image-slice 可以写数字,也可以写百分比。
1. 数字:按图片原始像素切
border-image-slice: 20;
这里的 20 不是 20px,而是图片坐标里的 20 个单位。
对于普通位图,比如 PNG、JPG,可以近似理解为:
从图片边缘切进去 20px。
注意,这里不能写 20px。
错误写法:
border-image-slice: 20px;
正确写法:
border-image-slice: 20;
这是很多人第一次用时会踩的坑。
2. 百分比:按图片尺寸比例切
border-image-slice: 25%;
意思是:
上:图片高度的 25%
下:图片高度的 25%
左:图片宽度的 25%
右:图片宽度的 25%
举个例子,如果图片是 100 × 50:
border-image-slice: 25%;
那么大致等价于:
上:12.5
下:12.5
左:25
右:25
因为:
上下基于图片高度 50
左右基于图片宽度 100
所以百分比不是所有方向都按同一个尺寸算。
**五、****fill**是什么?
默认情况下,九宫格中间那块会被丢弃。
例如:
border-image-slice: 20;
只会使用:
四个角
四条边
中间区域不会绘制。
如果你希望中间区域也显示出来,需要加 fill:
border-image-slice: 20 fill;
或者:
border-image-slice: 20 20 20 20 fill;
这样中间区域也会被拿来填充元素内容区域。
不加**fill**
.btn {
border: 20px solid transparent;
border-image-source: url("./button.png");
border-image-slice: 20;
}
效果类似:
只画边框,中间透明或由 background 决定
加**fill**
.btn {
border: 20px solid transparent;
border-image-source: url("./button.png");
border-image-slice: 20 fill;
}
效果类似:
边框 + 中间背景都使用图片
对于游戏按钮、像素风按钮、装饰卡片来说,fill 经常很有用。
**六、****border-image-slice和border-image-width**的区别
这两个很容易混。
border-image-slice
决定:原图怎么切。
例如:
border-image-slice: 20;
表示在原图上切出 20 的区域。
**border-image-width**决定:切出来的边框在元素上显示多宽。
例如:
border-image-width: 10px;
表示绘制到元素上时,边框区域宽度是 10px。
对比理解
假设图片是 100 × 50。
border-image-slice: 20;
border-image-width: 10px;
意思是:
从原图中切 20px 的边缘区域
但是绘制到页面上时,边框宽度显示为 10px
所以:
slice管原图width管页面显示- 两者不是一回事
七、必须设置**border**
很多人写了 border-image-slice 但没效果,原因是没有设置基础 border。
通常需要这样:
.btn {
border: 20px solid transparent;
border-image-source: url("./button.png");
border-image-slice: 20 fill;
border-image-width: 20px;
}
或者:
.btn {
border: 20px solid transparent;
border-image: url("./button.png") 20 fill / 20px stretch;
}
为什么需要 border?
因为 border-image 是画在边框区域上的。如果元素没有边框区域,浏览器就没有地方画。
一般推荐:
border: 20px solid transparent;
这里颜色写 transparent,因为真正显示的是图片,不是普通边框颜色。
八、完整示例:图片按钮
假设你有一张按钮图片:
button-green.png
尺寸:100 × 50
你希望按钮宽度可以变成 300px,高度是 50px,四个角保持不变,中间拉伸。
可以这样写:
.gmc-btn-green {
width: 300px;
height: 50px;
border: 16px solid transparent;
border-image-source: url("/images/button-green.png");
border-image-slice: 16 fill;
border-image-width: 16px;
border-image-repeat: stretch;
background: transparent;
}
也可以简写:
.gmc-btn-green {
width: 300px;
height: 50px;
border: 16px solid transparent;
border-image: url("/images/button-green.png") 16 fill / 16px stretch;
background: transparent;
}
**九、****border-image-repeat**会影响最终效果
border-image-slice 只是决定“怎么切”,而切出来的边怎么铺,还要看:
border-image-repeat
它常见值有:
stretch
repeat
round
space
1.****stretch
border-image-repeat: stretch;
表示把边缘区域直接拉伸铺满。
这是最常用的。
适合:
- 渐变按钮
- 普通 UI 边框
- 非像素风图片
缺点是如果边缘有纹理,可能会被拉变形。
2.****repeat
border-image-repeat: repeat;
表示重复铺。
适合:
- 像素风边框
- 重复纹理边框
缺点是可能在末尾被裁剪,导致边缘对不齐。
3.****round
border-image-repeat: round;
也是重复铺,但浏览器会稍微缩放图片块,让它刚好铺满。
适合:
- 希望重复但不要裁剪
- 花纹边框
- 像素风边框
4.****space
border-image-repeat: space;
表示重复铺,但多余空间用间距分散。
这个用得比较少。
十、为什么会出现黑线、白线、缝隙?
这是 border-image-slice 实战里最常见的问题。
尤其是游戏按钮、透明 PNG、像素风 UI,特别容易出现边缘黑线。
常见原因有几个。
1. 原图切割位置刚好切到阴影或描边
比如图片边缘本身有黑色描边。
你设置:
border-image-slice: 25;
但这个位置刚好落在黑色描边中间。
浏览器切图再拉伸时,就可能把这条黑色像素拉成一整条线。
解决方法:
border-image-slice: 24;
或者:
border-image-slice: 26;
微调 1 到 2 个单位。
很多时候就是差这 1px。
2. 图片有半透明抗锯齿像素
PNG 边缘经常有半透明像素,比如:
透明
半透明黑
实体绿色
浏览器切图和缩放时,半透明像素被采样,就会出现黑边、灰边或白边。
解决方式:
- 重新处理图片边缘
- 避免切线经过半透明区域
- 尽量切在纯色区域
- 使用更干净的九宫格素材
3. 元素尺寸导致小数像素
比如图片原始宽度是 100px,按钮显示宽度是 301px。
浏览器拉伸边框时,可能产生小数像素。
比如:
某一块需要显示成 137.5px
浏览器最终要渲染到物理像素上,就可能发生采样误差。
结果就是有时有线,有时没线。
这也是你调整屏幕宽度时,黑线时隐时现的原因之一。
解决方式:
width: 300px;
height: 50px;
尽量让尺寸是整数,避免复杂缩放。
如果是响应式宽度,可以考虑:
min-width: 120px;
height: 50px;
同时减少 border-image 对复杂缩放的依赖。
**4.****slice和border-width**不匹配
例如:
border-image-slice: 25;
border-image-width: 13px;
border: 13px solid transparent;
原图切 25,显示却压成 13,浏览器会缩放边缘区域。
缩放过程中就可能采样到不该出现的像素。
一般建议先保持它们接近:
border: 16px solid transparent;
border-image-slice: 16 fill;
border-image-width: 16px;
如果图片本身尺寸允许,先让 slice 和 border-image-width 对齐,问题会少很多。
十一、
border-image-slice
的调试方法
如果图片效果不对,可以按这个顺序排查。
第一步:确认图片尺寸
比如图片是:
100 × 50
那你要知道:
横向中心:50
纵向中心:25
如果你想四等分切,大概就是:
border-image-slice: 25 50 25 50;
但这个值非常极端,因为左右各切 50,就没有中间横向区域了。
对于 100 × 50 的图片,一般更现实的是:
border-image-slice: 16 24 16 24 fill;
或:
border-image-slice: 20 30 20 30 fill;
具体取决于图片的圆角、描边、渐变区域在哪里。
第二步:先画出明显边框
.btn {
border: 20px solid red;
}
先确认元素真的有边框区域。
然后再加:
border-image-source: url("./button.png");
border-image-slice: 20 fill;
第三步:先用
stretch
border-image-repeat: stretch;
先不要用 repeat 或 round。
stretch 更容易判断切图是否正确。
第四步:微调
slice
例如从:
border-image-slice: 20 fill;
改成:
border-image-slice: 19 fill;
或者:
border-image-slice: 21 fill;
观察黑线是否消失。
这一步非常重要。很多 border-image 问题不是代码逻辑错,而是切线刚好切到了不该切的位置。
十二、简写语法怎么读?
完整写法:
border-image-source: url("./button.png");
border-image-slice: 20 fill;
border-image-width: 20px;
border-image-outset: 0;
border-image-repeat: stretch;
可以简写成:
border-image: url("./button.png") 20 fill / 20px / 0 stretch;
结构是:
border-image:
source
slice
/
width
/
outset
repeat;
例如:
border-image: url("./border.png") 30 / 30px / 0 round;
意思是:
图片:border.png
切图:30
边框显示宽度:30px
向外扩展:0
铺法:round
不过实际开发中,我更建议新手不要一开始就写简写。
更清楚的写法是:
.box {
border: 30px solid transparent;
border-image-source: url("./border.png");
border-image-slice: 30;
border-image-width: 30px;
border-image-repeat: round;
}
等你确认没问题,再压成简写。
**十三、****border-image-slice和background-size**的区别
有些人会问:
我直接用 background-image 不行吗?
可以,但它们解决的问题不同。
background-image
适合:
整张图片作为背景
例如:
background-image: url("./button.png");
background-size: 100% 100%;
这样会把整张图片直接拉伸。
缺点是:
四个角也会被拉伸变形
如果按钮从 100px 拉到 300px,圆角、描边、阴影都会变形。
border-image
适合:
四角保持不变,边缘和中间拉伸
也就是九宫格缩放。
对于 UI 按钮、卡片、弹窗边框,border-image 更适合。
十四、什么时候适合用**border-image-slice****?**
适合这些场景:
游戏 UI 按钮
像素风边框
聊天气泡
装饰卡片
弹窗面板
复古风窗口
RPG 对话框
带复杂纹理的边框
尤其是图片边框不能简单用 border-radius、box-shadow、linear-gradient 实现时,就可以考虑它。
十五、什么时候不建议用?
不太建议用在这些场景:
普通圆角按钮
普通渐变按钮
简单边框
纯色描边
响应式特别复杂的容器
需要极高精度对齐的 UI
如果 CSS 本身能实现,就没必要上 border-image。
例如普通按钮:
.button {
border-radius: 12px;
background: linear-gradient(#6ee76e, #28a728);
border: 2px solid #137c13;
}
这种比 border-image 更稳定、更清晰。
十六、常见坑总结
1. 忘记写基础**border**
错误:
.btn {
border-image-source: url("./button.png");
border-image-slice: 20;
}
正确:
.btn {
border: 20px solid transparent;
border-image-source: url("./button.png");
border-image-slice: 20;
}
2. 给**slice写了px**
错误:
border-image-slice: 20px;
正确:
border-image-slice: 20;
3. 忘记加
fill
如果你希望中间也显示图片,需要:
border-image-slice: 20 fill;
不加 fill,中间区域默认不会被绘制。
4. 切线切到了脏像素
例如切到了阴影、描边、半透明边缘。
解决:
border-image-slice: 19 fill;
或者:
border-image-slice: 21 fill;
上下微调。
5. 图片本身不适合九宫格
不是所有图片都适合 border-image。
适合九宫格的图片最好满足:
四个角独立
四条边可以拉伸或重复
中间区域尽量干净
边缘没有奇怪半透明脏像素
如果图片是复杂插画,强行九宫格切割很容易变形。
十七、实战建议
如果你是在做游戏按钮,推荐流程是:
- 先确认图片原始尺寸。
- 找出四个角不能变形的区域。
slice切线尽量放在纯色区域。border、border-image-width和slice先保持一致。- 加上
fill,让中间也绘制。 - 用
stretch测试。 - 如果有黑线,微调
slice1px。 - 如果响应式变化时黑线时有时无,考虑换成伪元素或 canvas 方案。
例如:
.gmc-btn-green {
height: 50px;
min-width: 120px;
border: 16px solid transparent;
border-image-source: url("/images/btn-green.png");
border-image-slice: 16 fill;
border-image-width: 16px;
border-image-repeat: stretch;
background: transparent;
}
如果左右出现黑线,可以试:
border-image-slice: 16 15 16 15 fill;
或者:
border-image-slice: 15 16 15 16 fill;
根据黑线方向微调。
十八、一句话总结
border-image-slice 的本质是:
告诉浏览器:这张边框图片应该从哪里切成九宫格。
它不负责图片怎么铺,也不负责边框显示多宽。
对应关系是:
border-image-slice → 原图怎么切
border-image-width → 页面上显示多宽
border-image-repeat → 切出来的边怎么铺
fill → 中间区域要不要显示
掌握这几个关系之后,border-image-slice 就没那么玄学了。
但它确实比较吃图片素材质量。尤其是游戏 UI 按钮,如果原图边缘有抗锯齿、阴影、半透明像素,或者切割位置不干净,就很容易出现黑线、白线、缝隙。这不是你代码写错,而是九宫格切图和浏览器采样一起造成的经典问题。
如果您觉得这篇文章有帮助,请点个赞吧~
评论
请登录后发表评论
去登录