CSS border-image 的神奇用法

最近我为艾美奖获奖游戏作曲家迈克·沃斯设计新网站时,受雇打造高度视觉化的作品展示方案,并全程运用了border-image技术。

图0:CSS border-image 的神奇用法

设计由安迪·克拉克,Stuff & Nonsense完成。迈克·沃斯的个人网站将于2025年4月上线,但您可通过CodePen查看本文示例

属性与值的简要概述

首先,让我们快速回顾一下。大多数关于border-image 的说明都从这个极具启发性的代码片段开始:

border-image: [source] [slice]/[width]/[outset] [repeat]

这是border-image属性的一组简写形式,但最好分别处理每个属性,以便更轻松地理解其概念。

元素周期表

border-image里的“source”

首先从要插入边框区域的位图或矢量格式图像、CSS渐变的来源开始:

border-image-source: url('/img/scroll.png');

当我将SVG图像插入边框时,有多种实现方式可选。我可以使用外部SVG文件:

border-image-source: url('/img/scroll.svg');

或者我也可以使用Base64.Guru这类工具将SVG转换为数据URI,不过由于SVG和HTML都是基于XML的,因此不建议这样做:

border-image-source: url('data:image/svg+xml;base64,…');

相反,我可将SVG代码直接添加到源URL值中,从而节省一次不必要的HTTP请求:

border-image-source: url('data:image/svg+xml;utf8,…');

最后,我终于能在边框中插入完全由CSS生成的锥形、线性或径向渐变:

border-image-source: conical-gradient(…);

提示:需注意浏览器渲染 border-image时,其位置位于元素背景和 box-shadow之上,但内容层之下。稍后将对此进行详细说明。

分割border-image

在指定边框图像的来源后,我可通过将其分割并应用于元素周围的不同位置来实现边框效果。这对初次接触border-image的人而言往往是最令人困惑的部分。

多数border-image的说明示例中,分割后的图像片段通常是等比例的,例如:

图1:CSS border-image 的神奇用法

然而,border-image可由任意形状生成,无论其多么复杂或不规则。

与直接将图像插入边框并观察其在元素周围重复显示不同,不可见的切割线将border-image分割为九个部分。这些线条类似于图形应用程序中的切片辅助线。这些分割后的图像片段随后被分别填充到元素边框的九个区域中。

图2:CSS border-image 的神奇用法border-image-slice 属性通过指定图像每条边沿的距离来定义每个切片的大小。我可以使用与每条边沿相同的距离:

border-image-slice: 65

我可以组合顶部/底部和左侧/右侧的数值:

border-image-slice: 115 65;

或者,我可以为所有四条切割线指定距离值,按顺时针方向依次为: top, right, bottom, left:

border-image-slice: 65 65 115 125;

图像的左上角将用于元素边框的左上角。右下角将用于右下角,依此类推。

图3:CSS border-image 的神奇用法当使用位图图像时,我无需为border-image-slice值添加单位,因为浏览器会正确地将位图视为像素单位。而SVG的viewBox属性使得使用方式略有不同,因此我也倾向于明确指定其高度和宽度:

<svg height="600px" width="600px">…</svg>

请务必设置这些边框的宽度,否则边框图像将无处显示:

border-image-width: 65px 65px 115px 125px;

填充中心区域

到目前为止,我已利用了图像的四个角和四条边,那么中心区域呢?默认情况下,浏览器在切片后会忽略图像中心区域。但通过在border-image-slice值中添加fill关键字,我就能充分利用这个区域:

border-image-slice: 65px 65px 115px 125px fill;

边框图像的角部定位完成后,我便可着手处理它们之间的边缘衔接。正如你所料想的,图像顶部的切片将被放置在顶部边缘,右侧、底部和左侧边缘亦遵循相同原则。在弹性布局中,我们无法预知这些边缘的宽度或高度,因此我需要精细调整图像在填充边缘时的重复或拉伸方式。

