- const RING_COUNT = 21;
.container
.scene
.scene__shadow
.plane(style=`--ring-count: ${RING_COUNT}`)
.plane__shadow
- let rings = 0;
while rings < RING_COUNT
.ring(style=`--index: ${rings}; --name: slink-${rings}`)
- rings++;
View Compiled
*
*:after
*:before
box-sizing border-box
transform-style preserve-3d
:root
--border-width 1.2vmin
--depth 20vmin
--stack-height 6vmin
--scene-size 20vmin
--ring-size calc(var(--scene-size) * 0.6)
--plane radial-gradient(hsla(0, 0%, 0%, 0.1) 50%, transparent 65%)
--ring-shadow hsla(0, 0%, 0%, 0.5)
--hue-one 320
--hue-two 210
--blur 10px
--speed 1.2s
--bg hsl(0, 0%, 98%)
--ring-filter brightness(1) drop-shadow(0 0 0 var(--accent))
@media(prefers-color-scheme dark)
--bg hsl(0, 0%, 15%)
--ring-shadow 'hsla(%s, 100%, 50%, 1)' % var(--hue-one)
--plane 'radial-gradient(hsla(%s, 90%, 60%, 0.1) 50%, transparent 65%)' % var(--hue-one)
--ring-filter brightness(1.75) drop-shadow(0 0 1vmin var(--accent))
body
background var(--bg)
min-height 100vh
display grid
place-items center
overflow hidden
.scene
height var(--scene-size)
width var(--scene-size)
animation step-up var(--speed) infinite ease
&__shadow
position absolute
top 0
left 100%
height 100%
width 100%
animation fade-in var(--speed) infinite linear
background var(--plane)
transform scale(1.25)
filter blur(var(--blur))
.flipper
height var(--scene-size)
width var(--scene-size)
animation flip-flop calc(var(--speed) * 2) infinite steps(1)
@keyframes flip-flop
0%
transform rotate(0deg)
50%
transform rotate(180deg)
100%
transform rotate(360deg)
.plane
height 100%
width 100%
transform translateZ(var(--depth))
position relative
&__shadow
content ''
height 100%
width 100%
position absolute
top 50%
left 50%
background var(--plane)
filter blur(var(--blur))
transform translate(-50%, -50%) scale(1.25)
animation fade-out var(--speed) infinite linear
.scene__shadow
.plane__shadow
&:after
content ''
height var(--ring-size)
width var(--ring-size)
position absolute
top 50%
left 50%
border var(--border-width) solid var(--ring-shadow)
border-radius 50%
transform translate(-50%, -50%) scale(0.8)
.container
transform translateZ(100vmin) rotateX(-12deg) rotateY(0deg) rotateX(90deg) translateZ(calc(var(--depth) * -1.5)) rotate(0deg)
animation rotate-scene calc(var(--speed) * 40) infinite linear
.ring
--origin-z calc(var(--stack-height) - (var(--stack-height) / var(--ring-count)) * var(--index))
--destination-z calc(((var(--depth) + var(--origin-z)) - (var(--stack-height) - var(--origin-z))) * -1)
--hue var(--hue-one)
--accent 'hsl(%s 100% 55%)' % var(--hue)
--ring-filter brightness(1) drop-shadow(0 0 0 var(--accent))
height var(--ring-size)
width var(--ring-size)
border-radius 50%
border var(--border-width) solid var(--accent)
position absolute
top 50%
left 50%
transform-origin calc(100% + (var(--scene-size) * 0.2)) 50%
animation-name var(--name)
animation-duration var(--speed)
animation-iteration-count infinite
animation-timing-function cubic-bezier(.25,0,1,1)
filter var(--ring-filter)
&:nth-of-type(odd)
--hue var(--hue-two)
@media(prefers-color-scheme dark)
--ring-filter brightness(2) drop-shadow(0 0 calc(var(--border-width) * 0.5) var(--accent))
// STYLUS GENERATED KEYFRAMES BE HERE...
$ring-count = 21
$animation-window = 50
$animation-step = $animation-window / $ring-count
// Need to generate the keyframes here.
// This would be a great use case for animation-repeat-delay instead of padding out
// keyframes. We would be able to reuse dynamic delays with the same keyframes.
// Need to generate keyframes based on ring-count and given a set window within the keyframes.
// For example; 50% of the window for 10 rings.
for $ring in (0..$ring-count)
// Generate a set of keyframes based on the ring index
// index is the ring
$start = $animation-step * ($ring + 1)
@keyframes slink-{$ring} {
// In here is where we need to generate the keyframe steps based on ring count and window.
0%, {$start * 1%} {
transform translate3d(-50%, -50%, var(--origin-z)) translateZ(0) rotateY(0deg)
}
// Flip without falling
{($start + ($animation-window * 0.75)) * 1%} {
transform translate3d(-50%, -50%, var(--origin-z)) translateZ(0) rotateY(180deg)
}
// Fall until cut off point
{($start + $animation-window) * 1%}, 100% {
transform translate3d(-50%, -50%, var(--origin-z)) translateZ(var(--destination-z)) rotateY(180deg)
}
}
@keyframes fade-in {
{$animation-window * 1%}, 0% {
opacity 0
}
{$animation-window * 1.5%}, 100% {
opacity 1
}
}
@keyframes fade-out {
0% {
opacity 1
}
{$animation-window * 1.5%}, 100% {
opacity 0
}
}
@keyframes step-up
to
transform translate3d(-100%, 0, var(--depth))
@keyframes rotate-scene
to
transform translateZ(100vmin) rotateX(-12deg) rotateY(0deg) rotateX(90deg) translateZ(calc(var(--depth) * -1.5)) rotate(360deg)
View Compiled
// 404
View Compiled
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.