什么是点九图,如何在CSS中实现点九图?彻底搞懂 border-image!

背景

最近接了一个需求,产品让在页面上加一个按钮,我(不假思索):"好的!简单!"。

设计:"好的,按钮样式如下:"

我:"?"

作为一个前端摆子,我肯定不会思考怎么实现不规则图形的,于是我跑去和设计要了切图,设计:"诺~"

把图形当做背景图片就好了嘛,三分钟写完。

js 复制代码
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>购买按钮</title>
  </head>
  <style>
    body {
      padding: 100px;
    }
    .button-container {
      position: relative;
    }
    button {
      border: none;
      padding: 8px 16px;
      background: #000000;
      color: #fff;
      border-radius: 5px;
      font-size: 26px;
      font-weight: bold;
    }
    .bubble {
      position: absolute;
      top: -22px;
      left: 70px;
      font-weight: bold;
      font-size: 12px;
      color: #ffffff;
      padding: 4px 10px 7px;
      background: url(./src/assets/qipao.png);
      background-size: contain; /* cover */
    }
  </style>
  <body>
    <div class="button-container">
      <div class="bubble">先抢先得,仅剩48件</div>
      <button>立即购买</button>
    </div>
  </body>
</html>

不过我好像忘记了一件事情,文字是不固定长度的,而我写出来的样式是这样,这样,这样的......

