> 原文出處:http://www.w3cplus.com/css3/css-secrets/continuous-image-borders.html
## 問題
有時候,我們想將一些圖案或圖片添加為邊框,而不是背景。比如,在下圖中所示的元素就擁有一個裝飾性的邊框,邊框內是一個被限制在邊框區域的圖片。此外,我們還希望圖片可以覆蓋整個邊框區域。那么我們怎樣使用 CSS 達到這一目的呢?

*圖注:圖片被用來裝飾各種高度的邊框*
此時,也許在你的內心會響起一個響亮的聲音:“border-image,border-image,我們可以使用?`border-image`,它可以完美的解決這個問題!”年輕人,做事不要太急躁。讓我們重新回憶一下?`border-image`?的解析機制:它實際上將背景分成了九塊,然后分別將各個塊作用到了元素的邊角上。下圖就是一個視覺原理圖。

*圖注:[`border-image`](http://www.w3cplus.com/content/css3-border-image)?的快速入門。上面:分割后的圖片;虛線框內的就是分割后的碎片;中間:`border-image: 33.34% url(...) stretch;`?下面:?`border-image: 33.34% url(...) round;`,[在線示例鏈接](http://codepen.io/airen/pen/qOqGrL)*
那我們是否可以將圖片切分成塊,然后使用?`border-image`?模擬出下圖這樣的效果呢?

實際上,即使我們精確計算出了元素的尺寸和邊框寬度,仍然無法達到自動適配多種尺寸的目的。問題的核心就是,我們并不是讓邊角具有某種特定的圖形,而且即使添加上了圖形,當元素尺寸變化時,圖形也會發生形變。如果你稍微嘗試一下,就會理解使用`border-image`?是無法實現效果的,那么我們應該怎么辦呢?
解決這個問題最簡單的方法就是使用兩個 HTML 標簽:一個標簽使用目標圖片作為北京,兩一個使用白色作為背景并覆蓋在前一個標簽上面:
~~~
<div class="something-meaningful">
<div>
I have a nice stone art border,
don’t I look pretty?
</div>
</div>
.something-meaningful {
background: url(stone-art.jpg);
background-size: cover;
padding: 1em;
}
.something-meaningful > div {
background: white;
padding: 1em;
}
~~~
這種方法確實實現了下圖的效果:

但是它卻需要添加額外的 HTML 標簽。這只能算是一種折中的辦法:它不僅僅混合了表現和樣式,而是在某些情況下必須修改 HTML 結構。那么我們是否可以只用一層標簽就實現這個效果呢?
## 解決方案
值得慶幸的是,CSS 的漸變以及在?[Backgrounds & Borders Level 3](http://w3.org/TR/css3-background)?中擴展后的?`background`?屬性可以幫助我們實現這一個效果,而且是只用一個標簽。這種方法的核心就是使用純色覆蓋背景圖片。不過,為了讓第二章圖片裝飾到邊框上,我們需要為[`backgroud-clip`](http://www.w3cplus.com/content/css3-background-clip)?屬性配置不同的屬性值。最后一件事就是讓最底下的圖層只有一種顏色,所以我們需要通過 CSS 漸變模擬一個純白色背景。
我們最初實現這個方法的代碼就像下面一樣:
~~~
padding: 1em;
border: 1em solid transparent;
background: linear-gradient(white, white),
url(stone-art.jpg);
background-size: cover;
background-clip: padding-box, border-box;
~~~

*圖注:第一次的嘗試非常接近理想效果。*
正如上圖所示,效果非常接近我們的目標了,唯一的不足是多了一些重復的部分。其中的原因就是?[`backgroud-origin`](http://www.w3cplus.com/content/css-background-origin)?屬性的默認值為?`padding-box`,因此,圖片會定位到內邊距盒模型的左上角,剩余的部分就會不斷平鋪這一圖片。為了矯正這一效果,我們需要將?`background-origin`?的屬性值修改為?`border-box`:
~~~
padding: 1em;
border: 1em solid transparent;
background: linear-gradient(white, white),
url(stone-art.jpg);
background-size: cover;
background-clip: padding-box, border-box;
background-origin: border-box;
~~~
這些新屬性也可以統一使用?`background`?簡寫語法來聲明,從而讓我們的代碼更加簡潔優雅:
~~~
padding: 1em;
border: 1em solid transparent;
background:
linear-gradient(white, white) padding-box,
url(stone-art.jpg) border-box 0 / cover;
~~~
當然,我們也可以將這一技巧應用到和漸變相關的背景圖案上。比如,看一看下面的這些代碼,我們可以用它來生成信封風格的邊框:
~~~
padding: 1em;
border: 1em solid transparent;
background: linear-gradient(white, white) padding-box,
repeating-linear-gradient(-45deg,
red 0, red 12.5%,
transparent 0, transparent 25%,
#58a 0, #58a 37.5%,
transparent 0, transparent 50%)
0 / 5em 5em;
~~~
最終結果如圖所示:

*圖注:我們實現的懷舊信封邊框*
現在,你可以使用?`background-size`?隨意修改條紋的寬度,也可以使用?`border`?隨意修改邊框的寬度。不同于前一個示例,這種效果是可以使用?`border-image`?來實現的:
~~~
padding: 1em;
border: 16px solid transparent;
border-image: 16 repeating-linear-gradient(-45deg,
red 0, red 1em,
transparent 0, transparent 2em,
#58a 0, #58a 3em,
transparent 0, transparent 4em);
~~~
不過,使用?`border-image`?會遇到幾個問題:
* 每次修改?`border-width`?的時候,同時需要修改?`border-image-slice`
* 因為不能在?`border-image-slice`?中使用類似?`em`?的單位,所以我們只能對邊框寬度使用像素單位
* 條紋的寬度需要硬編碼到顏色過渡點上,那么當需求變化時就需要修改四個地方的代碼
這種技巧的另一種有趣應用就是創建一個類似選區的邊框(marching ants borders)。選區型邊框(譯者:之所以稱之為選區型,是因為效果非常類似 ps 中選區邊框的效果,更容易理解)是虛線邊框,而且虛線是實時滾動的,非常類似行進中的螞蟻(當然,這需要一定的想象力將虛線想象為螞蟻)。這在 GUI 中幾乎是不可想象的效果。圖像編輯軟件通常使用這種邊框來表示這是一塊被選中的區域,簡稱選區。

*圖注:選區型邊框在 Adobe Photoshop 中被用來標志被選中的地方*
為了創建這種邊框,我們將要使用前面創建信封邊框的技巧。首先是將條紋更改為黑白兩色,并且將邊框調整為?`1px`?的寬度(你注意到現在條紋是怎樣變化為虛線邊框的了吧?),然后適當修改一個?`background-size`,最后為?`background-size`?添加動畫效果(從初始值增加到?`100%`):
~~~
@keyframes ants { to { background-position: 100% } }
.marching-ants {
padding: 1em;
border: 1px solid transparent;
background:
linear-gradient(white, white) padding-box,
repeating-linear-gradient(-45deg,
black 0, black 25%, white 0, white 50%
) 0 / .6em .6em;
animation: ants 12s linear infinite;
}
~~~
現在,你可以從下圖中看到一個靜態的效果。

*圖注:在紙上顯示選區型邊框是不可能的,可以訪問在線示例進行查看——非常有意思!*
顯然,這種技巧不僅僅對選區型邊框有用,只需修改一下邊框顏色和虛線之間的間距,就可以用來創建各種自定義的虛線邊框。
目前,如果想要使用?`border-image`?屬性實現類似的效果,那么就只能使用?`border-image-source`?添加 GIF 來模擬了,詳情見?[Marching ants animated selection rectangle in CSS](http://www.chrisdanford.com/blog/2014/04/28/marching-ants-animated-selection-rectangle-in-css/)。當瀏覽器廣泛支持漸變效果之后,我們就可以用漸變來創建這種效果了,而且代碼會更加簡練優雅。

*圖注:頂部剪切過得邊框,用來模擬傳統書籍中的腳注*
不過,`border-image`?也是非常強大的屬性,甚至有時比漸變更強大。比如,假設我們需要一個裁剪過的頂部邊框,就像常見的腳注樣式。那么只需要使用?`border-image`和垂直漸變就可以實現,其中裁剪的長度可以硬編碼實現。邊框的寬度則有?`border-width`?來控制。代碼就像是這樣:
~~~
border-top: .2em solid transparent;
border-image: 100% 0 0 linear-gradient( 90deg,
padding-top: 1em;
currentColor 4em,
transparent 0);
~~~
最終結果如上圖所示。此外,因為我們在這里使用?`em`?單位,所以整體效果就能隨字體大小而變化;因為使用了`currentColor`,所以它也可以隨字體顏色而改變顏色。
## 總結
在CSS2.1的時代要實現圖片邊框效果是一種奢侈的想法,但在CSS3中雖然增加了[`border-image`](http://www.w3cplus.com/content/css3-border-image)屬性實現圖片邊框,但依舊受到諸多的限制性,其中最大的限制就是瀏覽器對其支持度。在這一節中,我們介紹了使用多背景,以及配合[`background-clip`](http://www.w3cplus.com/content/css3-background-clip)、[`background-origin`](http://www.w3cplus.com/content/css-background-origin)屬性模擬出圖片邊框效果。