《CSS揭秘》精读笔记之背景与边框

346 阅读19分钟

半透明边框

难题

假设我们想给一个容器设置一层白色背景和一道半透明白色边框,我们最开始的尝试可能是这样的。

border: 10px solid hsla(0, 0%, 100%, .5);
background: white;
image.png

蛤?我们的边框去哪里了捏???

解决方案

我们尝试着添加一个红色的虚线边框

border: 10px dashed red;
image.png

奥?!原来被我们的背景吃掉了。默认情况下,背景会延伸到边框所在区域的下层。

我们可以通过 background-clip 属性来调整上述默认行为所带来的不便。这个属性的初始值是 border-box,意味着背景会被元素的 border box(边框的外沿框)裁切掉。如果不希望背景侵入边框所在的范围,我们要做的就是把它的值设为 padding-box,这样浏览器就会用内边距的外沿来把背景裁切掉。

  border: 10px solid hsla(0, 0%, 100%, .5);
  background: white;
  background-clip: padding-box;

完美效果

image.png

多重边框

难题

实现起来经常需要用多个元素来模拟多重边框,会污染我们的结构。

box-shadow 方案

我们可以给其添一个“投影”,一个正值的扩张半径加上两个为零的偏移量以及为零的模糊值,得到的“投影”其实就是一道边框。

  background: yellowgreen;
  box-shadow: 0 0 0 30px #655;
image.png

box-shadow 支持逗号分隔语法,我们可以创建任意数量的投影。
我们可以非常轻松地在上面的示例中再加上一道 deppink 颜色的“边框”。

  background: yellowgreen;
  box-shadow: 0 0 0 30px #655, 0 0 0 45px deeppink;
image.png

唯一需要注意的是,box-shadow是层层叠加的,第一层投影位于最顶层,以此类推。
因此我们前面 deppink 颜色的“边框”的实际宽度为15px(45px-30px)
我们依然可以在这些“边框”的底下加一层常规的投影:

  background: yellowgreen;
  box-shadow: 0 0 0 30px #655, 
              0 0 0 45px deeppink,
              10px 10px 10px 45px hsla(0, 0%, 0%, .6);
image.png

投影的行为跟边框 不完全一致 ,因为它不会影响布局,而且也不会受到 box-sizing 属性的影响。(因为根本就没有真正的边框嘛,border-width 是零呀!!!)

  box-sizing: border-box;
  box-sizing: content-box;

木有丝毫的区别。

不过,你还是可以通过内边距或外边距(这取决于投影是内嵌的还是外扩的)来额外模拟出边框所需要占据的空间。不然就会这样:

  background: yellowgreen;
  box-shadow: 0 0 0 30px #655, 
              0 0 0 45px deeppink,
              10px 10px 10px 45px hsla(0, 0%, 0%, .6);
  /* margin: 45px; */
image.png

“边框”被卡没了呢~

上述方法所创建出的假的“边框”出现在元素的 外圈 。它们并不会响应鼠标事件,比如悬停或点击。(见下面 demo)如果这一点非常重要,你可以给 box-shadow 属性加上 inset 关键字,来使投影绘制在元素的 内圈 。请注意,这时你需要增加额外的内边距来腾出足够的空隙。

outline 方案

在某些情况下,我们可能只需要 两层边框 ,那就可以先设置一层常规边框,再加上 outline(描边)属性来产生外层的边框。代码可以这样写:

  background: yellowgreen;
  border: 30px solid #655;
  outline: 15px solid deeppink;
image.png

圆角也是可以正常实现的捏

  background: yellowgreen;
  border: 30px solid #655;
  outline: 15px solid deeppink;
  border-radius: 10px;
image.png

这种方法的一大优点是非常灵活,不像上面的 box-shadow 方案只能模拟实线边框(假设偶们需要产生虚线边框效果,box-shadow 就没辙了)。
描边的另一个好处在于,你可以通过 outline-offset 属性来控制它跟元素边缘之间的间距,这个属性甚至可以接受负值。 我们可以利用其实现一个简单的缝边效果。