(以上分别设置了 background-size: initial;background-size: contain;background-size: cover;

既然 background不能用,动了动脑子,我想出了好办法,拿一个图片当做背景图,然后指定和文字相同的宽高就好了!

js 复制代码
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>购买按钮</title>
  </head>
  <style>
   body { padding: 100px; } .button-container { position: relative; } button {
border: none; padding: 8px 16px; background: #000000; color: #fff;
border-radius: 5px; font-size: 26px; font-weight: bold; } .bubble { position:
absolute; top: -22px; left: 70px; font-weight: bold; font-size: 12px; color:
#ffffff; padding: 4px 10px 7px; background-size: contain; background-size:
cover; }
  </style>
  <body>
    <div class="button-container">
      <div class="bubble">
        <img src="./src/assets/qipao.png" style="position: absolute; left: 0; top: 0; width: 100%; height: 100%;" />
        <span style="position: relative;">先抢先得,仅剩48件</span>
      </div>
      <button>立即购买</button>
    </div>
  </body>
</html>

结果是这样的,乍一看好像还凑合,不过当文字边长时,就彻底变形了。。。

可怜的小饼干已经在抓狂了T^T

点九图

不过还好,搜到了点九图这个东西(参考 点九切图你知道怎么切吗?

点九图(9 patch image) ,是Android开发中用到的一种特殊格式的图片,文件名以" .9.png "命名。这种图片能告诉开发,图像哪一部分可以被拉伸,哪一部分不能被拉伸需要保持原有比例。运用点九图可以保证图片在不模糊变形的前提下做到自适应。点九图常用于对话框和聊天气泡背景图片中

如图为一个点九图,可以比较明显的看到上下左右分别有一个像素的黑色线段。简单来说,序号1和2表示了可以拉伸的区域序号3和4表示了显示内容区域。

当设定了按钮实际应用的宽和高之后,横向会拉伸1区域的像素,纵向会拉伸2区域的像素。而显示内容区域表示了需要展示文字的区域。

看看!这个正是我想要的吗!不过人家是安卓的,和前端又有什么关系?!

CSS 实现点九图 - border-image

咱就是说有什么事情不能问问神奇的 ChatGPT 呢

OK,让我们来学一下 border-image

border-image

border-image 的默认值为 border-image: none 100% / 1 0 stretch,拆分成子属性为:

css 复制代码
border-image-source: none;
border-image-slice: 100%;
border-image-width: 1;
border-image-outset: 0;
border-image-repeat: stretch;

接下来分别说下子属性的作用,先通过表格简单总结,后面分开来说。

属性 作用 默认值
border-image-source 指定边框图片的 URL 或者渐变值。 none
border-image-slice 指定边框图片的裁切方式 100%
border-image-width 指定边框图片的宽度。 1
border-image-outset 指定边框图片的偏移量 0
border-image-repeat 指定边框图片的重复方式 stretch

border-image-source

border-image-source 属性用于指定边框图片的 URL 或者渐变值。

border-image-source 属性接受一个 URL 值或者一个渐变值,表示边框图片的来源。如果使用 URL 值,则可以指定一个图片文件的 URL,例如:

css 复制代码
border-image-source: url(border.png);

如果使用渐变值,则可以使用 linear-gradient() 或者 radial-gradient() 函数来定义一个渐变,例如:

css 复制代码
border-image-source: linear-gradient(to right, red, yellow);

需要注意的是,border-image-source 属性必须与 border-image-slice 属性一起使用,否则边框图片不会被显示。

border-image-width

border-image-width 属性用于指定边框图片的宽度,可以使用长度值、百分比值或者数字值来指定。如果使用长度值或百分比值,则表示边框图片的宽度;如果使用数字值,则表示边框图片的宽度为边框宽度的倍数。

例如,以下代码将边框图片的宽度设置为 20 像素:

css 复制代码
border-image-width: 20px;

如果边框图片的宽度小于边框区域的宽度,则边框图片将被拉伸以填充整个边框区域;如果边框图片的宽度大于边框区域的宽度,则边框图片将被裁切以适应边框区域。因此,可以通过设置 border-image-width 属性来控制边框图片的大小。

需要注意的是,border-image-width 属性必须与 border-image-source 属性一起使用,否则边框图片不会被显示。

border-image-slice

border-image-slice 属性用于指定边框图片的裁切方式,即指定边框图片的哪一部分用于绘制边框,哪一部分用于填充边框内部。

border-image-slice 属性接受一个或四个值,分别表示图片裁切的上、右、下、左四个方向的值。如果只指定一个值,则表示四个方向的值都相同;如果指定两个值,则第一个值表示上下方向的值,第二个值表示左右方向的值;如果指定三个值,则第一个值表示上方的值,第二个值表示左右方向的值,第三个值表示下方的值;如果指定四个值,则分别表示上、右、下、左四个方向的值。

border-image-slice 可以指定为百分比或者数值,数值单位为像素。

假设我设置 border-image-slice: 10% 20% 30% 40%;,那么图形将以如下的方式被分割成 9 份,然后 1,3,7,9 会被放置在边框的四个角,2,6,8,4 在四个边,如果长度不够会被拉伸(border-image-repeat:stretch情况下),如果设置 fill 则中间部分5也会在新的背景中展示。

然后举个例子,先找一个比较经典的图片:

html 复制代码
<!DOCTYPE html>
<html lang="en">
  <style>
    body { padding: 100px; --width: 20px; } 
    .box { width: 100px; height: 100px; box-sizing: border-box; position: relative; box-shadow: 0px 0px 0px 1px #000; } 
    .inner1 { position: absolute; top: 0; bottom: 0; left: var(--width); right: var(--width); border-style: solid; border-width: 0 1px 0px 1px; } 
    .inner2 { position: absolute; top: var(--width); bottom: var(--width); left: 0; right: 0; border-style: solid; border-width: 1px 0px 1px 0; } 
    .box {
      border-image-source: url(./src/assets/border.png);
      border-image-slice: 100%;
      border-image-width: var(--width);
      border-image-outset: 0;
      border-image-repeat: stretch;
    }
  </style>
  <body>
    <div class="box">
      <div class="inner1"></div>
      <div class="inner2"></div>
    </div>
  </body>
</html>

展示效果

通过两个 div 设置了辅助线,为了清楚得看到 border-image 所占宽度。

上面是默认值 100% 的效果,下面尝试调整 border-image-slice 的值。

样式 效果
border-image-slice: 60%
border-image-slice: 50%
border-image-slice: 40%
border-image-slice: 10%

可以看到,当 border-image-slice 大于 50% 的时候,只有四个角有图形,四个边框是没有图形的。这也很合理,因为按照上面的切割方式,当 left > right 时,中间是没有图形的。

再尝试下四个方向不同的大小。以及添加 fill 的样式。

样式 效果
border-image-slice: 33% 100% 33% 50%;
border-image-slice: 30% 20% fill

border-image-repeat

border-image-repeat 属性用于指定边框图片的重复方式,即指定边框图片在边框区域内的重复方式。

border-image-repeat 属性接受一个或两个值,分别表示图片在水平方向和垂直方向的重复方式。如果只指定一个值,则表示水平和垂直方向的重复方式相同。

border-image-repeat 属性的值可以是以下几种:

  1. stretch:默认值,表示边框图片将被拉伸以填充整个边框区域。

  2. repeat:表示边框图片将在边框区域内平铺重复。

  3. round:表示边框图片将在边框区域内平铺重复,如果图片大小不能完全填充边框区域,则会自动缩小或放大图片,直到完全填充边框区域。

  4. space:表示边框图片将在边框区域内平铺重复,如果图片大小不能完全填充边框区域,则会在图片之间留出等间距的空白。

这个乍一看不是很好理解,可以通过例子来看下。

当我们设置 border-image-slice: 30% fill;border-image-repeat: stretch; 时,中间的图形会被拉伸为如下效果。

当我们设置为 border-image-repeat: repeat; 可以看到同样的图案没有被拉伸,而是被平铺重复。

border-image-repeat: round; 还是会被重复,但是这种情况下会适当拉伸或缩小,让图形刚好重复倍数个。

最后 border-image-repeat: space; 不会被拉伸或缩小,只让图形刚好重复倍数个,剩余的空间在重复图形间留下空白。

border-image-outset

border-image-outset 属性用于指定边框图片的偏移量,即指定边框图片与边框区域的距离。

border-image-outset 属性接受一个或四个值,分别表示图片偏移的上、右、下、左四个方向的值。如果只指定一个值,则表示四个方向的值都相同;如果指定两个值,则第一个值表示上下方向的值,第二个值表示左右方向的值;如果指定三个值,则第一个值表示上方的值,第二个值表示左右方向的值,第三个值表示下方的值;如果指定四个值,则分别表示上、右、下、左四个方向的值。

例如,以下代码将边框图片的偏移量设置为 10 像素:

css 复制代码
border-image-slice: 100%;
border-image-outset: 10px;
border-image-repeat: stretch;

回到最初的例子

js 复制代码
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <style>
    body {
      padding: 100px;
    }
    .button-container {
      position: relative;
    }
    button {
      border: none;
      padding: 8px 16px;
      background: #000000;
      color: #fff;
      border-radius: 5px;
      font-size: 26px;
      font-weight: bold;
    }
    .bubble {
      position: absolute;
      top: -22px;
      left: 70px;
      font-weight: bold;
      font-size: 12px;
      color: #ffffff;
      padding: 4px 10px 7px;
      border-image-source: url(./src/assets/qipao.png);
      border-image-slice: 26 fill;
      border-image-width: 50px;
      border-image-slice: 27 35 32 37;
    }
  </style>
  <body>
    <div class="button-container">
      <div class="bubble">先抢先得,仅剩48888888件</div>
      <button>立即购买</button>
    </div>
  </body>
</html>

可以看到现在文字再长图形也不会变形了。

参考

相关推荐
破浪前行·吴9 小时前
【初体验】【学习】Web Component
前端·javascript·css·学习·html
爱码网页成品17 小时前
HTML静态网页成品作业(HTML+CSS)——婚礼婚纱网页设计制作(6个页面)
前端·css·html
长风清留扬18 小时前
小程序在智慧城市构建中的角色与功能研究
javascript·css·人工智能·微信小程序·小程序·html·智慧城市
大嘴史努比18 小时前
前端-如何做一个关键字生成组件
前端·javascript·css
WebDesign_Mu20 小时前
HTML+CSS+JS制作中国传统节日主题网站(内附源码,含5个页面)
javascript·css·html
一点一木20 小时前
Can I Use 实战指南:优化你的前端开发流程
前端·javascript·css
疯狂的沙粒21 小时前
HTML和CSS相关详解,如何使网页为响应式?
前端·css·html
无法长大1 天前
el-upload on-preview 扩大预览事件点击范围
前端·javascript·css·vue.js·elementui·vue
@_猿来如此1 天前
Web网页制作之JavaScript的应用
前端·javascript·css·html·html5
仿生狮子1 天前
CSS Layer、Tailwind 和 sass 如何共存?
javascript·css·vue.js