在实际 Web 开发过程中,总会遇到各种各样的布局。有公司同事问我这样一种布局有没有什么好的实现方式,就是一种在活动充值页非常普遍的优惠券效果,如下

还有这样的

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

一、最佳实现方式

首先,碰到这类布局的最佳实现肯定是mask遮罩。关于遮罩,可以看一下CSS3 Mask 安利报告。这里简单介绍一下

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

.content{-webkit-mask: '遮罩图片' ;
}
/*完整语法*/
.content{-webkit-mask: '遮罩图片' [position] / [size] ;
}
复制代码

这里的遮罩图片和背景的使用方式基本一致,可以是PNG图片SVG图片、也可以是渐变绘制的图片,同时也支持多图片叠加

遮罩的原理很简单,最终效果只显示不透明的部分,透明部分将不可见,半透明类推

事实上,除了根据透明度(Alpha)来作为遮罩条件,还可以通过亮度(luminance)来决定,比如白色表示隐藏,黑色表示可见。不过目前只有 Firefox 支持

所以,只要能绘制以上各种形状,就可以实现了。

二、内凹圆角

优惠券大多有一个很明显的特点,就是内凹圆角。提到圆角,很容易想到radial-gradient。这个语法有点复杂,记不住没关系,可以看看张老师的这篇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来表示

进一步简化就得到了

.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代码长这样,很多工具都可以导出来,实在不会可以直接找设计同学

<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 内核,移动端可放心使用

感谢阅读,希望能对日后的工作有所启发。

作者:阅文前端团队
链接:https://juejin.cn/post/6945023989555134494

CSS 实现优惠券的技巧相关推荐

  1. css背景渐变的技巧与方法

    [发帖际遇]: the_truth玩宠物的时候不幸损失威望13. css背景渐变的技巧与方法 用css实现网页背景渐变的代码如下: 一.从上往下渐变 Example Source Code: body ...

  2. 如何用纯 CSS 实现优惠券效果

    ​ 背景 本文来自CODE.FUN  ,讲述如何用纯 CSS 实现优惠券效果的实践案例,分享给大家. 优惠券视觉效果 上面是优惠券的视觉效果,本文分享如何使用纯 CSS 实现它的主要框架,希望对大家有 ...

  3. 纯 CSS 实现优惠券透明圆形镂空打孔效果

    本文同步发布在:纯 CSS 实现优惠券透明圆形镂空打孔效果 我们在做商城类项目时,时常会有开发优惠券的需求,那么我们如何通过纯 CSS 来实现类似京东.淘宝的优惠券样式. 下面给大家分享一个纯 CSS ...

  4. html中如何消除左边界,元素的局中对齐问题,CSS盒属性使用技巧,前端开发必备...

    本文介绍的盒属性应用包括以下几点: 块级元素在容器中的水平居中 绝对定位的块级元素在页面中水平垂直居中 去掉所有HTML元素的边界和填充值 去掉无序列表左侧为项目符号留出的位置 一.块级元素在容器中的 ...

  5. css 小经验: 重构css的优化与技巧

    一.使用css缩写 使用缩写可以帮助减少你CSS文件的大小,更加容易阅读.css缩写的主要规则请参看<常用css缩写语法总结>,这里就不展开描述. 二.明确定义单位,除非值为0 忘记定义尺 ...

  6. CSS一些实用的技巧

    css 字体简写规则 当使用css定义字体时你可能会这样做: font-size: 1em; line-height: 1.5em; font-weight: bold; font-style: it ...

  7. CSS布局奇淫技巧之--各种居中

    居中是我们使用css来布局时常遇到的情况.使用css来进行居中时,有时一个属性就能搞定,有时则需要一定的技巧才能兼容到所有浏览器,本文就居中的一些常用方法做个简单的介绍. 注:本文所讲方法除了特别说明 ...

  8. 做网页很实用代码集合和CSS制作网页小技巧整理

    做网页很实用代码集合 控制横向和纵向滚动条的显隐?<body style="overflow-y:hidden"> 去掉x轴 <body style=" ...

  9. 自学前端第二十九天 CSS高级之细节技巧

    第二十九天 css高级细节技巧 一.background-color :属性设置元素的背景颜色. 定义和用法 background-color 属性设置元素的背景颜色. 元素背景的范围 backgro ...

最新文章

  1. Activiti——数据表结构
  2. 2021年春季学期-信号与系统-第十五次作业参考答案-第八小题参考答案
  3. springboot配置spring.profiles.active多环境支持
  4. 【HDU 5184】 Brackets (卡特兰数)
  5. QT+FFMPEG实现视频播放
  6. java构建json_Java构造和解析Json数据的两种方法详解一
  7. pta-4、运算符-找钱 (10 分)
  8. 网页制作 css样式,网页设计与制作-CSS样式.ppt
  9. 2019.7.20十道js题目
  10. 第三周学习《对象与类》心得
  11. 真核有参转录组测序标准分析
  12. 用original绘制重叠柱状图
  13. 电脑无法设置默认打开方式的解决办法
  14. pacman安装ubuntu_pacman命令 – 软件包管理器
  15. python列表获取最后一项_如何在Python中获取列表的最后一项?
  16. 小白的 Python学习笔记 之 input()
  17. python爬取斗鱼主播图片
  18. MFC(CFile)文件操作
  19. QQ邮箱取消免费扩容;苹果搜索引擎“胎死腹中”,核心成员已回归谷歌麾下;Xcode 14导致应用体积大增|极客头条
  20. 计算机专业相关知识零碎记录

热门文章

  1. vue实现下拉二级联动_select下拉菜单实现二级联动效果
  2. 澳大利亚莫纳什大学推出公开漏洞奖励计划
  3. 夺宝奇兵 (优先队列 + 贪心 + 暴力枚举)
  4. 思科模拟器出现Translating XXXX...domain server (255.255.255.255) 解决办法
  5. 洛谷p2298 bfs
  6. vue实现伸缩菜单功能
  7. [转]齐善鸿:职业心智训练与管理教育
  8. nodejs爬虫与python爬虫_Python,Node.js 哪个比较适合写爬虫?
  9. 利用Kmeans聚类进行用户分层分析
  10. 将本地图片或者网上图片用post方式上传到图片服务器