稀土掘金技术社区 07月08日 14:15
CSS 实现九宫格缩放(9-slice scaling 不变形拉伸)
index_new5.html
../../../zaker_core/zaker_tpl_static/wap/tpl_guoji1.html

 

文章介绍了游戏开发中常用的9宫格缩放技术,以及CSS中border-image属性如何实现类似效果。通过划分图像区域,固定角部样式,拉伸边框和中心区域,可以避免图片变形,减少美术资源用量。文章详细解释了border-image-source、border-image-slice和border-image-repeat属性的使用,并展示了实例代码,帮助读者理解和应用这一技术。

🔺9宫格缩放技术是一种常见的图形技术,将图像划分为9个区域,其中四个角固定尺寸不缩放,四条边和中心区域可拉伸,用于保持UI边角样式和填充剩余空间。

🖌️CSS中通过border-image-source、border-image-slice和border-image-repeat属性可以实现类似9宫格缩放的效果,其中border-image-slice属性用于指定图像的切割区域,border-image-repeat属性用于设置拉伸方式。

💻文章以实例代码详细解释了如何使用border-image属性实现图片不变形的拉伸效果,包括设置边框宽度、指定源图片、切割区域和拉伸方式,并展示了鼠标悬停时的动态效果。

原创 德莱厄斯 2025-06-30 08:30 重庆

前言一些游戏中的窗口通常都有一些炫酷的效果....

前言一些游戏中的窗口通常都有一些炫酷的效果

比如这样的

这样的

还有这样的

哎等等,你发现没有,后面两张的窗口长得很相似,只是第二张比较矮,第三张比较高,那么是不是要做两张素材来支持这种形式呢?

当然不用,在游戏开发中,通常会使用一种叫做 “ 9 宫格缩放(9-slice scaling)” 的技术,这是一种非常常见且极其实用的图形技术,「9-slice scaling」 是一种对位图图像进行缩放的方法,它将图像划分成 9 个区域(3 行 × 3 列),像这样

    ╔════╦═══════╦════╗

    ║ TL ║  Top  ║ TR ║

    ╠════╬═══════╬════╣

    ║ L  ║Center ║ R  ║

    ╠════╬═══════╬════╣

    ║ BL ║ Bottom║ BR ║

    ╚════╩═══════╩════╝

    「四个角(TL, TR, BL, BR)」 :固定尺寸,「不缩放」,用来保持 UI 的边角样式(圆角、高光、装饰等)。

    「四条边(Top, Bottom, Left, Right)」 :只在一个方向拉伸:

    Top/Bottom 水平拉伸

    Left/Right 垂直拉伸

    「中心区域(Center)」 :在 「水平和垂直方向都可以拉伸」,填满剩下的空间。

    不得不说,发明九宫格缩放的人就是个天才,这大大减少了美术资源用量。

    聪明的你肯定联想到了你那睿智的 UI 同事,他也总是给你一些让你抓耳挠腮的背景图,让你在使用时总是有图片拉伸变形的问题。

    那么前端有没有类似的用法呢?

    有的兄弟有的哦?你以为我又要介绍某个 auto 系列插件是吗?

    还真让你猜错了,今天我要说的是几个 CSS 属性。它们分别是:

    border-image-source

    border-image-slice

    border-image-repeat

    通过这三个属性,就可以做到让图片做到不变形的拉伸效果。

    现在拿一个图片举例

    可以看到,我拿红线将在此图上花了一个井字形,这个井字可不是随便画的,它大有来头,它标记了我允许它形变的地方,和保持不变的地方。

    这样四个角将会保持我们目前看到的样子(原始比例),当图片宽度或高度改变时,只会改变可拉伸区域的表现。

    这张图片的原始尺寸是 1064*141,且上面的截图是以原始尺寸展示的。从此图来看(梯形),它大概率要承受比它更长或更短的内容,目测一下,可以看到右上角、左上角的不允许形变区域大概是 50px、而左右不允许形变区域大概是 200px、由于这张梯形图且不考虑上下拉伸,所以下面则不能设置固定部分,否则会使左右两边发生断层(有时斜率不一致)。

    所以我们这么写

            .frame-container {

              /* 1. 先设定边框宽度(上 右 下 左)*/

              border-width50px 200px 0px 200px;

              border-style: solid;

              border-color: transparent; /* 透明即可,边框颜色会被 image 覆盖 */

            }

      我们将正常的边框属性按照刚刚目测的数值写成这样,现在看起来无事发生,因为边框是透明的。

      那么我们接着写:

              .frame-container {

                /* 1. 先设定边框宽度(上 右 下 左)*/

                border-width50px 200px 0 200px;

                border-style: solid;

                border-color: transparent; /* 透明即可,边框颜色会被 image 覆盖 */

                /* 2. 指定 border-image 源图片 */

                border-image-sourceurl('./a.png');

                /* 为了演示,就给它一个动态宽度和高度 */

                width1064px;

                height141px;

                /* 3. 指定 slice,也就是按 30px / 10px / 20px / 15px 把图片分成 9 块 */

                border-image-slice50 200 0 200 fill;

              }

        这里为了方便演示,我们将容器大小设置为图片的原始大小,目前的效果看起来有点奇怪,左右两边看起来被折断了。

                .frame-container {

                  /* 1. 先设定边框宽度(上 右 下 左)*/

                  border-width50px 200px 0 200px;

                  border-style: solid;

                  border-color: transparent; /* 透明即可,边框颜色会被 image 覆盖 */

                  /* 2. 指定 border-image 源图片 */

                  border-image-sourceurl('./a.png');

                  /* 为了演示,就给它一个动态宽度和高度 */

                  width1064px;

                  height141px;

                  /* 3. 指定 slice,也就是按 30px / 10px / 20px / 15px 把图片分成 9 块 */

                  border-image-slice50 200 0 200 fill;

                  /* 4. 指定拉伸(stretch)—— 

                   上边/下边 拉伸水平;左边/右边 拉伸垂直;中间那块自由拉伸/填充 */

                  border-image-repeat: stretch;

                  transition1s;

                  /* 5. 你可以给中间区域再加个背景,比如纯白或者另一张图 */

                  background-color: white;

                  /* 如果想用内容图,也可以启用下面这行: */

                  /* background: url("content.png") no-repeat center/cover; */

                  box-sizing: border-box; /* 确保 width/height 包括 border */

                }

          加上 box-sizing: border-box; 图片看起来正常多了,我还加了其他必须的代码,现在这张图已经具备我们开头说的能力了。

          加一个 hover 简单看一下:

                  /* 鼠标移进去改变尺寸,看看效果,模拟内容变少 */

                  .frame-container:hover {

                    width400px;

                    height141px;

                  }

            总结通过上面的演示,可以发现,通过这种方式可以实现横向纵向(取决于图片异形,有的只能横向,有的只能纵向,有的横纵都可)的不变形拉伸。

            学会了这招,再也不用向 UI 要多张切图、拆分切图了,还不谢谢我。

            AI编程资讯AI Coding专区指南:https://aicoding.juejin.cn/aicoding

            ""~

            阅读原文

            跳转微信打开

            Fish AI Reader

            Fish AI Reader

            AI辅助创作,多种专业模板,深度分析,高质量内容生成。从观点提取到深度思考,FishAI为您提供全方位的创作支持。新版本引入自定义参数,让您的创作更加个性化和精准。

            FishAI

            FishAI

            鱼阅,AI 时代的下一个智能信息助手,助你摆脱信息焦虑

            联系邮箱 441953276@qq.com

            相关标签

            9宫格缩放 CSS border-image 图形技术 前端开发
            相关文章