本文探讨如何利用 CSS clip-path 属性实现类似 Material Design 的动态圆形展开菜单效果。通过对比 box-shadow 和 radial-gradient 等方案的局限性,详细解析使用 clip-path 进行区域裁剪的优势。文章提供了完整的 CSS 代码示例,展示如何通过改变 clip-path 参数实现从中心圆到全屏矩形的平滑过渡,同时解决内部 DOM 元素定位与交互问题。
背景
在浏览 CodePen 时,发现了一个极具创意的交互效果:

CodePen Demo -- Material Design Menu By Bennett Feely
该效果包含若干值得深入分析与学习的技术细节,接下来我们将逐一探讨。
如何复现此类效果?
首先思考,若由你来实现上述视觉效果,会采取何种方案?
此处简要列举几种可能的实现路径:
- 阴影 box-shadow
- 渐变 radial-gradient
- 缩放 transform: scale()
接下来快速逐一分析这些方案。
使用 box-shadow 实现
若采用 box-shadow,代码结构大致如下:
<div class="g-container">
<div class="g-item"></div>
</div>
.g-container {
position: relative;
width: 400px;
height: 300px;
overflow: hidden;
}
.g-item {
position: absolute;
width: 48px;
height: 48px;
border-radius: 50%;
background: #fff;
top: 20px;
left: 20px;
box-shadow: 0 0 0 0 #fff;
transition: box-shadow .3s linear;
&:hover {
box-shadow: 0 0 0 420px #fff;
}
}
其核心逻辑在于:
- 外层容器设置
overflow: hideen以创建遮罩层 - 内部元素在 hover 状态下,实现从
box-shadow: 0 0 0 0 #fff到box-shadow: 0 0 0 420px #fff的属性变化
视觉效果如下:

尽管动画效果得以模拟,但存在两个致命缺陷:
- 当鼠标移出圆形区域时,动画会反向执行,白色区域迅速收缩,导致用户无法完成按钮点击操作
- 动画展开后矩形区域内的元素定位困难
因此,box-shadow 方案虽视觉效果良好,但实际应用中不得不放弃。相关 Demo 代码见 -- CodePen Demo -- box-shadow zoom in animation
使用渐变 radial-gradient 实现
接下来,结合径向渐变 radial-gradient 与 CSS @property 特性,亦可还原上述效果:
<div class="g-container"></div>
@property --size {
syntax: '<length>';
inherits: false;
initial-value: 24px;
}
.g-container {
position: relative;
width: 400px;
height: 300px;
overflow: hidden;
background: radial-gradient(circle at 44px 44px, #fff 0, #fff var(--size), transparent var(--size), transparent 0);
transition: --size .3s linear;
&:hover {
--size: 450px;
}
}
通过控制径向渐变的动画过程,在 hover 状态下使原本的小圆背景扩展为大圆背景,效果如下:

虽然视觉效果得以还原,但问题同样显著:
- 由于依赖背景变化,鼠标无需悬停于小圆之上,只要进入 div 范围动画即触发,这不符合交互逻辑
- 与第一种
box-shadow方案类似,隐藏在白色背景下的导航元素 DOM 结构难以合理放置
相关 Demo 代码见 -- CodePen Demo -- radial-gradient zoom in animation
此外,通过缩放 transform: scale() 的方法也存在类似问题,此处不再赘述。
综上所述,实现该效果的关键在于:
- 鼠标必须悬停于圆形区域方可触发动画,且鼠标在展开后的区域内自由移动时,动画效果不应收回
- 动画展开后,内部 DOM 元素的布局应简便,最好无需借助 Javascript 控制内容的显示与隐藏
利用 clip-path 实现动态区域裁剪
因此,我们需要一种动态的区域裁剪机制。
在文章 -- 如何不使用 overflow: hidden 实现 overflow: hidden? 中,介绍了 CSS 中几种元素裁剪方式,其中最适合此场景的是 -- clip-path。
借助 clip-path,可以非常高效地实现动态裁剪功能,且代码简洁:
<div class="g-container"></div>
.g-container {
position: relative;
width: 400px;
height: 300px;
overflow: hidden;
transition: clip-path .3s linear;
clip-path: circle(20px at 44px 44px);
background: #fff;
&:hover {
clip-path: circle(460px at 44px 44px);
}
}
只需利用 clip-path,初始时将矩形 div 通过 clip-path: circle(20px at 44px 44px) 裁剪为圆形,在 hover 状态下将裁剪圆的半径扩大至覆盖整个矩形区域即可。
效果如下:

如此,即可完美复现题图效果,且内置的 DOM 元素可直接置于该 div 内部。
<div class="g-container">
<ul>
<li>11111</li>
<li>22222</li>
<li>33333</li>
<li>44444</li>
</ul>
</div>
效果如下:

CodePen Demo -- clip-path zoom in animation
这是一个非常实用的技巧,通过 clip-path 实现动态区域裁剪,希望大家能熟练掌握。
到此这篇关于JS利用 clip-path 实现动态区域裁剪功能的文章就介绍到这了,更多相关clip-path区域裁剪内容请搜索本站以前的文章或继续浏览下面的相关文章希望大家以后多多支持本站!