图4:CSS border-image 的神奇用法Stretch::当切片图像平整或光滑时,可拉伸以填充任意高度或宽度。即使是仅65像素的小切片,也能无损拉伸至数百甚至数千像素。

border-image-repeat: stretch;

Repeat::若图像具有纹理,则无法进行拉伸处理,因此可通过重复填充来适应任意高度或宽度。

border-image-repeat: repeat;

Round:若图像存在无法拉伸的图案或形状,且需要匹配重复区域的边缘,可指定采用圆形重复模式。浏览器将调整图像尺寸,确保每个边缘内仅显示完整的图案单元。

border-image-repeat: round;

Space:round类似,使用空间属性时,仅完整片段会在边界内显示。但浏览器不会调整图像尺寸,而是会在重复区域中添加空白。

border-image-repeat: space;

当我需要为每条边指定独立的 stretchrepeatround,或 space值时,可以使用多个关键词:

border-image-repeat: stretch round;

border-image外延

有时需要让图像延伸至元素border-box之外。通过border-image-outset属性即可实现。最简单的语法是将边框图像在所有边方向均匀外延10像素:

border-image-outset: 10px;

当然,由于每个元素都有四个边界,我也可以分别指定每个边界:

border-image-outset: 20px 10px; 
/* or */
border-image-outset: 20px 10px 0;

border-image的实际应用

迈克·沃斯是一位屡获殊荣的电子游戏作曲家,曾凭其作品斩获艾美奖。他痴迷于90年代动画——尤其是迪士尼的《鸭子故事》——并委托我创作定制插画,打造出大胆而复古的设计风格。

图5:CSS border-image 的神奇用法

为迈克开发时面临的挑战在于,如何在不牺牲性能的前提下实现高度图形化的设计,尤其是在移动设备上。虽然CSS中通常有多种方式达成相同目标,但在此场景下,border-image往往被证明是最高效的解决方案。

装饰性按钮

最简单直接的切入点是创建仿石碑风格的按钮,其边缘呈现剥落不平的质感。

图6:CSS border-image 的神奇用法我创建了一个平板电脑形状的SVG,并通过border-image将其添加到按钮中:

button {
  border-image-repeat: stretch;
  border-image-slice: 10 10 10 10 fill;
  border-image-source: url('data:image/svg+xml;utf8,…');
  border-image-width: 20px;
}

我将所有边缘的border-image-repeat设置为stretch ,中心部分设置为填充,这样这些石碑风格的按钮就能随内容扩展至任意高度或宽度。

古老卷轴

我希望迈克网站设计的每个细节都能彰显他的品牌特色。这意味着要在长篇内容中延续90年代卡通主题,将其转化为纸质卷轴的形式呈现。

图7:CSS border-image 的神奇用法

标记非常简单,仅包含一个article 元素:

<article>
  <!-- ... -->
</article>

然而,我苦恼于如何实现纸张效果。最初的想法是将卷轴拆分为三个独立的SVG文件(顶部、中部和底部),并使用伪元素添加卷轴卷起的上下部分。我首先尝试在文章中部应用垂直重复的图形:

article {
  padding: 10rem 8rem;
  box-sizing: border-box;
  /* Scroll middle */
  background-image: url('data:image/svg+xml;utf8,…');
  background-position: center;
  background-repeat: repeat-y;
  background-size: contain;
}

然后,我添加了两个伪元素,每个都包含自己的SVG内容:

article:before {
  display: block;
  position: relative;
  top: -30px;
  /* Scroll top */
  content: url('data:image/svg+xml;utf8,…');
}

article:after {
  display: block;
  position: relative;
  top: 50px;
  /* Scroll bottom */
  content: url('data:image/svg+xml;utf8,…');
}

虽然这种实现方式达到了预期效果,但使用两个伪元素和三个独立的SVG文件显得笨拙。然而,通过采用border-image、单个SVG文件且不使用伪元素的方法,不仅更显优雅,还显著减少了实现该效果所需的代码量。