image.png

灵活的背景定位

难题

针对容器的某个角对背景图片做偏移定位,使用 CSS 2.1 来做到这一点会很麻烦。但我们现在已经有了更好的解决方案。

background-position 方案

假如我们希望让背景图片同时和右边和底边保持一定的偏移量,我们可以这样尝试:

  background: url('juejin.svg') no-repeat white;
  background-position: right 40px bottom 20px;

image.png 我们也可以简写成:

  background: url('juejin.svg') no-repeat right 40px bottom 20px hsl(0, 0%, 95%);

如果担心浏览器兼容性问题,我们也可以提供一个回退方案:

  background: url('juejin.svg') no-repeat right bottom hsl(0, 0%, 95%);
  background-position: right 40px bottom 20px;

background-origin 方案

在给背景图片设置距离某个角的偏移量时,有时候我们希望偏移量与容器的内边距一致。如果采用上面提到的 background-position 方案,代码看起来会是这样的:

  padding: 20px;
  background: url('juejin.svg') no-repeat right 20px bottom 20px hsl(0, 0%, 95%);

这个方案一定是可行的,但它不够 DRY(Don't Repeat Yourself)(傲娇 ┑( ̄▽  ̄)┍ ):每次改动内边距的值是,我们都需要在三个地方更新这个值!!!就很不 elegant ~
默认情况下, background-position 是以 padding box 为基准的(闭着眼睛也猜得到),我们可以通过 background-origin 属性来实现:

  padding: 20px;
  background: url('juejin.svg') no-repeat right  bottom  hsl(0, 0%, 95%);
  background-origin: content-box;

image.png
也是可以简写的捏

background: url('juejin.svg') no-repeat right bottom content-box padding-box hsl(0, 0%, 95%);

但是要注意 <box> 层属性一定要写全,如果只写一个值的话 background-originbackground-clip 属性会同时应用,然后就:
image.png
寄~

边框内圆角

有时我们需要一个容器,只在内侧有圆角,而边框或描边的四个角在外部仍然保持直角的形状。
我们可以用两个元素实现这个效果,这并没有什么特别的。

  <div id="target">
    <div />
  </div>
 #target {
    background: #655;
    padding: .8rem;
    width: 25rem;
  }

#target > div {
  background: tan;
  border-radius: .8rem;
  height: 15rem;
}
image.png

条纹背景

难题

不论是在网页设计中,还是在其他传统媒介中(比如杂志和墙纸等),各种尺寸、颜色、角度的条纹图案在视觉设计中无处不在。如果可以直接在CSS中创建条纹图案,那该有多棒啊!

解决方案

