微信小程序实现一些优惠券/卡券

背景

👏 前几周有小伙伴问我如何用css实现一些优惠券/卡券,今天就来分享一波吧!速速来Get吧~
🥇文末分享源代码。记得点赞+关注+收藏!

1.实现效果

在这里插入图片描述

2.实现原理

2.1 实现内凹圆角

假设我们要实现这样的一个效果,两侧透明内圆角+外侧投影,有几种实现方式呢?

在这里插入图片描述

2.1.1 方法一:半圆伪元素(投影不准确)

  • 可将这个想象成一个正常的矩形,左右两侧分别有个小半圆
在这里插入图片描述
  • 将半圆的颜色设置为与背景色一致
在这里插入图片描述
  • 为其添加drop-shadow投影,发现无法正确的在半圆内部显示投影
在这里插入图片描述
.card{
  width: 700rpx;
  height: 250rpx;
  margin: 0 auto 20rpx;
  border-radius: 20rpx;
  position: relative;
  background: #ff6810;
  position: relative;
  filter: drop-shadow(2px 2px 1px rgba(0, 0, 0, .3));
}

.card::before,
.card::after {
  content: '';
  position: absolute;
  width: 20rpx;
  height: 40rpx;
  background: var(--bg);
  top: calc(50% - 20rpx);
}
.card::before {
  border-radius: 0 20rpx 20rpx 0;
  left: 0;
}
.card::after {
  border-radius: 20rpx 0 0 20rpx;
  right: 0;
}
局限性:

1.当页面背景是图片或者非纯色的时候,无法正确的显示

2.无法正确的显示投影

2.1.2 方法二:radial-gradient渐变

radial-gradient:

radial-gradient() CSS 函数创建一个图像,该图像由从原点辐射的两种或多种颜色之间的渐进过渡组成。它的形状可以是圆形或椭圆形。函数的结果是 gradient数据类型的对象。这是一种特别的 image。

语法:

background-image: radial-gradient(shape size at position, start-color, ..., last-color); 

径向渐变通过指定渐变的中心(0% 椭圆所在的位置)和结束形状(100% 椭圆)的大小和形状来指定。

渐变颜色默认第一个颜色位置是0%,最后一个颜色位置是100%.

eg:
  • 圆形,起始点位置为左上角即left center(不写则为center),从橘色开始,变成粉色,最后变成天空蓝,不写百分比就均匀分布。
background: radial-gradient(circle at 0rpx, orange , pink, skyblue ) ; 
//等价于background: radial-gradient(circle at 0rpx, orange 0, pink 50%, skyblue 100%) ; 
在这里插入图片描述
  • 圆形,起始点位于left,center,透明色占据20rpx,pink占据20rpx,skyblue从20rpx到100%;
background: radial-gradient(circle at left center, transparent 20rpx, pink 20rpx, skyblue);
在这里插入图片描述
  • 圆形,起始点位于center,center,透明色占据20%,pink占据20% 45%,skyblue从45% 70%
    ,rgb(211, 128, 50)从 70% 100%
background: radial-gradient( circle ,transparent 20%, pink 20% 45%, skyblue 45% 70%, rgb(211, 128, 50) 70% 100%);
在这里插入图片描述
  • 圆形,起始点位于left ,center,透明色占据0rpx 20rpx,pink占据20rpx 30%,skyblue从45% 70%
    ,skyblue 从 30% 100%
background: radial-gradient(circle at left center, transparent 0rpx 20rpx, pink 20rpx 30%, skyblue 30%);
在这里插入图片描述
实现两侧内圆角:
  • 圆形,起始点位于left,center,定义一个透明色占据20rpx,剩下颜色为20rpx到100%的纯色
background: radial-gradient(circle at left center, transparent 20rpx, pink 20rpx);
在这里插入图片描述
  • 试着改变pink颜色的起始位置,我们发现要实现一个透明的半圆,后面的颜色起始点要小于等于前个颜色的结束位置
在这里插入图片描述
  • 试着在右边再次定义一个内圆角,发现两个透明圆角都不显示了
 background: radial-gradient(circle at left, transparent 20rpx, pink 20rpx), radial-gradient(circle at right, transparent 20rpx, pink 20rpx);
