<div class="wrapper">
<heading>
<h1>Circular Wipe</h1>
<p>Hover, tap, or focus below to see transition</p>
</heading>
<div class="scenes" tabindex="0">
<div class="scene-1"></div>
<div class="scene-2"></div>
</div>
<div class="visualizer">
<div class="visualizer-mask"></div>
</div>
<p>This is the <code>clip-path</code> version.</p>
</div>
@font-face {
font-family: "Star Jedi Hollow";
src: url("fonts/Starjedi-hollow.woff2");
}
.scenes {
position: relative;
aspect-ratio: 1920 / 820;
outline: 2px solid #ccc;
width: 100%;
}
.scene-1,
.scene-2 {
position: absolute;
inset: 0;
background-size: cover;
}
.scene-1 {
background-image: url("img/scene-1.jpg");
}
.scene-2 {
clip-path: circle(0% at 50% 50%);
background-image: url("img/scene-2.jpg");
}
@keyframes scene-transition {
100% {
clip-path: circle(85% at 50% 50%);
}
}
.scenes:is(:hover, :focus) .scene-2 {
animation: scene-transition 2s linear forwards;
}
/* everything else */
*,
*::before,
*::after {
box-sizing: border-box;
}
body {
display: grid;
place-items: center;
min-height: 100vh;
margin: 0;
padding: 20px;
color: #fff;
background-color: #111;
font-size: clamp(0.75rem, 0.3rem + 1.9vw, 1.5rem);
font-family: "Roboto", sans-serif;
}
:focus {
outline: 2px solid red;
}
.wrapper {
display: grid;
justify-items: center;
gap: 1.5rem;
width: min(1000px, 100%);
}
.wrapper heading {
text-align: center;
margin: 0;
}
h1 {
font-family: "Star Jedi Hollow", serif;
font-size: clamp(1.5rem, 1.25rem + 1.9vw, 3rem);
color: rgb(255, 255, 44);
margin: 0;
}
.visualizer {
display: flex;
justify-content: center;
width: min(150px, 25vw);
aspect-ratio: 2.4 / 1;
outline: 2px solid #ccc;
background-color: #333;
background-image: linear-gradient(
45deg,
#444 25%,
transparent 25%,
transparent 75%,
#444 75%
),
linear-gradient(45deg, #444 25%, transparent 25%, transparent 75%, #444 75%);
background-size: 16px 16px, 16px 16px;
background-position: 0 0, 8px 8px;
overflow: hidden;
}
.visualizer-mask {
background-color: white;
width: 100%;
height: 100%;
clip-path: circle(0% at 50% 50%);
}
.scenes:is(:hover, :focus) + .visualizer .visualizer-mask {
animation: scene-transition 2s linear forwards;
}
A circular wipe transition between scenes, just like in Star Wars.
I wanted to explore how to execute the effect with the best cross-browser support. This version uses the clip-path
property.
You can read my article where I discuss this implementation and compare it with other methods such as animating a CSS mask using @property
, or animating a SVG mask.