#wrap
-47.times do
.circle
.inner
#controls
.control
%label Delay 1
%input#delay1.slider{:max => "10", :min => "0", :step => "0.005", :type => "range", :value => "5"}/
.control
%label Delay 2
%input#delay2.slider{:max => "10", :min => "0", :step => "0.005", :type => "range", :value => "5"}/
.control
%label Delay 3
%input#delay3.slider{:max => "10", :min => "0", :step => "0.005", :type => "range", :value => "5"}/
.control
%label Offset
%input#offset.slider{:max => "1.15", :min => "0.15", :step => "0.005", :type => "range", :value => "0.25"}/
.control
%label Bezier 1
%input#cubic1.slider{:max => "1", :min => "0", :step => "0.005", :type => "range", :value => "0.5"}/
.control
%label Bezier 2
%input#cubic2.slider{:max => "2", :min => "0", :step => "0.005", :type => "range", :value => "1"}/
.control
%label Bezier 3
%input#cubic3.slider{:max => "1", :min => "0", :step => "0.005", :type => "range", :value => "0.5"}/
.control
%label Bezier 4
%input#cubic4.slider{:max => "2", :min => "0", :step => "0.005", :type => "range", :value => "1.25"}/
.control
%label Hue
%input#hue.slider{:max => "360", :min => "0", :step => "0.005", :type => "range", :value => "0"}/
.control
%label Size
%input#size.slider{:max => "7.5", :min => "5", :step => "0.005", :type => "range", :value => "5"}/
View Compiled
body {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
background: #fff;
--delay1: 5;
--delay2: 5;
--delay3: 5;
--cubic1: 0.5;
--cubic2: 1;
--cubic3: 0.5;
--cubic4: 1.25;
--offset: 0.25;
--hue: 0deg;
--size: 5px;
#controls {
position: absolute;
width: 100%;
bottom: 25px;
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-template-rows: repeat(5, 1fr);
grid-column-gap: 40px;
grid-row-gap: 0px;
padding: 20px 40px;
box-sizing: border-box;
max-width: 350px;
z-index: 10;
@media (max-height: 700px) {
grid-template-columns: repeat(5, 1fr);
grid-template-rows: repeat(2, 1fr);
max-width: 100%;
}
@media (min-width: 768px) and (min-height: 700px) {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-template-rows: repeat(3, 1fr);
max-width: 500px;
height: 175px;
.control {
&:nth-of-type(9) {
grid-area: 5 / 1 / 6 / 3;
padding: 0;
}
&:nth-of-type(10) {
grid-area: 5 / 3 / 6 / 5;
padding: 0;
}
}
}
.control {
padding: 10px 0;
&:hover {
label {
color: #000;
}
}
label {
transition: 0.3s ease-in-out;
color: #666;
width: 100%;
text-align: center;
font-size: 10px;
font-family: Futura;
text-transform: uppercase;
display: block;
}
@for $i from 1 through 4 {
&:nth-of-type(#{$i}) {
input[type="range"]::slider-thumb {
background: #40e0d0;
}
}
}
@for $i from 5 through 8 {
&:nth-of-type(#{$i}) {
input[type="range"]::slider-thumb {
background: #ff8c00;
}
}
}
}
input[type="range"] {
appearance: none;
background: transparent;
width: 100%;
}
input[type="range"]::slider-thumb {
appearance: none;
}
input[type="range"]:focus {
outline: none;
}
input[type="range"]::slider-thumb {
appearance: none;
height: 15px;
width: 15px;
border-radius: 50px;
cursor: pointer;
margin-top: -6px;
background: #ff0080;
box-shadow: 0 0 0 3px #fff, inset 0 0 20px -20px rgba(0, 0, 0, 0.25);
transition: 0.3s ease-in-out;
&:active {
box-shadow: 0 0 0 3px #fff, inset 0 0 20px 20px rgba(0, 0, 0, 0.25);
}
}
input[type="range"]::slider-runnable-track,
input[type="range"]:focus::slider-runnable-track {
height: 2px;
cursor: pointer;
background: #ccc;
border-radius: 25px;
outline: none;
}
}
#wrap {
width: 0px;
height: 0px;
position: relative;
transform: translateY(-75px);
filter: hue-rotate(var(--hue));
&:before,
&:after {
content: "";
border-radius: 100%;
position: absolute;
width: 500px;
height: 500px;
top: calc(50% - 250px);
left: calc(50% - 250px);
background: linear-gradient(to right, #40e0d0, #ff8c00, #ff0080);
animation: rotate 6s linear infinite;
box-shadow: 0 0 0 5px #fff, 0 0 0 7px #40e0d0, 0 0 80px -40px #000;
@keyframes rotate {
to {
transform: rotate(360deg);
}
}
z-index: 10;
mix-blend-mode: darken;
}
&:after {
background: #000;
z-index: 8;
mix-blend-mode: none;
}
.circle {
z-index: 9;
width: 0px;
height: 0px;
position: absolute;
$j: 3;
@for $i from 1 through 4 {
$k: $j;
$j: $j + $j;
@for $h from $k through $j {
&:nth-of-type(#{$h}) {
transform-origin: 50% 50%;
transform: rotate(#{(360 / $k) * $h}deg)
translateY(calc(#{(($k/5) * (240 - $j)) / 10}px * var(--offset)));
.inner {
content: "";
position: absolute;
width: 20px;
height: 20px;
top: 10px;
left: calc(50% - 10px);
border-radius: 100%;
display: inline-block;
animation: bounceIn
3s
cubic-bezier(
var(--cubic1),
var(--cubic2),
var(--cubic3),
var(--cubic4)
)
infinite
alternate;
animation-delay: calc(#{$k / -20}s * var(--delay3));
&:before,
&:after {
content: "";
position: absolute;
display: inline-block;
top: calc(50% - (var(--size) / 2));
left: calc(50% - (var(--size) / 2));
width: var(--size);
height: var(--size);
background: #fff;
border-radius: 100px;
box-shadow: 0 0px #fff, 0px 0 #fff, 0px 0 #fff, 0px 0 #fff;
animation: bounce2
4s
cubic-bezier(
var(--cubic1),
var(--cubic2),
var(--cubic3),
var(--cubic4)
)
infinite,
shadow 2s ease-in-out infinite;
animation-delay: calc(#{$h / -60}s * var(--delay1));
transform-origin: 50% 25px;
@keyframes shadow {
to {
box-shadow: 0 100px 0 -10px #fff, 0px -100px 0 -10px #fff,
100px 0 0 -10px #fff, -100px 0 0 -10px #fff;
}
}
@keyframes bounce2 {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
}
&:after {
animation-delay: calc(#{($h / -20) - 2}s * var(--delay2));
transform-origin: 50% -25px;
}
@keyframes bounceIn {
to {
transform: translateY(50px);
}
}
}
}
}
}
}
}
}
View Compiled
const body = document.body;
const delay1 = document.getElementById("delay1");
const delay2 = document.getElementById("delay2");
const delay3 = document.getElementById("delay3");
const cubic1 = document.getElementById("cubic1");
const cubic2 = document.getElementById("cubic2");
const cubic3 = document.getElementById("cubic3");
const cubic4 = document.getElementById("cubic4");
const offset = document.getElementById("offset");
const hue = document.getElementById("hue");
const size = document.getElementById("size");
body.querySelectorAll(".slider").forEach(slider => {
slider.addEventListener('input', e => {
body.style.setProperty("--delay1", delay1.value);
body.style.setProperty("--delay2", delay2.value);
body.style.setProperty("--delay3", delay3.value);
body.style.setProperty("--cubic1", cubic1.value);
body.style.setProperty("--cubic2", cubic2.value);
body.style.setProperty("--cubic3", cubic3.value);
body.style.setProperty("--cubic4", cubic4.value);
body.style.setProperty("--offset", offset.value);
body.style.setProperty("--hue", hue.value + "deg");
body.style.setProperty("--size", size.value + "px");
});
});
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.