我首先创建了一个完整的平板电脑形状的SVG文件:

图8:CSS border-image 的神奇用法我计算出了四条切割线的位置:

图9:CSS border-image 的神奇用法随后,我将这张单一SVG插入文章边框:首先选定源文件,对图像进行切片处理,并将上下边缘设置为stretch ,左右边缘设置为round

article {
  border-image-slice: 150 95 150 95 fill;
  border-image-width: 150px 95px 150px 95px;
  border-image-repeat: stretch round;
  border-image-source: url('data:image/svg+xml;utf8,…');
}

最终呈现出一种灵活的纸卷效果,能够适配视口宽度以及任意数量或类型的内容。

主页叠加层

我最后的挑战是实现为迈克·沃斯主页设计的动作感十足的图形。该设计包含前景SVG元素——迈克的猩猩吉祥物,以及一个具有缩放效果的背景图形:

图10:CSS border-image 的神奇用法

<section>
  <!-- content -->
  <div>...</div>

  <!-- ape -->
  <div>
    <svg>…</svg>
  </div>
</section>

我将该section 定义为其子元素的位置上下文:

section {
  position: relative;
}

然后,我将一个伪元素设置为绝对定位,并在其背景中添加了缩放图形:

section:before {
  content: "";
  position: absolute;
  z-index: -1;
  background-image: url('data:image/svg+xml;utf8,…');
  background-position: center center;
  background-repeat: no-repeat;
  background-size: 100%;
}

我希望这个图形能旋转并为面板增添微妙的动态效果,因此我为伪元素应用了一个简单的CSS动画:

@keyframes spin-bg {
  from { transform: rotate(0deg); }
  to { transform: rotate(360deg); }
}

section:before {
  animation: spin-bg 240s linear infinite;
}

接下来,我添加了一个CSS遮罩,使缩放图形的边缘逐渐融入背景。CSS的mask-image属性用于指定遮罩层图像,可以是PNG图像、SVG图像或遮罩,也可以是CSS渐变:

section:before {
  mask-image: radial-gradient(circle, rgb(0 0 0) 0%, rgb(0 0 0 / 0) 60%);
  mask-repeat: no-repeat;
}

此时,你或许会好奇边框图像在该设计中的应用场景。为增强图形交互性,我希望在用户与之互动时降低其opacity值,并通过添加彩色渐变叠加层改变其颜色。应用叠加层到元素最简单却鲜少使用的方法之一就是border-image。首先,我设置了默认opacity值并添加了简短的transition效果:

section:before {
  opacity: 1;
  transition: opacity .25s ease-in-out;
}

然后,在悬停时,我将不透明度降低到0.5,并添加了border-image::

section:hover::before {
  opacity: .5;
  border-image: fill 0 linear-gradient(rgba(0,0,255,.25),rgba(255,0,0,1));
}

你或许会疑惑为何我未采用先前说明的其他border-image值,因此我将剖析该声明。首先是border-image-slice值,其中零像素确保八个角与边界保持空白。fill关键字则确保中间区域填充线性渐变。其次,border-image-source采用CSS线性渐变实现蓝红渐变效果。浏览器会将此border-image渲染在背景之上、内容之后的位置。

结论:重新审视border-image属性

border-image属性是一款功能强大却常被忽视的CSS工具,它提供了惊人的灵活性。通过对图像进行分割、重复和偏移设置,您只需极少代码即可创建复杂边框、装饰元素,甚至动态叠加层。

在为Mike Worth网站进行设计时,border-image展现出无可替代的价值——它在提升性能的同时,完美保留了高度图形化的美学效果。无论是应用于按钮、交互式覆盖层还是大型图形元素,border-image都能创造视觉冲击力十足的设计,且无需依赖额外标记或多重资源。

若您尚未尝试border-image,现在正是重新发掘其潜力并将其纳入设计工具箱的绝佳时机。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注


京ICP备12002735号