在这里插入图片描述
  • XboxYan-CSS 实现优惠券的技巧这篇文章在讲mask遮罩时,有说到是因为两层背景相互叠加,导致整块背景都成了不透明的,那么是不是同样适用到这个渐变上呢?试试看
  • 修改background-position为对应位置,background-size宽度为50%,高度不变,background-repeat不重叠,先将颜色分开试试,看看效果如何

background-position:

background-position CSS 属性为每一个背景图片设置初始位置。这个位置是相对于由 background-origin 定义的位置图层的。
对于两个值的语法: 一个定义 x 坐标,另一个定义 y 坐标,其他的请看相关文档,这里就不赘述了。

background: radial-gradient(circle at left, transparent 20rpx, skyblue 20rpx) 0 100% /51% no-repeat, radial-gradient(circle at right, transparent 20rpx, pink 20rpx) 100% 0 /51% no-repeat;
//或者
background: radial-gradient(circle at left, transparent 20rpx, skyblue 20rpx) ,radial-gradient(circle at right, transparent 20rpx, pink 20rpx) ;
background-size: 51%;
background-repeat: no-repeat; 
background-position: 0, 100%;
在这里插入图片描述
  • 将颜色修改回来,并添加drop-shadow投影
在这里插入图片描述
  • 试着将上述内容进行简写,得到一个圆心距离左边20rpx,半径为20rpx居中的透明圆
