Featured image of post 利用 CSS 实现半透明边框和多重边框

利用 CSS 实现半透明边框和多重边框

这篇文章整理了半透明边框、多重边框等的实现方式,供大家参考。学习这些例子还能帮助你深入掌握CSS中与边框相关的属性,包括 `border`,`outline`,`box-shadow` 等。

背景

《CSS 揭秘》这本书的第 2 章中讲到了各类特殊边框效果的实现,包括半透明边框、多重边框等,这篇文章对此进行了整理,大家在平常的开发过程中如果有相应的需求可以参考。学习这些例子还能帮助你深入掌握 CSS 中与边框相关的属性,包括borderoutlinebox-shadow等。

一些更加复杂的边框效果仅靠 CSS 无法实现,我的这篇文章讲解了用 SVG 实现动态渐变色边框的方法,需要的朋友也可以参考。

半透明边框

半透明边框的效果如下图所示:

图中的图片边框是由设计师给出的一张完整图片的边缘部分。要实现这样的一个效果,我们可以考虑嵌套两层div,外层div将图片设为背景,负责图片的展示;内层div设置白色的背景和半透明的边框,并负责文字的展示。写成代码大概是这个样子:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
<style>
  .container {
    // ...
    background-image: url("...");
  }
  .inner {
    // ...
    background-color: white;
    border: 10px solid hsla(0, 0%, 100%, 0.5);
  }
</style>
<div class="container">
  <div class="inner">Hello World</div>
</div>

运行之后会发现效果并不符合预期,半透明的边框并没有出现。

打开开发者工具查看一下会发现原本应该是半透明边框的位置显示了纯白色。

这是因为元素的背景默认会延伸到边框的下方,而我们的边框又是半透明的白色,背景颜色的白色透过半透明的白色展示出来的仍然是纯白色。要更好地理解这一点,我们不妨把背景颜色改为黑色试试:

那一圈浅灰色正是边框的半透明色叠加黑色的背景颜色的结果。

要想解决这个问题,就得想办法让背景颜色不要延伸到边框所在的位置。background-clip属性可以帮我们实现这个目标,该属性用于控制元素背景的渲染范围。其取值包括border-box,padding-boxcontent-box,其默认值是border-box。聪明的你一定不难想出这几个属性各自的作用,padding-box可以让背景覆盖除了边框之外的区域,content-box可以让背景只覆盖元素盒子的content部分。

(如果不知道contentpaddingborder对应的区域,请复习盒模型的知识

回到我们的代码中,只要加上一行background-clip: padding-box就可以实现一开始想要的那种效果了。此时背景的纯白色不再延伸到边框处,半透明的边框下展示的是背景图片。

多重边框

有时候设计师会要求我们给一个元素套上多个边框,但border属性只支持一层边框。一种比较简单的想法是嵌套多个div元素,但这样并不是很优雅,对于性能也会有所影响。我们可以利用box-shadowoutline属性来更加优雅地实现多重边框效果。

使用 box-shadow 实现

我们通常使用box-shadow来实现阴影效果,一个典型的box-shadow代码如下:

1
2
background-color: yellowgreen;
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.6);

其中前两个参数对应了阴影的 x 轴和 y 轴的偏移量,第三个参数是阴影的模糊半径,可以简单地理解为阴影的大小,最后一个参数指定了阴影的颜色。这里我们得到了一个向下偏移了 5px,扩张半径为 15px 的灰色阴影。

但其实box-shadow还有另外一个数值参数,也就是其扩张半径。可以认为box-shadow是由无渐变投影和有渐变阴影两部分构成的,其中无渐变部分默认的大小就是元素本身的大小。扩张半径可以使无渐变部分的大小在元素本身大小的基础上增长,模糊半径控制了渐变阴影部分的大小。

平时我们使用阴影的时候通常都只是希望得到一个渐变的效果,所以不需要声明扩张半径的值(其默认值为 0),只要阴影的渐变部分就好。但我们也可以反过来想,如果把模糊半径声明为 0,扩张半径声明为某个正值,再把偏移量都设为 0,得到的效果就会像是元素的边框。

1
box-shadow: 0 0 0 10px #655;

这里我们利用box-shadow模拟生成了一个 15px 的灰色边框的效果。

一个元素是可以同时拥有多个box-shadow的,所以我们如果想要多重边框,只要再声明更多的box-shadow就可以了。

1
2
box-shadow: 0 0 0 10px #655, 0 0 0 15px deeppink,
  0 2px 5px 15px rgba(0, 0, 0, 0.6);

这里我们给元素设置了三个box-shadow,第一个对应内层的灰色边框,第二个对应外层的粉色边框,第三个是元素最外层的阴影。

有一点要注意的是,box-shadow是相互交叠的,所以外层的边框必须要写在内层边框之后,在设置宽度时要把内层边框的宽度考虑进去。例如这里我们想要一个 5px 宽的粉色边框,因为内层的灰色边框已经占据了 10px,所以其宽度应该是 10 + 5 = 15px。

box-shadow多重边框方案在大部分情况下都非常好用,但它有两个小问题:

  • box-shadow并不会被计入元素的box-sizing中,这可能会导致元素大小计算出现问题。可以通过利用margin或者padding来模拟边框占据的空间来解决这个问题。
  • box-shadow是处在元素之外的,所以它不会捕捉相关的指针事件,例如点击、hover 等。可以通过inset关键字来让box-shadow被放置在元素之内,这时你需要添加额外的padding来让边框出现在正确的位置。

使用 outline 实现

如果你只需要双层边框,可以直接用常规的border属性加上outline属性来实现。相比于box-shadowoutline有更加灵活的样式,例如虚线。同时,我们还可以通过outline-offset控制outline距离元素边界的距离,这个距离可以是负值。我们可以借此来实现一些有趣的效果:

1
2
3
4
border-radius: 10px;
outline: white dashed 1.5px;
outline-offset: -10px;
background-color: #4e403d;

利用outline来实现刚刚的例子的代码如下:

1
2
3
background: yellowgreen;
border: 10px solid #655;
outline: 15px solid deeppink;

参考资料

CSS 揭秘 - Lea Verou

(本文作者 wzkMaster)

comments powered by Disqus
Built with Hugo
Theme Stack designed by Jimmy