<input type="checkbox" name="playPause" id="playPause">
<div class="scene">
<div class="sponge">
<div class="upper">
<div class="slice vertical"></div>
<div class="slice vertical"></div>
<div class="slice vertical"></div>
<div class="slice horizontal"></div>
<div class="slice horizontal"></div>
<div class="slice horizontal"></div>
</div> <!--end of .upper -->
<div class="lower">
<div class="slice vertical"></div>
<div class="slice vertical"></div>
<div class="slice vertical"></div>
<div class="slice horizontal"></div>
<div class="slice horizontal"></div>
<div class="slice horizontal"></div>
</div> <!--end of .lower -->
</div>
</div>
<nav>
<label for="playPause"></label>
</nav>
body {
margin: 0;
height: 100vh;
display: grid;
background-color: #000;
font-size: .7vmin;
filter: sepia() hue-rotate(-30deg) saturate(5);
overflow: hidden;
}
body * {
position: absolute;
transform-style: preserve-3d
}
.scene {
place-self: center;
width: 100em;
aspect-ratio: 1;
animation: zoom 3s ease-in-out infinite alternate;
}
@keyframes zoom {
0% {
perspective: 450em;
}
100% {
perspective: 100em;
}
}
.sponge {
animation: spin 6s linear infinite;
}
@keyframes spin {
0% {
rotate: y 15deg;
}
100% {
rotate: y calc(15deg + 1turn);
}
}
.scene div {
inset: 0;
}
.upper {
--dir: 1;
}
.lower {
--dir: -1;
scale: 1 var(--dir);
}
.sponge > div {
rotate: y calc(90deg*(1 + var(--dir)));
}
.slice {
--angle: calc(acos(cos(30deg)*2/3));
--texture1: repeating-radial-gradient(#000,#bbb, #000 6%);
--texture2: repeating-conic-gradient(#000,#bbb,#000 12deg);
background-blend-mode: multiply, lighten, lighten;
}
.slice:nth-child(3n+1) { --step: 0; }
.slice:nth-child(3n+2) { --step: 1; }
.slice:nth-child(3n+3) { --step: 2; }
.vertical {
rotate: y calc(120deg*var(--step));
clip-path: polygon(
50% 50%,
50% 0,
calc(50%*(1 + sin(var(--angle)))) calc(50%*(1 - cos(var(--angle)))),
calc(50%*(1 + sin(2*var(--angle)))) calc(50%*(1 - cos(2*var(--angle)))) );
background-image: linear-gradient(hsl(0deg 0% calc(75% + 25%*var(--dir))), #000 60%), var(--texture1), var(--texture2);
}
.horizontal {
transform: rotateY(calc(30deg + 120deg*var(--step))) rotateX(var(--angle));
border-radius: 50%;
clip-path: polygon(50% 50%, calc(50%*(1 + sin(var(--angle)))) calc(50%*(1 + cos(var(--angle)))), 50% 100%, calc(50%*(1 - sin(var(--angle)))) calc(50%*(1 + cos(var(--angle)))));
background-image: repeating-conic-gradient(from calc(180deg - var(--angle)), #000, #fff, #000 var(--angle)), var(--texture1), var(--texture2);
}
/* PLAY/PAUSE button */
input {
display: none;
}
nav {
width: max(30em, 108px);
aspect-ratio: 1;
margin: max(5em, 30px);
position: relative;
perspective: 0;
perspective-origin: 100% 50%;
overflow: hidden;
}
label {
position: absolute;
inset: 0;
display: grid;
transform-origin: 0;
margin: 5em;
transition: .5s ease-out;
transition-property: rotate, scale, filter;
filter: drop-shadow(0 0 3em #888);
}
label:hover {
scale: 1 1.25;
filter: drop-shadow(0 0 1em #888);
}
label::before, label::after {
content: '';
position: absolute;
inset-block: 0;
width: 33%;
pointer-events: none;
transition: inherit;
transition-property: box-shadow;
background-color: #000;
}
label::after {
justify-self: end;
}
#playPause:not(:checked) ~ .scene,
#playPause:not(:checked) ~ .scene .sponge {
animation-play-state: paused;
}
#playPause:not(:checked) ~ nav label {
rotate: y 20deg;
}
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.