iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 15
0
Modern Web

CSS Secrets 導讀系列 第 15

Secret 12: 截角效果 (inline SVG)

雖然 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; 	
}

https://ithelp.ithome.com.tw/upload/images/20181030/20091606dHlc2e6TMc.png

這下子含截角的邊界出來了,但少了內容的背景色。我們能在border-image加上fill關鍵字讓背景色填滿內容區域。不過我們會使用background的方法,除了可以玩更多花樣之外,還能做為border-image不支援狀況的 fallback。

在這裡或許有些眼睛銳利的人發現到,怎麼截角比起之前 CSS gradient 做法的結果來得小?你沒有看錯,這裡我們是設border-width: 15px,但是前一個方法的15px是用在 gradient color stop,因為我們改變了漸層的方向,所以15px是和截角邊垂直的。不過在這裡15px卻是以截角邊為斜邊的等邊三角形的其中一個邊。因此再求助於畢氏定理,可以得到我們在這個範例中需要設的border-width20px

.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;
}

https://ithelp.ithome.com.tw/upload/images/20181030/20091606bCOsIsTXaA.png
(用不同顏色分別表示 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;
}

https://ithelp.ithome.com.tw/upload/images/20181030/200916064CGiHWCatx.png

這下子我們的截角圖案和前一個方法做的圖案已經相當接近,而且要改變截角大小只要調整一個border-width的值就足夠!再加上border-width是 CSS Animations 可以使用的屬性之一,所以我們可以對截角加上動畫效果。還有既然現在backgroundborder是分開,我們能在背景加上漸層或是任何圖案,只要背景外緣和邊界的顏色一樣就好。

.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%);
}

https://ithelp.ithome.com.tw/upload/images/20181030/20091606VCudKCTE5i.png

這個方法只有一個問題,在不支援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;
}

CodePen


上一篇
Secret 12: 截角效果 (CSS gradient)
下一篇
Secret 12: 截角效果 (clip-path)
系列文
CSS Secrets 導讀30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言