多边框
最后更新于:2022-04-01 03:43:31
> 原文出处:http://www.w3cplus.com/css3/css-secrets/multiple-borders.html
## 问题
[Backgrounds & Borders Level 3](http://www.w3.org/TR/css3-background/) 还是一份草案的时候,CSS WG 就在是否支持多重边框的问题进行了大量的探讨,就像是讨论多重背景图片一样。不幸的是,当时认为多重边框的用处并不大,即使需要也可以使用[`border-image`](http://www.w3cplus.com/content/css3-border-image)属性来模拟。不过,WG显然忘记了在 CSS 代码中灵活地调整边框,才是我们需要的,现在开发者只能使用一些Hack手段来模拟多重边框,比如使用多重元素的嵌套来模拟多重边框。现在,我将告诉你一些更优秀的方法,无需使用多余的标签即可实现多重边框。
## box-shadow解决方案
现在,大多数的时候都用[`box-shadow`](http://www.w3cplus.com/content/css3-box-shadow)来创建阴影。不过,很少有人知道它还接受[第四个参数(spread)](http://www.w3cplus.com/css3/css3-box-shadows-unnoticed-spread),该参数可以缩放阴影的范围。比如下面的示例,我们创建了一个水平和垂直偏移量为`0` 的阴影,它就使用了上述所说的第四个参数:
~~~
background: yellowgreen;
box-shadow: 0 0 0 10px #655;
~~~
效果如下图所示:
![多重边框](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2015-10-01_560cdb45ac962.png "多重边框")
*图注:使用 `box-shadow` 模拟边框线*
这还不够令人惊讶,因为它和我们使用 `border` 创建的边框差不多。不过,强大的是我们可以使用逗号来创建任意数量的阴影。所以,只需要继续添加阴影就可以实现多重阴影了,比如,添加一个颜色为 **deeppink** 的边框:
~~~
background: yellowgreen;
box-shadow: 0 0 0 10px #655, 0 0 0 15px deeppink;
~~~
唯一需要牢记的事情就是,`box-shadow` 属性是叠在一起的,第一个阴影总是位于最顶层,所以你需要调整阴影的大小。比如,在上一段代码中,我们希望最外层的边框为 `5px`,那么我们就可以设置一个 `15px`(`10px + 5px`) 的阴影。如果你需要,那么就可以为指定任意层次的阴影:
~~~
background: yellowgreen;
box-shadow: 0 0 0 10px #655,
0 0 0 15px deeppink,
0 2px 5px 15px rgba(0,0,0,.6);
~~~
除了下述的少数情况外,使用 `box-shadow` 的解决方案都很好用:
* 阴影并不是边框,它们并不占有实际的空间,也不能归属于 `box-sizing` 的范围。不过,你可以通过使用内边距或外边距(取决于阴影是内部的还是外部的)占据额外的空间来模拟。
* 上述示例模拟的边框是位于元素外部的。它不能捕获类似悬停和点击的鼠标事件。如果事件很重要,那么可以通过添加 `inset` 关键字让阴影出现在元素的内部。注意,你可能需要添加额外的内边距来扩充空间。
## outline的解决方案
在某些情况下,如果我们只需要两层边框,那么我们只需要一层常规的边框和一层`outline` 就可以实现。这也让我们的边框在样式上保持了足够的灵活性(比如我们想要一个虚线边框),但是使用 `box-shadow` 的话,我们只能模拟出实线边框。如下图所示:
![多重边框](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2015-10-01_560cdb45e55dc.png "多重边框")
*图注:使用 `box-shadow` 模拟两条轮廓线*
~~~
background: yellowgreen;
border: 10px solid #655;
outline: 15px solid deeppink;
~~~
使用 `outline` 的另一个好处就是,我们可以通过 `outline-offset` 控制 `outline` 到元素边框的距离,该属性甚至可以接受负值。这对很多效果都非常有用,如下图所示:
![多重边框](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2015-10-01_560cdb4b4a85b.png "多重边框")
*注:对于虚线样式的轮廓线,通过给 `outline-offset` 设置负值,创建了一个基础的缝纫效果 *
不过,这种方法也有一些限制:
* 就像起初说的那样,这种方法只能模拟两层边框,因为每个元素只能创建一个 `outline`。如果需要创建多重边框,那么只能使用 `box-shadow` 的方法。
* `border-radius` 并不能让 `outline` 呈现圆角效果,所以,即使你的边框是圆角的,`outline` 仍然是直角的(如下图所示)。注意,CSS WG 认为这是一个 bug,在未来`border-radius`可能可以将 `outline` 变为圆角。
* 根据 [CSS User Interface Level 3 specification](http://www.w3.org/TR/css3-ui/) 的说法:“`outliens` 可能并不是矩形。”虽然大多数情况下它看起来像是矩形,但是在你使用这一方法时,还是需要进行跨浏览器测试的。
![多重边框](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2015-10-01_560cdb4b71a90.png "多重边框")
*图注:通过`outline`创建的轮廓线并没有贴合元素的圆角,这个问题在未来可能会被修正*
## border-colors解决方案
[border-colors](http://www.w3cplus.com/content/css3-border-color)是一个独特的属性,从字面上来说就是为多边框而生,只可惜的是,到目前为止这仅是Gecko内核浏览器独有的属性。
如果不追究浏览器的兼容性,那么`border-colors`也可以实现多边框的效果。在具体使用时,需要分成四边边框来写:
~~~
-moz-border-top-colors: <color> <color> <color>*; /*顶边边框*/
-moz-border-right-colors:<color> <color> <color>*; /*右边边框*/
-moz-border-bottom-colors: <color> <color> <color>*; /*底边边框*/
-moz-border-left-colors: <color> <color> <color>*; /*左边边框*/
~~~
![多重边框](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2015-10-01_560cdb55a0f44.png "多重边框")
虽然这种方式也能实现多边框效果,但相比前两种解决方案而言要麻烦一些,来看一个简单示例:
~~~
border: 10px solid;
-moz-border-top-colors: red red red red green green green blue blue blue;
-moz-border-bottom-colors: red red red red green green green blue blue blue;
-moz-border-right-colors: red red red red green green green blue blue blue;
-moz-border-left-colors: red red red red green green green blue blue blue;
~~~
为了要实现三个颜色的多边框效果,`red`占`4px`,`green`占`3px`和`blue`点`4px`。需要大费周折。而且还不能直接写`border-colors`,因为浏览器不识别这样的属性。
除此之外,目前浏览器对这个属性支持度相当的弱。可以说,它只是Firefox的私有属性。
## 扩展阅读
* [Multiple Backgrounds and Borders with CSS 2.1](http://nicolasgallagher.com/multiple-backgrounds-and-borders-with-css2/)
* [Multiple Borders](https://css-tricks.com/snippets/css/multiple-borders/)
* [Multiple Borders with CSS](http://www.impressivewebs.com/multiple-borders-css/)
* [Multiple borders methods with CSS](https://carst.me/2011/08/multiple-borders-methods-css/)
## 总结
在CSS2.1的时代要实现[多边框的效果](http://nicolasgallagher.com/multiple-backgrounds-and-borders-with-css2/),大多数都是依赖于添加标签或依赖于伪元素实现。而今天实现多边框的方案也越来越多,比如`box-shadow`和`outline`等。虽然这些方法能更好的帮助大家实现多边框效果,但每一种方案都有其自己的利弊。不过随着技术的向前发展,说不定哪一天会有一个属性直接有支持多边框,就如Firefox的私有属性`-moz-border-<[top]|[right]|[bottom]|[left]>-colors`。让我们一起期待吧。