在實際 Web 開發過程當中,總會遇到各類各樣的佈局。有公司同事問我這樣一種佈局有沒有什麼好的實現方式,就是一種在活動充值頁很是廣泛的優惠券效果,以下css
還有這樣的css3
考慮到各類可能出現的場景,抽象出如下幾種案例,一塊兒來看看實現吧web
首先,碰到這類佈局的最佳實現確定是mask遮罩。關於遮罩,能夠看一下CSS3 Mask 安利報告。這裏簡單介紹一下chrome
基本語法很簡單,和background的語法基本一致canvas
.content{ -webkit-mask: '遮罩圖片' ; } /*完整語法*/ .content{ -webkit-mask: '遮罩圖片' [position] / [size] ; }
這裏的遮罩圖片和背景的使用方式基本一致,能夠是PNG圖片、SVG圖片、也能夠是漸變繪製的圖片,同時也支持多圖片疊加。api
遮罩的原理很簡單,最終效果只顯示不透明的部分,透明部分將不可見,半透明類推svg
事實上,除了根據透明度(Alpha)來做爲遮罩條件,還能夠經過亮度(luminance)來決定,好比白色表示隱藏,黑色表示可見。不過目前只有 Firefox 支持
因此,只要能繪製以上各類形狀,就能夠實現了。wordpress
優惠券大多有一個很明顯的特色,就是內凹圓角。提到圓角,很容易想到radial-gradient?fileGuid=kDGWvXGxTXG6KrrQ)。這個語法有點複雜,記不住不要緊,能夠看看張老師的這篇10個demo示例學會CSS3 radial-gradient徑向漸變。工具
.content{ -webkit-mask: radial-gradient(circle at left center, transparent 20px, red 20px); }
這樣就繪製了一個半徑爲 20px 的透明的圓,不過代碼層面還有不少優化的空間。佈局
測試發現移動端對 16 進制支持不加,因此仍是 須要採用 transparent 或者 rgba 的形式
進一步簡化就獲得了
.content{ -webkit-mask: radial-gradient(circle at 0, #0000 20px, red 0); }
不錯,又少了好幾個B的流量~ 能夠查看在線實例codepen 優惠券實現1
上面是一個最基本的內凹圓角效果,如今來實現下面幾種佈局,好比兩個半圓的,根據上面的例子,再複製一個圓不就能夠了?改一下定位的方向
.content{ -webkit-mask: radial-gradient(circle at 0, #0000 20px, red 0), radial-gradient(circle at right, #0000 20px, red 0); }
這時發現一個圓都沒有了。緣由其實很簡單,以下演示,兩層背景相互疊加,致使整塊背景都成了不透明的,因此 mask 效果表現爲所有可見。
解決方式有2個,分別是:
.content{ -webkit-mask: radial-gradient(circle at 0, #0000 20px, red 0), radial-gradient(circle at right, #0000 20px, red 0); -webkit-mask-size: 51%; /*避免出現縫隙*/ -webkit-mask-position: 0, 100%; /*一個居左一個居右*/ -webkit-mask-repeat: no-repeat; }
動態演示以下,這樣就不會互相覆蓋了
能夠查看在線實例codepen 優惠券實現2
標準屬性下mask-composite有 4 個屬性值(Firefox支持)
/* Keyword values */ mask-composite: add; /* 疊加(默認) */ mask-composite: subtract; /* 減去,排除掉上層的區域 */ mask-composite: intersect; /* 相交,只顯示重合的地方 */ mask-composite: exclude; /* 排除,只顯示不重合的地方 */
這個可能有些很差理解,其實能夠參考一些圖形軟件的形狀合成操做,好比 photoshop
-webkit-mask-composite與標準下的值有所不一樣,屬性值很是多,看下面
-webkit-mask-composite: clear; /*清除,不顯示任何遮罩*/ -webkit-mask-composite: copy; /*只顯示上方遮罩,不顯示下方遮罩*/ -webkit-mask-composite: source-over; -webkit-mask-composite: source-in; /*只顯示重合的地方*/ -webkit-mask-composite: source-out; /*只顯示上方遮罩,重合的地方不顯示*/ -webkit-mask-composite: source-atop; -webkit-mask-composite: destination-over; -webkit-mask-composite: destination-in; /*只顯示重合的地方*/ -webkit-mask-composite: destination-out;/*只顯示下方遮罩,重合的地方不顯示*/ -webkit-mask-composite: destination-atop; -webkit-mask-composite: xor; /*只顯示不重合的地方*/
是否是一下就懵了?不用慌,能夠看到上面有幾個值是source-,還有幾個是destination-開頭的,source 表明新內容,也就是上面繪製的圖層,destination 表明元內容,也就是下面繪製的圖層(在CSS中,前面的圖層會覆蓋後面的圖層),這裏的屬性值實際上是借用了Canvas 中的概念,具體能夠查看CanvasRenderingContext2D.globalComposite
記不住不要緊,實際開發能夠逐一試驗[\捂臉]。具體差別能夠查看codepen -webkit-mask-composite 屬性值演示
瞭解這個屬性後,上面的疊加問題就很簡單了,設置只顯示重合的地方就好了
.content{ -webkit-mask: radial-gradient(circle at 0, #0000 20px, red 0), radial-gradient(circle at right, #0000 20px, red 0); -webkit-mask-composite: source-in | destination-in ; /*chrome*/ mask-composite: intersect; /*Firefox*/ }
動態演示以下,這樣只會顯示互相重合的地方
能夠查看在線實例codepen 優惠券實現3
2個圓角的實現了,4個的就很容易了,畫4個圓就行,一樣利用遮罩合成能夠輕易實現
content{ -webkit-mask: radial-gradient(circle at 0 0, #0000 20px, red 0), radial-gradient(circle at right 0, #0000 20px, red 0), radial-gradient(circle at 0 100%, #0000 20px, red 0), radial-gradient(circle at right 100%, #0000 20px, red 0); /*4個角落各放一個圓*/ -webkit-mask-composite: source-in | destination-in ; /*chrome*/ mask-composite: intersect; /*Firefox*/ }
能夠查看在線實例codepen 優惠券實現4
上面的例子展現了2個圓角和4個圓角的效果,分別繪製了2個和4個圓,其實這是能夠經過平鋪來實現的,只須要一個圓就能夠。實現步驟以下
.content{ -webkit-mask: radial-gradient(circle at 20px, #0000 20px, red 0); }
.content{ -webkit-mask: radial-gradient(circle at 20px, #0000 20px, red 0); -webkit-mask-position: -20px } /*也能夠縮寫爲*/ .content{ -webkit-mask: radial-gradient(circle at 20px, #0000 20px, red 0) -20px; }
效果就出來了,是否是很神奇?其實就是利用到了默認的repeat特性,這裏用一張動圖就能明白了
下面 紅色邊框內表示視區範圍,也就是最終的效果,這裏爲了演示,把視線以外的 平鋪作了半透明處理,移動表示 position 改變的過程
能夠查看在線實例codepen 優惠券實現5
一樣原理,4個圓角也能夠採用這種方式實現
.content{ -webkit-mask: radial-gradient(circle at 20px 20px, #0000 20px, red 0); -webkit-mask-position: -20px -20px; } /*也能夠縮寫爲*/ .content{ -webkit-mask: radial-gradient(circle at 20px 20px, #0000 20px, red 0) -20px -20px; }
實現原理演示以下
能夠查看在線實例codepen 優惠券實現6
6個圓角就須要改一下平鋪尺寸了。
.content{ -webkit-mask: radial-gradient(circle at 20px 20px, #0000 20px, red 0); -webkit-mask-position: -20px -20px; -webkit-mask-size: 50%; } /*也能夠縮寫爲*/ .content{ -webkit-mask: radial-gradient(circle at 20px 20px, #0000 20px, red 0) -20px -20px / 50%; }
實現原理演示以下
能夠查看在線實例codepen 優惠券實現7
若是繼續縮小背景圖的尺寸,還能夠獲得最後的效果
.content{ -webkit-mask: radial-gradient(circle at 10px, #0000 10px, red 0); -webkit-mask-position: -10px; -webkit-mask-size: 100% 30px; } /*也能夠縮寫爲*/ .content{ -webkit-mask: radial-gradient(circle at 20px 20px, #0000 20px, red 0) -10px / 100% 30px; }
實現原理演示以下,其實就平鋪
能夠查看在線實例codepen 優惠券實現8
有些狀況下可能單一的一層漸變繪製不了很複雜的圖形,這就須要用到反向鏤空技術了,其實就是上面提到過的遮罩合成,這裏再運用一下
.content{ -webkit-mask: radial-gradient(circle at 20px 20px, #0000 20px, red 0) -20px -20px / 50%; }
.content{ -webkit-mask: radial-gradient( circle at 50%, red 5px, #0000 0) 50% 50% / 100% 20px, radial-gradient(circle at 20px 20px, #0000 20px, red 0) -20px -20px / 50%; -webkit-mask-composite: destination-out; mask-composite: subtract; /*Firefox*/ }
注意這裏用到了-webkit-mask-composite: destination-out,表示減去,只顯示下方遮罩,重合的地方不顯示
能夠查看在線實例codepen 優惠券實現9
也能夠放在兩邊,改一下position就能夠了
.content{ -webkit-mask: radial-gradient( circle at 5px, red 5px, #0000 0) -5px 50% / 100% 20px, radial-gradient(circle at 20px 20px, #0000 20px, red 0) -20px -20px / 50%; -webkit-mask-composite: destination-out; mask-composite: subtract; /*Firefox*/ }
能夠查看在線實例codepen 優惠券實現10
有些同窗以爲徑向漸變太複雜,實在是寫不出來,能不能用圖片代替呢?其實也是可行的。這裏說的邊框遮罩指的是mask-border, 目前還在 W3C 草案當中,不過有一個替代屬性-webkit-mask-box-image
語法和概念和border-image很是類似,關於border-image可參考這篇文章border-image 的正確用法,這裏主要了解一下用法和效果
.content{ -webkit-mask-box-image: '遮罩圖片' [<top> <right> <bottom> <left> <x-repeat> <y-repeat>] }
好比有一張這樣的圖片
SVG代碼長這樣,不少工具均可以導出來,實在不會能夠直接找設計同窗(也可採用.png格式)
<svg xmlns="http://www.w3.org/2000/svg" width="60.031" height="60.031" viewBox="0 0 60.031 60.031"><path d="M40 60.027H20.129A20.065 20.065 0 0 0 .065 40H0V20.127h.065A20.066 20.066 0 0 0 20.131.061v-.065H40v.065a20.065 20.065 0 0 0 20.027 20.064V40A20.063 20.063 0 0 0 40 60.027z" fill-rule="evenodd"/></svg>
這裏須要轉義一下,可藉助張老師的SVG在線合併工具
.content{ -webkit-mask-box-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='60.031' height='60.031' viewBox='0 0 60.031 60.031'%3E%3Cpath d='M40 60.027H20.129A20.065 20.065 0 0 0 .065 40H0V20.127h.065A20.066 20.066 0 0 0 20.131.061v-.065H40v.065a20.065 20.065 0 0 0 20.027 20.064V40A20.063 20.063 0 0 0 40 60.027z' fill-rule='evenodd'/%3E%3C/svg%3E") 20; /*這裏的20表示四周保留20像素的固定區域,剩餘部分平鋪或者拉伸*/ }
而後就實現了這樣一個形狀,一樣是自適應的
能夠查看在線實例codepen -webkit-mask-box-iamge 實現1
再好比有一張這樣的圖片
.content{ -webkit-mask-box-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='60.031' height='60.031' viewBox='0 0 60.031 60.031'%3E%3Cpath d='M55.186 30.158a4.965 4.965 0 0 0 4.841 4.959V40A20.063 20.063 0 0 0 40 60.027H20.129A20.065 20.065 0 0 0 .065 40H0v-4.888c.054 0 .1.016.158.016a4.973 4.973 0 1 0 0-9.945c-.054 0-.1.014-.158.015v-5.074h.065A20.066 20.066 0 0 0 20.131.058v-.065H40v.065a20.065 20.065 0 0 0 20.027 20.064v5.07a4.965 4.965 0 0 0-4.841 4.966z' fill-rule='evenodd'/%3E%3C/svg%3E") 20; }
能夠獲得這樣一個形狀,兩側的半圓被拉伸了
這時只須要設置平鋪方式-webkit-mask-box-image-repeat ,這個和border-image-repeat是同樣的概念,有如下 4 個值
-webkit-mask-box-image-repeat: stretch; /*拉伸(默認),不會平鋪*/ -webkit-mask-box-image-repeat: repeat; /*重複*/ -webkit-mask-box-image-repeat: round; /*重複,當不能整數次平鋪時,根據狀況拉伸。*/ -webkit-mask-box-image-repeat: space; /*重複,當不能整數次平鋪時,會用空白間隙填充*/
幾種平鋪方式的差別以下
這裏咱們能夠採用round或者repeat
.content{ -webkit-mask-box-image: url("...") 20; -webkit-mask-box-image-repeat: round; }
能夠查看在線實例codepen -webkit-mask-box-iamge 實現2
以上一共介紹了12種繪製優惠券的案例,應該能夠解決掉絕大部分這類佈局的問題,這裏總結如下幾點
關於兼容性,其實不考慮 IE 都沒有什麼大問題,最後的 mask-border 目前只兼容 chrome 內核,移動端可放心使用
感謝閱讀,但願能對往後的工做有所啓發。