前军教程网

中小站长与DIV+CSS网页布局开发技术人员的首选CSS学习平台

一个CSS小技巧实现 DIV 的凹槽曲线和形状, 惊呆产品经理

新人求关注?,博主天天日更,全年无休,您的关注是我的更新的功力~ 感谢

在编写前端页面的时候,我们会经常遇到编写一些异形的容器元素,例如实现下面这种图形

如果从来没有做过这种案例的同学来说,可能一上来有点蒙,不知道如何下手,今天我们就手摸手帮你实现这种效果,欢迎点赞、关注、收藏,等下次遇到的这些需求的时候,可以直接拷贝代码到项目中,直接亮瞎客户的双眼。 哈哈哈,话不多说,直接 show code

实现这种效果其实也很简单,通过 mask 遮罩实现的,具体代码如下:

关键 CSS

.box {
  --r: 20px; /* control the rounded part*/
  --s: 40px; /* control the size of the cut */
  --a: 40deg; /* control the depth of the curvature*/
  
  --_m:0/calc(2*var(--r)) var(--r) no-repeat
    radial-gradient(50% 100% at bottom,#000 calc(100% - 1px),#0000);
  --_d:(var(--s) + var(--r))*cos(var(--a));
  mask:
    calc(50% + var(--_d)) var(--_m),calc(50% - var(--_d)) var(--_m),
    radial-gradient(var(--s) at 50% calc(-1*sin(var(--a))*var(--s)),
      #0000 100%,#000 calc(100% + 1px)) 0 calc(var(--r)*(1 - sin(var(--a)))) no-repeat,
    linear-gradient(90deg,#000 calc(50% - var(--_d)),#0000 0 calc(50% + var(--_d)),#000 0);
}

代码解释:

1. 定义 CSS 变量

--r: 20px; /* control the rounded part */
--s: 40px; /* control the size of the cut */
--a: 40deg; /* control the depth of the curvature */
  • --r: 20px; 控制圆角部分的半径大小。
  • --s: 40px; 控制切割的尺寸,即凹口的宽度。
  • --a: 40deg; 控制曲线的深度,即凹口的角度。

2. 定义遮罩(mask)的基本单位 --_m

--_m: 0/calc(2*var(--r)) var(--r) no-repeat radial-gradient(50% 100% at bottom,#000 calc(100% - 1px),#0000);

--_m 定义一个基本遮罩图形,使用径向渐变 (radial-gradient) 来创建半圆形的遮罩效果:

  • 0/: 设置背景位置为 (0, 0)。
  • calc(2*var(--r)) var(--r): 设置背景大小为 (2 * 圆角半径) 宽度和 (圆角半径) 高度。
  • no-repeat: 禁止背景图像重复。
  • radial-gradient(...): 使用径向渐变创建一个从底部开始的渐变,其中 50% 100% at bottom 定义了圆心位置在底部中间,#000 calc(100% - 1px) 定义了渐变的颜色,从黑色变为透明。

3. 计算 _d 变量

--_d: (var(--s) + var(--r)) * cos(var(--a));

--_d 变量计算的是凹口宽度一半加上圆角部分的水平偏移量,它用来确定遮罩中曲线的深度。

  • (var(--s) + var(--r)): 计算切割宽度加上圆角半径。
  • cos(var(--a)): 使用 cos 函数计算角度 --a 对应的余弦值,从而调整凹口的宽度。

4. 定义 mask 属性

mask: calc(50% + var(--_d)) var(--_m), calc(50% - var(--_d)) var(--_m),
radial-gradient(var(--s) at 50% calc(-1*sin(var(--a))*var(--s)), #0000 100%, #000 calc(100% + 1px)) 0 calc(var(--r)*(1 - sin(var(--a)))) no-repeat,
linear-gradient(90deg, #000 calc(50% - var(--_d)), #0000 0 calc(50% + var(--_d)), #000 0);

这个 mask 属性结合了四个部分的遮罩图形来实现整体效果:

  • calc(50% + var(--_d)) var(--_m):

定位第一个半圆遮罩图形。通过 calc(50% + var(--_d)) 计算出其中心位置在元素宽度的一半加上偏移量的地方,应用 --_m 作为遮罩图形。

  • calc(50% - var(--_d)) var(--_m):

定位第二个半圆遮罩图形。通过 calc(50% - var(--_d)) 计算出其中心位置在元素宽度的一半减去偏移量的地方,应用 --_m 作为遮罩图形。

  • radial-gradient(...) 0 calc(var(--r)*(1 - sin(var(--a)))) no-repeat:

使用径向渐变创建一个凹口的中间部分:

  • var(--s) 定义了径向渐变的尺寸。

50% calc(-1*sin(var(--a))*var(--s)): 定义圆心位置,垂直方向上调整其位置以实现内凹效果。

#0000 100%, #000 calc(100% + 1px): 定义颜色,从透明到黑色。

  • 0 calc(var(--r)*(1 - sin(var(--a)))) no-repeat: 调整垂直偏移,确保凹口与边缘对齐,不重复。
  • linear-gradient(...):

使用线性渐变填充凹口之间的区域:

90deg: 线性渐变方向为水平。

#000 calc(50% - var(--_d)), #0000 0 calc(50% + var(--_d)), #000 0: 定义了从黑色到透明再回到黑色的渐变。

完整 demo 代码

<div class="box"></div>
<div class="box" style="--a: 20deg"></div>
<div class="box bottom" style="--a: 30deg;--r:30px;--s:20px"></div>

<style>
.box {
  --r: 20px; /* control the rounded part*/
  --s: 40px; /* control the size of the cut */
  --a: 40deg; /* control the depth of the curvature*/
  
  height: 120px;
  margin-block: 20px;
  background: linear-gradient(45deg,#FF4E50,#40C0CB);
  --_m:0/calc(2*var(--r)) var(--r) no-repeat
    radial-gradient(50% 100% at bottom,#000 calc(100% - 1px),#0000);
  --_d:(var(--s) + var(--r))*cos(var(--a));
  mask:
    calc(50% + var(--_d)) var(--_m),calc(50% - var(--_d)) var(--_m),
    radial-gradient(var(--s) at 50% calc(-1*sin(var(--a))*var(--s)),
      #0000 100%,#000 calc(100% + 1px)) 0 calc(var(--r)*(1 - sin(var(--a)))) no-repeat,
    linear-gradient(90deg,#000 calc(50% - var(--_d)),#0000 0 calc(50% + var(--_d)),#000 0);
}
.bottom {
  --_m:100%/calc(2*var(--r)) var(--r) no-repeat
    radial-gradient(50% 100% at top,#000 calc(100% - 1px),#0000);
  mask:
    calc(50% + var(--_d)) var(--_m),calc(50% - var(--_d)) var(--_m),
    radial-gradient(var(--s) at 50% calc(100% + sin(var(--a))*var(--s)),
      #0000 100%,#000 calc(100% + 1px)) 0 calc(var(--r)*(sin(var(--a)) - 1)) no-repeat,
    linear-gradient(90deg,#000 calc(50% - var(--_d)),#0000 0 calc(50% + var(--_d)),#000 0);
}

body {
  margin: 0;
}

</style>

完整效果:

小结

如果您有疑问或者其他问题,欢迎留言评论,大家一起探讨,一起进步~ 欢迎点赞、关注?、转发~

求关注~

发表评论:

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言