假设我们有一条基本的垂直线性渐变,就像这样:

  background: linear-gradient(#fb3, #58a);
image.png

现在,让我们试着逐渐把这两个色标拉近

  background: linear-gradient(#fb3 20%, #58a 80%);
image.png
  background: linear-gradient(#fb3 40%, #58a 60%);
image.png

你是不是开始好奇,如果我们把两个色标重合在一起会发生什么?

  background: linear-gradient(#fb3 50%, #58a 50%);
image.png

从上图中可以看到,已经没有任何渐变效果了,只有两块实色,个占据了 background-image 一半的面积。本质上,我们已经创建了两条巨大的水平条纹。
因为渐变是一种由代码生成的图像,我们能像对待其他任何背景图像那样对待它,而且还可以通过 background-size 来调整尺寸:

  background: linear-gradient(#fb3 50%, #58a 50%) no-repeat;
  background-size: 100% 100px;
  ...
image.png

上图中可以看到,我们把这两条条纹的高度都缩小到了 100px .
由于背景在默认情况下是重复平铺的,整个容器其实已经被填满了水平条纹。

image.png

我们还可以用相同的方法来创建不等宽的条纹,只需调整色标的位置即可:

  background: linear-gradient(#fb3 30%, #58a 30%);
  background-size: 100% 100px;
image.png

为了避免每次改动条纹宽度时都要修改两个数字,我们可以再次从规范那里找到捷径

颜色终止列表中颜色的终止点应该是依次递增的。如果后面的颜色终止点小于前面颜色的终止点则后面的会被覆盖,从而创建一个硬转换。
---- mdn web docs(developer.mozilla.org/zh-CN/docs/…

这意味着,如果我们把第二个色标的位置值设置为 0,那它的位置就总是会被浏览器调整为前一个色标的位置值,这个结果正是我们想要的。
因此,下面的代码会产生跟上图完全一样的背景,但代码会更加 DRY:

  background: linear-gradient(#fb3 30%, #58a 0);
  background-size: 100% 100px;

我们也可以生成多种颜色的条纹

  background: linear-gradient(#fb3 33.3%, #58a 0, #58a 66.6%, yellowgreen 0);
  background-size: 100% 100px;
image.png

垂直条纹

水平条纹都会了,那竖直条纹应该也不会太难吧

  background: linear-gradient(to right /* or 90deg */ ,#fb3 50%, #58a 50%);
  background-size: 100px 100%;
image.png

斜向条纹

在完成了水平和数值条纹之后,我们可能会顺着往下想:如果我们再次改变 background-size 的值和渐变的方向,是不是就可以得到斜向(比如45°)的条纹方案呢?比如这样:

  background: linear-gradient( 45deg ,#fb3 50%, #58a 50%);
  background-size: 50px 50px;
image.png

可以发现,这个办法行不通。原因在于我们只是把每个 “贴片”内部的 渐变旋转了45°,而不是把整个重复的背景都旋转了。

image.png

来看看我们要怎么做吧
首先,我们需要让单个贴片包含4条条纹,而不是两条,只有这样才有可能做到无缝拼接,因此我们需要增加一些色标:

image.png

把这些贴片组合起来:

image.png

我们实现了我们想要的效果。

更好的斜向条纹

在前面的段落中展示的方法还不够灵活。假设我们想让条纹以一些其他的角度倾斜,如果我们只是把渐变的角度改一下,那么结果看起来会相当糟糕。

image.png

幸运的是,我们还有更好的方法来创建斜向条纹。linear-gradient()radial-gradient 还各有一个循环式的加强版:repeating-linear-gradient()repeating-radial-gradient()
他的色标是无限循环重复的,直到填满整个背景!!!下面是一个重复渐变的例子:

  background: repeating-linear-gradient(45deg, #fb3, #58a 50px);
image.png

重复线性渐变完美使用于----条纹效果!!!

斜向条纹背景也可以由重复渐变来生成:

  background: repeating-linear-gradient(45deg, #fb3, #fb3 25px, #58a 0, #58a 50px);
image.png

第一个明显的好处就是减少了重复:我们需要改动任何颜色只需要修改两处,而不是原来的三处。
另外一点也很重要,我们现在是在渐变的色标中指定长度,而不是原来的 background-size。这里的 background-size 是每个“贴片”的大小,所以我们需要经过一系列复杂的计算才能根据我们想要的条纹宽度计算出 background-size 的大小。而现在的这些色标的长度是直接在 渐变轴 上进行度量的,所以就是真正的条纹宽度。
不过最大的好处在于,我们现在可以随心所欲的改变斜向条纹的角度啦!!!

  background: repeating-linear-gradient(25deg, #fb3, #fb3 25px, #58a 0, #58a 50px);
image.png
  background: repeating-linear-gradient(70deg, #fb3, #fb3 25px, #58a 0, #58a 50px);
image.png

灵活的同色系条纹

在大多数情况下,我们想要的条纹图案并不是由差异极大的几种颜色组成的,这些颜色往往属于同一色系,只是在透明度方面有着轻微的差异。
举个栗子,我们来康康这个条纹图案:

  background: repeating-linear-gradient(30deg, #79b, #79b 25px, #58a, 0, #58a 50px);
image.png

在上图中可以看到,条纹是由一个主色调和它的浅色变体所组成的。但是,这两种颜色之间的关系在代码中并没有体现出来。此外,如果我们想要改变这个条纹的主色调,甚至需要修改四处!
不过我们可以使用类似图层叠加的方式来实现:

  background: #58a;
  background-image: repeating-linear-gradient(30deg,
                      hsla(0, 0%, 100%, .1),
                      hsla(0, 0%, 100%, .1) 25px,
                      transparent 0,
                      transparent 50px);
image.png

结果看起来和上一种方法是一模一样滴,但我们现在只需要修改一个地方就可以改变所有颜色啦!

复杂的背景图案

在本篇攻略中,我们来深入讨论如何创建那些简单而常用的图案。

网格

我们可能首先想到的就是把水平和垂直的条纹叠加起来,从而得到各种各样的网格。比如:

  background: white;
  background-image: linear-gradient(90deg, rgba(200, 0, 0, .5) 50%, transparent 0),
                    linear-gradient(rgba(200, 0, 0, .5) 50%, transparent 0);
  background-size: 60px 60px;
image.png

在某些情况下,我们希望 网格中每个格子的大小可以调整,而网络线条的粗细同时保持固定 。举例来说,类似图纸辅助线的网格就是这种情况。这是一个非常好的例子,展示了 使用长度而不是百分比 作为色标的场景:

  background: #58a;
  background-image: linear-gradient(white 2px, transparent 0),
                    linear-gradient(90deg, white 2px, transparent 0);
  background-size: 60px 60px;
image.png

主色调在这里很好的起到了回退颜色的作用。
该网格是一个很好的例子,说明图案可以用合理的、可维护的 CSS 代码生成:

  • 当需要改变网格的尺寸、线宽或者任何颜色时,我们可以很容易地找到需要编辑的地方。
  • 在改变图案的任何一个要素时,我们不需要做大量的修改,而是只需修改一到两个值。
  • 代码很简短,只有四行,共计 170 字节。SVG 的代码不见得会比它更短。

我们甚至可以把两幅不同线宽、不同颜色的网格图案叠加起来,得到一个更加逼真的蓝图网格:

  background: #58a;
  background-image: 
    linear-gradient(white 2px, transparent 0),
    linear-gradient(90deg, white 2px, transparent 0),
    linear-gradient(hsla(0, 0%, 100%, .3) 1px, transparent 0),
    linear-gradient(90deg, hsla(0, 0%, 100%, .3) 1px , transparent 0);
  background-size: 75px 75px, 75px 75px,
                   15px 15px, 15px 15px;
image.png

波点

径向渐变能够创建最简单的图案就是圆点阵列:

  background: #655;
  background-image: radial-gradient(tan 30%, transparent 0);
  background-size: 60px 60px;
image.png

实话说,目前这个样子还不是很实用。听我说,你先别急,我们可以生成两层圆点阵列图案,并把它们的背景定位错开,这样就可以得到真正的波点图案了:

  background: #655;
  background-image: radial-gradient(tan 30%, transparent 0),
                    radial-gradient(tan 30%, transparent 0);
  background-size: 60px 60px;
  background-position: 0 0, 30px 30px;
image.png

请注意,为了达到效果,第二层背景的偏移定位值必须是贴片宽高的一半。
这样的话,如果我们想改动贴片尺寸,就要同时修改四处!!!
如果我们使用预处理器,就可以更优雅的实现它:

@mixin polka($size, $dot, $base, $accent) {
  background: $base;
  background-image: radial-gradient($accent $dot, transparent 0),
                    radial-gradient($accent $dot, transparent 0);
  background-size: $size $size;
  background-position: 0 0, $size/2 $size/2;
}

用的时候只需要这样调用就行啦:

  @include polka(60px, 30%, #655, tan);

棋盘

在 CSS 中创建棋盘图案是可能的,只不过实现过程可能比我们想象中的要“绕”一点(也可能是很多)
如果我们想像之前一样通过图片的重复平铺来实现它,那么单个贴片应该是这样的:

image.png

也就是上图虚线所标示的范围。 它貌似可以在 CSS 中很容易地重现出来:只需要创建两个不同背景定位的方块就可以了,没错吧?然而并非如此。
是的,在技术上,我们可以用 CSS 渐变来创建平铺的方块,但每个方块的周围是不会有空隙的。 因为,linear-gradient() 函数构建一系列垂直于渐变线的着色线,每一条着色线的颜色则取决于与之垂直相交的渐变线上的色点。是着色线!着色线!线!!!啊喂,是一条线,总不能着色着一半,另一半不要了吧 ╮(╯▽╰)╭

这里的窍门在于 用两个直角三角形来拼合出我们想要的方块

  background: #eee;
  background-image: linear-gradient(45deg, #bbb 50%, transparent 0);
  background-size: 60px 60px;
image.png

嗯mmmmm 这样似乎不行。两个三角形拼一下似乎只会得到一片实色。
如果我们 把色标的位置从 50% 改为 25% 呢:

  background: #eee;
  background-image: linear-gradient(45deg, #bbb 25%, transparent 0);
  background-size: 60px 60px;
image.png

与此类似,如果我们把色标的顺序反转,就可以创建相反方向的三角形:

  background: #eee;
  background-image: linear-gradient(45deg, transparent 75%, #bbb 0);
  background-size: 60px 60px;
image.png

你能猜到把他们组合在一起会发生什么吗?

  background: #eee;
  background-image: linear-gradient(45deg, #bbb 25%, transparent 0),
                    linear-gradient(45deg, transparent 75%, #bbb 0);
  background-size: 60px 60px;
image.png

乍看起来,这样的效果似乎并不是我们想要的。但是,我们只需要 把第二层渐变在水平和竖直方向均移动贴片长度的一半 ,就可以它们拼合成一个完整的方块:

  background: #eee;
  background-image: linear-gradient(45deg, #bbb 25%, transparent 0),
                    linear-gradient(45deg, transparent 75%, hsl(0, 0%, 65%) 0);
  background-position: 0 0, 30px 30px;
  background-size: 60px 60px;
image.png

我们适当的将第二层的颜色调深了一点,这样更加直观。

这就是 棋盘的一半!!! 接下来就变得简单了:

  background: #eee;
  background-image: 
    linear-gradient(45deg, #bbb 25%, transparent 0),
    linear-gradient(45deg, transparent 75%, #bbb 0),
    linear-gradient(45deg, #bbb 25%, transparent 0),
    linear-gradient(45deg, transparent 75%, #bbb 0);
  background-position: 0 0, 30px 30px,
                       30px 30px, 60px 60px;
  background-size: 60px 60px;
image.png

我们实现啦!!!
同时我们可以将四层简化为两层:

  background: #eee;
  background-image: 
    linear-gradient(45deg,
    rgba(0, 0, 0, .25) 25%, transparent 0,
      transparent 75%, rgba(0, 0, 0, .25) 0),
    linear-gradient(45deg,
    rgba(0, 0, 0, .45) 25%, transparent 0,
      transparent 75%, rgba(0, 0, 0, .45) 0);
  background-position: 0 0, 30px 30px;
  background-size: 60px 60px;
image.png

为了清晰,同样将第二层的颜色加重了一些。

现在我们把四层渐变简化成了两层渐变,但代码仍然跟以前一样 WET(We Enjoy Typing,表示繁琐重复、无法维护的代码)。为了改变棋盘的主色调或者是方格尺寸,我们还是需要修改四个地方。在这一点上,使用预处理器来简化一下我们的代码可能是个不错的选择:

@mixin checkerboard($size, $base, $accent: rgba(0, 0, 0, .25)) {
  background: $base;
  background-image:
    linear-gradient(45deg,
      $accent 25%, transparent 0,
      transparent 75%, $accent 0),
    linear-gradient(45deg,
      $accent 25%, transparent 0,
      transparent 75%, $accent 0);
  background-position: 0 0, $size $size;
  background-size: 2 * $size 2 * $size;
}

// 调用时是这样的
  @include checkerboard(30px, white);
image.png

在任何情况下,这样的代码都不能算少。所以转到 SVG 方案可能是更好的选择,这边暂时就不多赘述了。

伪随机背景

难题

重复平铺的几何图案很美观,但看起来可能有一些呆板。
其实自然界中的事物都不是以无限平铺的方式存在的。他们既会因排列整齐而产生美感,也会因稍稍错落而透出情趣。

“当你注意到一个有辨识度的特征(比如木纹上的节疤)在以固定的规律循环重复时,那它试图营造的自然随机性就会立刻崩塌。”
———— Alex Walker,《蝉原则对网页设计的重要性》

重现大自然的随机性是一个挑战,因为 CSS 本身没有提供任何随机功能。
假设我们想得到不同颜色和不同宽度的竖直条纹,我们可能会这么做:

  background: linear-gradient(90deg,
                #fb3 15%, #655 0, #655 40%,
                #ab4 0, #ab4 65%, hsl(20, 40%, 90%) 0);
  background-size: 160px 100%;
image.png

我们可以看到,这个重复规律是非常明显的。有什么更好的办法吗?

解决方案

为了更真实地模拟条纹的随机性,我们接下来可能会想到,把这组条纹从一个平面拆散为多个图层:一种颜色为底色,另三种颜色作为条纹,然后再让条纹以不同地间隔进行重复平铺,再用 background-size 来控制条纹的间距。

  background: hsl(20, 40%, 90%);
  background-image: 
    linear-gradient(90deg, #fb3 20px, transparent 0),
    linear-gradient(90deg, #ab4 40px, transparent 0),
    linear-gradient(90deg, #655 40px, transparent 0);
  background-size: 160px 100%, 120px 100%, 80px 100%;
image.png

因为最顶层贴片的重复规律最容易被察觉(它没有被任何东西遮挡),我们应该把平铺间距最大地贴片安排在最顶层(在我们的例子中是橙色条纹)

这样的结果明显更有随机的感觉,但如果自行观察的话,仍然可以看出重复的片段(上图中虚线方框标示)
这个组合图案中第一个贴片的终点,就是各层背景图案以不同间距重复次数后再次统一对齐的点。因此,这里贴片的尺寸实际上就是所有 background-size 的最小公倍数。
奥~ 让我们翻找一下小学的数学知识,我们知道为了让最小公倍数最大化,这些数字最好都是互斥的。
也就是说我们要尽量选择质数,因为他和任意不是自己倍数的数字都是互斥滴~ 于是我们可以这样改造我们的代码:

  background: hsl(20, 40%, 90%);
  background-image: 
    linear-gradient(90deg, #fb3 22px, transparent 0),
    linear-gradient(90deg, #ab4 46px, transparent 0),
    linear-gradient(90deg, #655 82px, transparent 0);
  background-size: 83px 100%, 127px 100%, 163px 100%;

这样我们的贴片大小就是 83 * 127 * 163 = 1,718,163 像素,不会有人的屏幕的分辨率有这么大吧,不会吧~ 不会吧~

image.png

连续的图像边框

难题

有时我们想把一幅图案或图片 应用为边框,而不是背景
这个时候,你的脑子里可能会有一个声音跳出来高声尖叫:“ border-image !用 border-image !只要有 border-image, 这根本就不是哟个问题!” 听我说,你先别急 我们先来回忆一下 border-image 是如何工作的。
它的基本原理就是 九宫格伸缩法: 把图片切割成九块,然后把它们应用的到元素边框相应的边和角。

工作原理记不清的的猛戳这里!!!

问题在于,我们并不想让图片的某个特定部分固定在拐角处;而是希望出现在拐角处的图片区域是随着元素宽高和边框厚度变化而变化的。

  border: 40px solid transparent;
  border-image: url("mountain-night.jpg") 33.4% stretch;
  border: 40px solid transparent;
  border-image: url("mountain-night.jpg") 33.4% round;
image.png image.png

这似乎都不是我们想要的。接下来我们要怎么办?

最简单的方法就是使用两个 HTML 元素:

<div id="mountain-night">
  <div />
</div>
#mountain-night {
  background: url("mountain-night.jpg");
  background-size: cover;
  padding: 40px;
}

#mountain-night > div {
  background: white;
}
image.png

这个方法确实可以生成“边框”效果,但需要一个额外的 HTML 元素。这显然不够理想。

解决方案

我们主要的思路就是 在背景图片上,再叠加一层纯白色的实色背景
根据这个思路,我们可以这样写:

  padding: 40pxem;
  border: 40px solid transparent;
  background: linear-gradient(white, white),
              url("mountain-night.jpg");
  background-size: cover;
  background-clip: padding-box, border-box;
image.png

嗯?似乎有一种怪异的拼接效果???
其实是因为决定背景原点位置的属性 background-origin 的值默认是 padding-box 我们只需要将他修改为 border-box 就可以啦

  padding: 40pxem;
  border: 40px solid transparent;
  background: linear-gradient(white, white),
              url("mountain-night.jpg");
  background-size: cover;
  background-clip: padding-box, border-box;
  background-origin: border-box;
image.png

这样就完美了。我们也可以简写:

  padding: 40px;
  border: 40px solid transparent;
  background: 
    linear-gradient(white, white) padding-box,
    url("https://s3.bmp.ovh/imgs/2022/10/30/95b8e6ebafa731c5.jpg") border-box
    0 0 / cover;

老式信封样式

  padding: 1em;
  border: .8em solid transparent;
  background: linear-gradient(white, white) padding-box,
              repeating-linear-gradient(-45deg,
                hsl(360, 50%, 50%) 0, hsl(360, 50%, 50%) 12.5%,
                transparent 0, transparent 25%,
                #58a 0, 37.5%,
                transparent 0, transparent 50%)
                0 / 4em 4em;

也可以通过 border-image 来实现:

  padding: 1em;
  border: 20px solid transparent;
  border-image: 20 repeating-linear-gradient(-45deg,
                     hsl(360, 50%, 50%) 0, hsl(360, 50%, 50%) .8em,
                     transparent 0, transparent 1.6em,
                     #58a 0, #58a 2.4em,
                     transparent 0, transparent 3.2em);
image.png

不过 border-image 方法存在一些问题

  • 每当我们改变 border-image-slice 时,都需要同时修改 border-width 来让它们互相匹配。
  • 由于我们不能再 border-image-slice 属性中使用 em 单位,只能把边框厚度设定为像素单位
  • 条纹的宽度需要在色标的位置信息中写好,因为我们在改变条纹宽度时,需要修改四处。
  • 由于我们真实的边框是透明的,所以它并不支持圆角效果(虽然在这个例子中可能没那么重要)

蚂蚁行军边框效果

#marching-ants {
  border: 2px solid transparent;
  background: 
    linear-gradient(white, white) padding-box,
    repeating-linear-gradient(-45deg,
      black 0, black 25%, white 0, white 50%
    ) 0 / 12px 12px;
    animation: ants 12s linear infinite;
}

@keyframes ants { to { background-position: 100% } }
image.png

这段代码不是很难理解。

传统脚注效果

  border-top: .2em solid transparent;
  border-image: linear-gradient(90deg, currentColor 4em, transparent 0) 100% 0 0;
image.png

写在最后

各位热爱前端技术的小伙伴们你们好啊。既然能读到这里就说明这篇笔记似乎没有那么枯燥(大概吧)。笔记间掺杂了那么一丢丢的个人理解(希望没有打乱原著的行文思路)。如你所见《CSS揭秘》这本书并不是一本简单的 cookbook, 期间凝聚了 Lea Verou 大师对 CSS 的理解,原著还是值得静下心来好好拜读一番的。

最后,如果帮助到各位小伙伴的话,记得点个赞呦。如果有错误还望大家指出。

那,我们下章见啦!