在实际 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 内核,移动端可放心使用
感谢阅读,但愿能对往后的工做有所启发。