CSS小技巧之绘制心形图案

本文翻译自 CSS Shapes: The Heart,作者: Temani Afif, 略有删改。

我们将使用CSS创建一个心形图案。你可能会说:"为什么又一篇关于心形的文章?已经做过很多了!"。我们不会只建立一个心形图案,我们会使用现代的CSS技巧来实现。忘记带有border-radiusrotation的伪元素。我们也将把图像转化为心形图案!

使用CSS渐变

第一种实现方法,我们将基于多个渐变来创建一个心形图案。

css 复制代码
.heart {
  --c: red;
  width: 200px;
  aspect-ratio: 1;
  background:
   /* 1 */ radial-gradient(circle at 60% 65%,var(--c) 64%,#0000 65%) top left/50% 50%,
   /* 2 */ radial-gradient(circle at 40% 65%,var(--c) 64%,#0000 65%) top right/50% 50%,
   /* 3 */ conic-gradient(from -45deg at 50% 85.5%,var(--c) 90deg,#0000 0) bottom/100% 50%;
  background-repeat: no-repeat;
}

我们使用aspect-ratio: 1定义一个正方形元素。然后使用三个渐变层来创建最终的形状。这里有一个插图来理解每个渐变的实际作用位置。

每个radial-gradient()将占据顶部元素的四分之一,以创建形状的圆形部分。conic-gradient()将在底部创建三角形部分。

可以通过调整宽度值来控制的心形图案大小和CSS变量来改变颜色。

值得注意的是,我们可以找到不同的语法来使用渐变实现相同的结果。下面是另一个代码较少的例子:

css 复制代码
.heart {
  --c: red;
  width: 200px;
  aspect-ratio: 1;
  background:
   radial-gradient(at 70% 31%,var(--c) 29%,#0000 30%),
   radial-gradient(at 30% 31%,var(--c) 29%,#0000 30%),
   conic-gradient(from -45deg at 50% 84%,var(--c) 90deg,#0000 0) 
    bottom/100% 50% no-repeat;
}

但都有相同的配置:两个radial-gradient()和一个conic-gradient(),只是书写不同。

使用 Clip-path

有时当我们使用conic-gradient()可能会遇到一些锯齿边缘的问题。为了避免这种情况,我们可以使用clip-path

css 复制代码
.heart {
  --c: red;
  width: 200px;
  aspect-ratio: 1;
  background:
   radial-gradient(at 70% 31%,var(--c) 29%,#0000 30%),
   radial-gradient(at 30% 31%,var(--c) 29%,#0000 30%),
   linear-gradient(var(--c) 0 0) bottom/100% 50% no-repeat;
  clip-path: polygon(-43% 0,50% 91%, 143% 0);
}

使用linear-gradient()替换了conic-gradient(),用主色覆盖底部区域。然后使用clip-path剪切元素并创建三角形形状:

使用 border-image

我们可以继续优化代码,用一个渐变替换三个渐变。我们将在使用border-image中使用radial-gradient()

css 复制代码
.heart {
  --c: red;
  width: 200px;
  aspect-ratio: 1;
  border-image: radial-gradient(var(--c) 69%,#0000 70%) 84.5%/50%;
  clip-path: polygon(-42% 0,50% 91%, 142% 0);
}

看上面的border-image语法可能有点难理解,让我们仔细分析一下。它是以下的简写:

css 复制代码
border-image-source: radial-gradient(var(--c) 69%,#0000 70%);
border-image-slice: 84.5%;
border-image-width: 50%;

最棘手的值是border-image-slice。可能需要一篇文章来解释这个概念,所以我会尽量让它简单。当你在切片中使用100%时,每个角上都会有一个圆圈。使用50%将给予你一个完整的圆覆盖整个元素。如果你手动使用50%和100%之间的值,你可以得到我们需要的形状。值为84.5%。

最后我们应用clip-path,得到心形图案的效果,如下图所示:

把图像变成一心形

实现一个心形图案是好的,但把在一个图像里面实现心形会更好!为此,我们将使用mask重用前面的代码。使用background的方法将依赖于mask,带边框的方法将依赖于mask-border

但现在mask-border的浏览器支持非常低,因此将依赖于mask属性作为降级。

css 复制代码
img {
  width: 250px;
  aspect-ratio: 1;
  --_m: radial-gradient(#000 69%,#0000 70%) 84.5%/50%;
  -webkit-mask-box-image: var(--_m);
             mask-border: var(--_m);
  clip-path: polygon(-42% 0,50% 91%, 142% 0);
}

/* fallback until better support for mask-border */
@supports not (-webkit-mask-box-image: var(--_m)) { 
  img {
   --_m:
     radial-gradient(at 70% 31%,var(--c) 29%,#0000 30%),
     radial-gradient(at 30% 31%,var(--c) 29%,#0000 30%),
     linear-gradient(#000 0 0) bottom/100% 50% no-repeat;
   -webkit-mask: var(--_m);
           mask: var(--_m);
  }
}

我们用一个小技巧把我们的图像变成了一个心形。由于前缀和浏览器的支持,代码看起来有点长,但将来它只会是这一个:

css 复制代码
img {
  width: 250px;
  aspect-ratio: 1;
  mask-border: radial-gradient(#000 69%,#0000 70%) 84.5%/50%
  clip-path: polygon(-42% 0,50% 91%, 142% 0);
}

增加一个很酷的悬停效果来显示您的心形图像:

最后

没有伪元素,没有圆角,没有旋转。使用现代CSS技巧,基于一个元素和几行代码既可创建一个心形图案。


看完本文如果觉得有用,记得点个赞支持,收藏起来说不定哪天就用上啦~

专注前端开发,分享前端相关技术干货,公众号:南城大前端(ID: nanchengfe)

相关推荐
Chengbei1143 分钟前
云安全漏洞挖掘SKILL、一站式云漏洞挖掘工具,支持S3爆破、IMDS探测、K8s检测与AK/SK权限利用
前端·人工智能·网络安全·云原生·容器·kubernetes·系统安全
不简说1 小时前
JS 代码技巧 vol.9 — 20 个设计模式在真实项目里的应用
前端·javascript·github
CoderLiu1 小时前
Agent 工程的下一层:为什么「把流程写成图」还不够,还需要 Graph Engineering
前端·人工智能·后端
勇往直前plus1 小时前
Vue3(篇三) Element Plus
前端·javascript·typescript·vue
爱勇宝1 小时前
《道德经》第 8 章:真正高级的能力,像水一样成事
前端·后端·程序员
Revolution612 小时前
数组本身没有 map,为什么还能直接调用:原型链怎样查找属性
前端·javascript·面试
bonechips2 小时前
RAG实战(一):EPUB 加载、文本切割与向量入库
前端·数据库
swipe2 小时前
10|(前端转全栈)库存扣减为什么最容易出事故?SKU、并发与原子更新
前端·后端·全栈
cdcdhj2 小时前
vue3中的watchEffect()监听,什么时候监听,什么时候清理,什么时候停止
前端·javascript·vue.js
huabuyu2 小时前
几百 MB 的文件为什么等几分钟才能打开?文件分片下载与渐进预览原理
前端·javascript