雖然 CSS gradient 的方法可以用,不過它的程式碼是冗長的,需求變更時要做多個地方調整,好在我們還有其他的方法,其中一種是用border-image
配合 inline SVG。
還記得border-image
怎麼用嗎?忘記的話到MDN複習一下。
我們在這裡的方法是用SVG畫一個 3x3 的八角形,經由border-image
的切割,製作出含截角的邊界,再設定背景顏色。因為 SVG 是向量圖,所以單位對它沒有意義,數字對它來說只是在比例上的差別。換句話說,width="3"
的圖形它的寬就是width="1"
的圖形的三倍。所以我們的 3*3 大小的border-image-source
圖案,在border-image-slice: 1
的時候就能完美切割成九等份。
對 SVG 有興趣可以參考 OXXO 的鐵人賽系列文章。
.inline-svg {
border: 15px solid transparent;
border-image: url('data:image/svg+xml,\
<svg xmlns="http://www.w3.org/2000/svg" width="3" height="3" fill="%23955d42">\
<polygon points="0,1 1,0 2,0 3,1 3,2 2,3 1,3 0,2"/>\
</svg>') 1;
}
這下子含截角的邊界出來了,但少了內容的背景色。我們能在border-image
加上fill
關鍵字讓背景色填滿內容區域。不過我們會使用background
的方法,除了可以玩更多花樣之外,還能做為border-image
不支援狀況的 fallback。
在這裡或許有些眼睛銳利的人發現到,怎麼截角比起之前 CSS gradient 做法的結果來得小?你沒有看錯,這裡我們是設border-width: 15px
,但是前一個方法的15px
是用在 gradient color stop,因為我們改變了漸層的方向,所以15px
是和截角邊垂直的。不過在這裡15px
卻是以截角邊為斜邊的等邊三角形的其中一個邊。因此再求助於畢氏定理,可以得到我們在這個範例中需要設的border-width
是20px
。
.inline-svg {
border: 20px solid transparent;
border-image: url('data:image/svg+xml,\
<svg xmlns="http://www.w3.org/2000/svg" width="3" height="3" fill="%23955d42">\
<polygon points="0,1 1,0 2,0 3,1 3,2 2,3 1,3 0,2"/>\
</svg>') 1;
background: #955d42;
}
(用不同顏色分別表示 SVG layer 和 background layer)
設定了背景色之後,卻發現辛苦做的截角不見了!!??別著急,還記得在半透明的邊界提過的background-clip
嗎?因為background
預設會延伸到border
底下,所以加上background-clip: padding-box
就可以看到截角了。
.inline-svg {
border: 20px solid transparent;
border-image: url('data:image/svg+xml,\
<svg xmlns="http://www.w3.org/2000/svg" width="3" height="3" fill="%23955d42">\
<polygon points="0,1 1,0 2,0 3,1 3,2 2,3 1,3 0,2"/>\
</svg>') 1;
background: #955d42;
background-clip: padding-box;
}
這下子我們的截角圖案和前一個方法做的圖案已經相當接近,而且要改變截角大小只要調整一個border-width
的值就足夠!再加上border-width
是 CSS Animations 可以使用的屬性之一,所以我們可以對截角加上動畫效果。還有既然現在background
和border
是分開,我們能在背景加上漸層或是任何圖案,只要背景外緣和邊界的顏色一樣就好。
.inline-svg {
border: 20px solid transparent;
border-image: url('data:image/svg+xml,\
<svg xmlns="http://www.w3.org/2000/svg" width="3" height="3" fill="%23955d42">\
<polygon points="0,1 1,0 2,0 3,1 3,2 2,3 1,3 0,2"/>\
</svg>') 1;
background: radial-gradient(hsla(0,0%,100%,.2) 50%, transparent 70%);
}
這個方法只有一個問題,在不支援border-image
的環境下,border
則不會出現,我們的盒子看起來就比正常來得小。所以與其用透明的border-color
,我們也把它設為相同的顏色,可惜的是不支援border-image
的時候截角就不會出現,在網頁設計上因為環境限制不得已減少某些效果,但是功能仍然能正常使用,這樣的設計方法叫做「優雅降級」(graceful fallback)。
.inline-svg {
border: 20px solid #955d42;
border-image: url('data:image/svg+xml,\
<svg xmlns="http://www.w3.org/2000/svg" width="3" height="3" fill="%23955d42">\
<polygon points="0,1 1,0 2,0 3,1 3,2 2,3 1,3 0,2"/>\
</svg>') 1;
background: #955d42;
background-clip: padding-box;
}