background: radial-gradient(circle at 20rpx center, transparent 20rpx, #ff6810 20rpx) ;
在这里插入图片描述
  • 利用background-position进行x轴方向的偏移,偏移-20rpx,并添加drop-shadow投影
filter: drop-shadow(2px 2px 1px rgba(0, 0, 0, .3));
background: radial-gradient(circle at 20rpx center, transparent 20rpx, #ff6810 20rpx) -20rpx;
//或者
filter: drop-shadow(2px 2px 1px rgba(0, 0, 0, .3));
background: radial-gradient(circle at 20rpx center, transparent 20rpx, #ff6810 20rpx);
background-position: -20rpx ;
在这里插入图片描述
局限性:

1.当优惠券背景是渐变色的时候,处理起来不方便

2.1.3 方法三: mask遮罩

mask:

CSS 属性 mask 允许使用者通过遮罩或者裁切特定区域的图片的方式来隐藏一个元素的部分或者全部可见区域。可以理解为透明的部分不显示,展示非透明区域。
mask语法与background类似,使用mask可以实现一些amazing的效果,可以参考文章ChokCoco-奇妙的 CSS MASK

  • 假设给一个元素设置一个mask遮罩,遮罩设置为起始点位于left,center,定义一个透明色占据20rpx的半圆
background: pink;
-webkit-mask: radial-gradient(circle at left center, transparent 20rpx, skyblue 21rpx);
在这里插入图片描述
  • 修改mask遮罩的第二个色值占据的百分比以及色值,看看效果如何?
  • 我们可以发现,当第二个色值占据的大小<=前一个时候,会展示一个透明色的内圆角;
  • mask遮罩遮住的是透明区域,所以不透明的部分不需要关心,那么后一个颜色的色值你可以随意设置。
在这里插入图片描述
  • 现在,我们可以根据2.1.2节生成的内圆角做一些变动,看看能不能得到我们想要的效果
  • 遮罩一:
.card-002 {
  background: #ff6810;
  -webkit-mask: radial-gradient(circle at left, transparent 20rpx, pink 20rpx) 0 100% /51% no-repeat, radial-gradient(circle at right, transparent 20rpx, pink 20rpx) 100% 0 /51% no-repeat;
}
  • 遮罩二:
.card-002 {
  background: #ff6810;
  -webkit-mask: radial-gradient(circle at 20rpx center, transparent 20rpx, red 0) -20rpx;
}

  • 上述两个遮罩(遮罩的形成与2.1.2节一致,这里不再赘述)都可以形成内凹圆角
在这里插入图片描述

-参考 XboxYan-CSS 实现优惠券的技巧这篇文章, 利用-webkit-mask-composite设置重叠区域的展示,设置source-in,只显示重合的地方,也可以实现两个内圆角

.card-002 {
  background: #ff6810;
  -webkit-mask: radial-gradient(circle at left, transparent 20rpx, pink 20rpx),
    radial-gradient(circle at right, transparent 20rpx, pink 20rpx);
  -webkit-mask-composite: source-in;
}
  • 添加drop-shadow投影,发现添加木有效果,为什么呢?
  • 那换种思路,将投影加在元素上,把mask遮罩放到伪元素上试试,果真可以了,试着分析一下,mask进行裁剪的时候会将投影也裁掉
在这里插入图片描述
.card-002{
    width: 700rpx;
    height: 250rpx;
    position: relative;
    filter: drop-shadow(2px 2px 1px rgba(0, 0, 0, .3));
}
.card-002::after {
  content: '';
  width: 100%;
  height: 100%;
  position: absolute;
  left: 0;
  top: 0;
  z-index: -1;
  background: #ff6810;
  border-radius: 20rpx;
  -webkit-mask: radial-gradient(circle at 20rpx center, transparent 20rpx, red 0) -20rpx;
  mask: radial-gradient(circle at 20rpx center, transparent 20rpx, red 0) -20rpx;
}
  • 将优惠券的背景修改为渐变色试试
--c1: orange;
--c2: #ff2e63;
background: linear-gradient(35deg, var(--c1), var(--c2));
在这里插入图片描述
综上所述,使用mask遮罩实现内凹圆角无疑是最佳方法

2.2 实现矩形四边1/4的内圆角

假设我们要实现这样的一个效果,矩形四边分别有1/4的圆角,有几种实现方式呢?

在这里插入图片描述
  • 可以把这个想象成四个透明的的1/4内圆角
在这里插入图片描述

2.2.1 radial-gradient渐变

  • 先实现一个透明的的1/4内圆角
background: radial-gradient(circle at 0 0, transparent 20rpx, #ff6810 0) ;
在这里插入图片描述
  • 按照左上,左下,右上,右下的位置,添上4个圆角,并调整background-position,background-size
  background: radial-gradient(circle at left 0, transparent 20rpx, pink 0) left 0 /50% 50% no-repeat,
    radial-gradient(circle at right 0, transparent 20rpx, skyblue 0) right 0 /50% 50% no-repeat,
    radial-gradient(circle at left 100%, transparent 20rpx, orange 0) left 100% /50% 50% no-repeat,
    radial-gradient(circle at right 100%, transparent 20rpx, #a6d1a9 0) right 100% /50% 50% no-repeat;
在这里插入图片描述

或者将起始点设置到左边20rpx,上边20rpx,并调整background-position位置

.card-003 {
  background: radial-gradient(circle at 20rpx 20rpx, transparent 20rpx, #ff6810 0) -20rpx -20rpx;
 filter: drop-shadow(2px 2px 1px rgba(0, 0, 0, .3));
}
在这里插入图片描述

2.2.2 mask遮罩

  • 其实,mask遮罩的内容与radial-gradient渐变的内容是一致的,我们可以按照2.2.1的内容实现两种遮罩
  • 遮罩一:
  background:slateblue;
  -webkit-mask: radial-gradient(circle at left 0, transparent 20rpx, pink 0) left 0 /50% 50% no-repeat,
    radial-gradient(circle at right 0, transparent 20rpx, skyblue 0) right 0 /50% 50% no-repeat,
    radial-gradient(circle at left 100%, transparent 20rpx, orange 0) left 100% /50% 50% no-repeat,
    radial-gradient(circle at right 100%, transparent 20rpx, #a6d1a9 0) right 100% /50% 50% no-repeat;
  • 遮罩二:
.card-004{
 position: relative;
 filter: drop-shadow(2px 2px 1px rgba(0, 0, 0, .3));
}
.card-004::after {
  -webkit-mask: radial-gradient(circle at 20rpx 20rpx, transparent 20rpx, red 0) -20rpx -20rpx;
  background: slateblue;
}
在这里插入图片描述
  • 背景设置为渐变色
  background: linear-gradient(to right, var(--c1) 0%, var(--c2) 100%);
在这里插入图片描述

2.3 实现一个内凹圆角边框

假设我们要实现这样的一个效果,内凹圆角边框,有几种实现方式呢?

在这里插入图片描述

2.3.1 mask遮罩+多重drop-shadow

  • 参考 XboxYan-CSS filter生成不规则边框这篇文章,利用多重投影drop-shadow

  • 因为mask会裁剪掉drop-shadow,所以要把mask渐变写到器伪元素上

  • 由于mask是显示非透明部分,所以要为元素设置背景色,不能为transparent,即与页面的背景色一致

.card-005 {
  filter: drop-shadow(0 0 2rpx) drop-shadow(0 0 0) drop-shadow(0 0 0) drop-shadow(0 0 0) drop-shadow(0 0 0);
  //投影的颜色默认是跟随当前文字颜色的
  color: #eb4f8b;
}
.card-005::after {
  content: '';
  width: 100%;
  height: 100%;
  position: absolute;
  left: 0;
  top: 0;
  z-index: -1;
  border-radius: 20rpx;
  -webkit-mask: radial-gradient(circle at 20rpx center, transparent 20rpx, red 0) -20rpx;
  //页面的背景色
  background: var(--bg);
}
在这里插入图片描述

2.3.1 mask遮罩+伪元素+border

  • 设置border+mask遮罩
  -webkit-mask: radial-gradient(circle at 20rpx center, transparent 18rpx, #000 0) -20rpx;
  color: #ff6810;
  border: 3rpx solid #ff6810;
在这里插入图片描述

添加两个半圆伪元素,背景色与border颜色一致,调整好相应位置

.card-006::before,
.card-006::after {
  content: '';
  position: absolute;
  width: 40rpx;
  height: 40rpx;
  border-radius: 50%;
  background-color: #ff6810;
  top: calc(50% - 21rpx);
}
.card-006::before {
  left: -3%;
}
.card-006::after {
  right: -3%;
}
image.png

3.实现代码

内容较多,这里展示前两个demo,完整代码请戳这里:🍡苏苏的github, 🍪苏苏的码云

<!-- 样式1 -->
<view class="card-box">
  <view class="card-name">苏苏就是小苏苏哇</view>
  <view class="card-banner">VIP</view>
  <view class="card-content">
    <text>剩余</text>
    <text>88888</text>
    <text>元</text>
  </view>
  <view class="flex-row j_c card-btm">
    <view class="flex-column j_c card-btm-item">
      <text>已获得奖项</text>
      <text>888个</text>
    </view>
    <view class="flex-column j_c card-btm-item">
      <text>已出售</text>
      <text>1008个</text>
    </view>
    <view class="flex-column j_c card-btm-item">
      <text>已买入</text>
      <text>999个</text>
    </view>
  </view>
</view>
<!-- 样式2 -->
<view class="coupon-box flex">
  <view class="cou-banner">即将过期</view>
  <view class="cou-left flex-row j_c">
    <view>
      <text>888</text>
      <text>元</text>
    </view>
  </view>
  <view class="cou-right flex-row ">
    <view>
      <view>苏苏就是小苏苏哇--苏苏</view>
      <view class="cou-right-time">剩余 23:59:59</view>
    </view>
  </view>
</view>
/* 样式1 */
.card-box {
  width: 700rpx;
  height: 360rpx;
  margin: 0 auto 20px;
  border-radius: 30rpx;
  overflow: hidden;
  box-sizing: border-box;
  padding: 20rpx;
  filter: drop-shadow(2px 2px 1px rgba(0, 0, 0, .3));
  position: relative;
  color: #fff;
}
.card-box::after {
  content: '';
  width: 100%;
  height: 100%;
  position: absolute;
  left: 0;
  top: 0;
  background: linear-gradient(35deg, var(--c1), var(--c2));
  -webkit-mask: radial-gradient(circle at 20rpx 65%, transparent 20rpx, red 0) -20rpx;
  mask: radial-gradient(circle at 20rpx 65%, transparent 20rpx, red 0) -20rpx;
  z-index: -1;
  animation: bgchange 3s infinite ease-in-out alternate-reverse;
}
@keyframes bgchange {
  0% {
    filter: hue-rotate(0deg);
  }
  100% {
    filter: hue-rotate(-50deg);
  }
}
.card-name {
  font-size: 40rpx;
  font-weight: bold;
  letter-spacing: 2rpx;
  margin-bottom: 45rpx;
}
.card-banner {
  position: absolute;
  display: inline-block;
  min-width: 100rpx;
  padding: 10rpx 0;
  text-align: center;
  height: 30rpx;
  line-height: 30rpx;
  border-radius: 30rpx;
  background: rgba(255, 255, 255, .26);
  top: 20rpx;
  right: 20rpx;
}
.card-content {
  font-size: 28rpx;
  display: flex;
  align-items: baseline;
  justify-content: center;
  position: relative;
  margin-bottom: 40rpx;
}
.card-content::before {
  content: '';
  width: 600rpx;
  height: 3rpx;
  position: absolute;
  background-image: linear-gradient(90deg, var(--c3) 50%, transparent 50%);
  background-size: 30rpx 30rpx;
  left: calc(50% - 300rpx);
  bottom: -30rpx;
}
.card-content text:nth-child(2) {
  font-size: 80rpx;
  line-height: 90rpx;
  letter-spacing: 2rpx;
  margin: 0px 20rpx;
}
.card-btm {
  font-size: 28rpx;
}
.card-btm-item {
  width: 30%;
  line-height: 48rpx;
}
/* 样式2 */
.coupon-box {
  width: 700rpx;
  height: 220rpx;
  overflow: hidden;
  border-radius: 20rpx;
  position: relative;
  background: radial-gradient(circle at right top, transparent 18rpx, var(--c4) 0) top left / 215rpx 51% no-repeat,
    radial-gradient(circle at right bottom, transparent 18rpx, var(--c4) 0) bottom left /215rpx 51% no-repeat,
    radial-gradient(circle at left top, transparent 18rpx, var(--c5) 0) top right /487rpx 51% no-repeat,
    radial-gradient(circle at left bottom, transparent 18rpx, var(--c5) 0) bottom right /487rpx 51% no-repeat;
  filter: drop-shadow(2px 2px 1px rgba(0, 0, 0, .3));
  margin: 20px auto;
  /* 解决filter-导致border-radius生效 */
  transform: translate3d(0, 0, 0);
}
.coupon-box::after {
  content: '';
  height: 184rpx;
  width: 3rpx;
  background-image: linear-gradient(0deg, #fff 50%, transparent 50%);
  background-size: 20rpx 20rpx;
  position: absolute;
  left: 212rpx;
  top: 0;
  bottom: 0;
  margin: auto;

}
.cou-banner {
  position: absolute;
  left: 0;
  top: 0;
  min-width: 130rpx;
  text-align: center;
  padding: 0 10rpx;
  line-height: 45rpx;
  height: 45rpx;
  font-size: 25rpx;
  color: red;
  background: rgba(255, 165, 0, .2);
  border-radius: 20rpx 0 20rpx 0;
}
.cou-left {
  width: 214rpx;
  height: 100%;
  font-size: 25rpx;
  color: red;
}
.cou-left text:nth-child(1) {
  font-size: 35px;
}
.cou-right {
  width: 484rpx;
  height: 100%;
  box-sizing: border-box;
  padding: 20rpx 20rpx 20rpx 35rpx;
  color: #333;
  font-size: 30rpx;
  font-weight: bold;
  line-height: 48rpx;
}
.cou-right-time {
  color: red;
}

4.写在最后🍒

看完本文如果觉得有用,记得点赞+关注+收藏鸭 🍕
更多小程序相关,关注苏苏的bug苏苏的github苏苏的码云~

参考链接:

XboxYan-CSS 实现优惠券的技巧

XboxYan-用纯css来实现一个优惠券

XboxYan-CSS filter 生成不规则边框

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,122评论 6 505
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,070评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,491评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,636评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,676评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,541评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,292评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,211评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,655评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,846评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,965评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,684评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,295评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,894评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,012评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,126评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,914评论 2 355

推荐阅读更多精彩内容