乐趣区

关于css:CSS-实现优惠券的技巧

在理论 Web 开发过程中,总会遇到各种各样的布局。有公司共事问我这样一种布局有没有什么好的实现形式,就是一种在流动充值页十分广泛的优惠券成果,如下

还有这样的

思考到各种可能呈现的场景,形象出以下几种案例,一起来看看实现吧

一、最佳实现形式

首先,碰到这类布局的最佳实现必定是 mask 遮罩。对于遮罩,能够看一下 CSS3 Mask 安利报告。这里简略介绍一下

根本语法很简略,和 background 的语法基本一致

.content{-webkit-mask: '遮罩图片' ;}
/* 残缺语法 */
.content{-webkit-mask: '遮罩图片' [position] / [size] ;
}

这里的遮罩图片和背景的应用形式基本一致,能够是 PNG 图片SVG 图片、也能够是 突变绘制 的图片,同时也反对 多图片叠加

遮罩的原理很简略,最终成果只显示不通明的局部,通明局部将不可见,半透明类推

事实上,除了依据透明度(Alpha)来作为遮罩条件,还能够通过亮度(luminance)来决定,比方红色示意暗藏,彩色示意可见。不过目前只有 Firefox 反对

所以,只有能绘制以上各种形态,就能够实现了。

二、内凹圆角

优惠券大多有一个很显著的特点,就是 内凹圆角。提到圆角,很容易想到 radial-gradient?fileGuid=kDGWvXGxTXG6KrrQ)。这个语法有点简单,记不住没关系,能够看看张老师的这篇 10 个 demo 示例学会 CSS3 radial-gradient 径向突变。

.content{-webkit-mask: radial-gradient(circle at left center, transparent 20px, red 20px); 
}

这样就绘制了一个半径为 20px 的通明的圆,不过代码层面还有很多优化的空间。

  1. 在实现边界明显的突变时,前面色彩的地位只须要小于等于后面色彩的地位就行了,比方0
  2. 通明色彩能够用 16 进制 缩写比方 #0000 来代替 不通明的局部轻易用一个色彩就好,我喜爱用red,次要是这个单词比拟短
  3. 还有突变的地位默认是居中的,所以第二个 center 能够去除,left 能够用 0 来示意

测试发现挪动端对 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 个,别离是:

  1. 把两个凹角的中央错开,这里能够通过批改尺寸和地位,同时还须要禁止平铺
.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

  1. 应用遮罩合成mask-composite,这个可能不太熟悉,简略介绍一下

规范属性下 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 个圆,其实这是能够通过平铺来实现的,只须要一个圆就能够。实现步骤如下

  1. 画一个左中的靠边的通明圆
.content{-webkit-mask: radial-gradient(circle at 20px, #0000 20px, red 0); 
}

  1. 向左平移本身的一半
.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

五、反向镂空叠加

有些状况下可能繁多的一层突变绘制不了很简单的图形,这就须要用到反向镂空技术了,其实就是下面提到过的 遮罩合成,这里再使用一下

  1. 先把下面的实现拿过去
.content{-webkit-mask: radial-gradient(circle at 20px 20px, #0000 20px, red 0) -20px -20px / 50%; 
}

  1. 间接在这个根底上打一排小洞
.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 种绘制优惠券的案例,应该能够解决掉绝大部分这类布局的问题,这里总结以下几点

  1. CSS mask肯定是这类布局最完满的实现形式
  2. 须要 CSS radial-gradient 绘制图形的技巧
  3. 尽可能采纳 repeat 来反复雷同的元素
  4. 多种形态叠加时须要灵活运用mask-composite
  5. 也能够采纳图片来代替 CSS 突变,须要应用mask-border

对于兼容性,其实不思考 IE 都没有什么大问题,最初的 mask-border 目前只兼容 chrome 内核,挪动端可放心使用

感激浏览,心愿能对日后的工作有所启发。

退出移动版