AnimationsSimpleApril 8, 2026
Clip-Path Polygon Video Reveal
Image or video is collapsed to a horizontal line using clip-path polygon. On hover it expands to full rectangle while rising upward. A distinctive hover interaction using pure CSS.
View Full Demo →Preview
Source
index.jsx
import styles from "./styles.module.css";
export default function ClipPathPolygonVideoReveal({ projects = [] }) {
return (
<div className={styles.grid}>
{projects.map((project) => (
<a key={project.title} href={project.href} className={styles.card}>
<div className={styles.videoWrap}>
<div
className={styles.video}
style={{ backgroundImage: `url(${project.image})` }}
/>
</div>
<div className={styles.info}>
<span className={styles.title}>{project.title}</span>
<span className={styles.category}>{project.category}</span>
</div>
</a>
))}
</div>
);
}
styles.module.css
.grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 1.5rem;
padding: 2rem;
}
.card {
display: flex;
flex-direction: column;
gap: 0.75rem;
text-decoration: none;
color: #1a1a1a;
}
/* Clip reveals from center line to full rectangle */
.videoWrap {
position: relative;
aspect-ratio: 4 / 5;
overflow: hidden;
}
.video {
position: absolute;
inset: 0;
background-size: cover;
background-position: center;
background-color: #1a1a1a;
clip-path: polygon(30% 50%, 70% 50%, 70% 50%, 30% 50%);
transform: translateY(-8.33%);
transition: clip-path 700ms cubic-bezier(0.87, 0, 0.13, 1),
transform 700ms cubic-bezier(0.87, 0, 0.13, 1);
}
.card:hover .video {
clip-path: polygon(0% 100%, 100% 100%, 100% 0%, 0% 0%);
transform: translateY(-50%);
}
.info {
display: flex;
justify-content: space-between;
align-items: baseline;
}
.title {
font-size: 0.9375rem;
font-weight: 500;
letter-spacing: -0.01em;
}
.category {
font-size: 0.8125rem;
color: #9b9b9b;
}
@media (max-width: 600px) {
.grid {
grid-template-columns: 1fr;
}
}