<h1 class="Caption">Click to generate the next sequence</h1>
<figure class="Grape">
<figcaption class="Leaves">
<div class="Leaf"></div>
<div class="Leaf"></div>
</figcaption>
<div class="Fruits"></div>
</figure>
$leaf_l_tranform: translate(-110%, -50%);
$leaf_r_tranform: translate(10%, -50%) scale(1.2);
* {
font-family: inherit;
font-size: inherit;
box-sizing: inherit;
padding: 0;
margin: 0;
}
html {
box-sizing: border-box;
overflow-x: hidden;
font-size: 62.5%;
font-family: 'Rubik', sans-serif;
user-select: none;
body {
background-color: #cf8;
width: 100vw;
height: 100vh;
overflow: inherit;
font-size: 1.6rem;
display: flex;
justify-content: center;
align-items: center;
}
}
.Caption {
position: fixed;
width: 100%;
text-align: center;
top: 3rem;
font-size: 2rem;
color: purple;
opacity: 0.75;
}
.Grape {
--layers: 1;
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: center;
transform: translateY(calc(var(--layers) * 2rem - 10vh));
transition: transform .5s;
.Leaves {
position: relative;
transform-origin: 50% 100%;
transform: scale(calc(var(--layers) * 0.2 + 0.8));
transition: transform .5s;
.Leaf {
width: 8rem;
height: 4rem;
position: absolute;
background-color: green;
border-radius: 50%;
border: solid 2px rgba(0,0,0,.3);
&:first-child {
transform-origin: 100% 100%;
transform: $leaf_l_tranform rotate(30deg);
animation: wiggleL 5s ease-in-out infinite;
}
&:last-child {
transform-origin: 0% 100%;
transform: $leaf_r_tranform rotate(-30deg);
animation: wiggleR 5s ease-in-out infinite;
}
&::after {
content: "";
display: block;
position: absolute;
width: 80%;
height: 2rem;
border-radius: 50%;
border-top: 2px solid darkgreen;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
}
}
.Fruits {
display: flex;
flex-direction: column-reverse;
.Row {
display: flex;
justify-content: center;
align-items: center;
animation: expand 0.5s cubic-bezier(.78,.29,.51,1.21);
animation-fill-mode: both;
.Fruit {
--digits: 1;
--delay: 0;
--variant: 0;
--zindex: 0;
width: 5rem;
height: 5rem;
transform: scale(1.5);
position: relative;
background-color: hsl(calc(-90deg + var(--variant) * 60deg), 55%, 40%);
border-radius: 100%;
border: solid 2px rgba(0,0,0,.3);
display: flex;
justify-content: center;
align-items: center;
animation: pop .5s cubic-bezier(.23,1.25,.74,1.33);
animation-fill-mode: backwards;
animation-delay: calc(var(--delay) * 0.1s);
font-size: calc(2.5rem / (0.7 + var(--digits) * 0.3));
color: #fff;
z-index: var(--zindex);
transition: transform .5s, z-index .5s;
&:hover {
z-index: 999999;
transform: scale(1.75);
}
&::before {
content: '';
display: block;
position: absolute;
width: 20%;
height: 20%;
border-radius: 100%;
background-color: rgba(255, 255, 255, .75);
top: 20%;
left: 20%;
}
&::after {
content: '';
display: block;
position: absolute;
top: 0;
left: 0;
width: calc(100% - .8rem);
height: calc(100% - .8rem);
border-radius: 100%;
border-bottom: solid .8rem rgba(0,0,0,.2);
border-right: solid .8rem rgba(0,0,0,.2);
}
}
}
}
}
@keyframes expand {
from {
margin-top: -3em;
}
to {
margin-top: 0em;
}
}
@keyframes pop {
from {
transform: scale(0);
}
to {
transform: scale(1.5);
}
}
@keyframes wiggleL {
0% {
transform: $leaf_l_tranform rotate(20deg);
}
50% {
transform: $leaf_l_tranform rotate(40deg);
}
100% {
transform: $leaf_l_tranform rotate(20deg);
}
}
@keyframes wiggleR {
0% {
transform: $leaf_r_tranform rotate(-20deg);
}
50% {
transform: $leaf_r_tranform rotate(-40deg);
}
100% {
transform: $leaf_r_tranform rotate(-20deg);
}
}
View Compiled
document.body.addEventListener('click', nextGeneration);
document.body.addEventListener('touchend', nextGeneration);
const grape = document.querySelector('.Grape');
const fruits = document.querySelector('.Fruits');
const numbers = [];
function nextGeneration(){
let lastGen = numbers[numbers.length - 1] || [];
let newGen = [];
const row = document.createElement('div');
row.classList.add('Row');
for(let i = 0; i < lastGen.length + 1; i++) {
let number = ((lastGen[i - 1] || 0) + (lastGen[i] || 0)) || 1;
newGen.push(number);
let fruit = document.createElement('div');
fruit.classList.add('Fruit');
fruit.innerText = number;
fruit.style.setProperty('--digits', number.toString().length);
fruit.style.setProperty('--variant', Math.random());
let delay = Math.floor(Math.abs(i - lastGen.length * 0.5));
fruit.style.setProperty('--delay', delay);
fruit.style.setProperty('--zindex', 1000 * numbers.length + 100 - delay);
row.append(fruit);
}
numbers.push(newGen);
fruits.append(row);
grape.style.setProperty('--layers', numbers.length);
}
let timer = setInterval(()=>{
if(numbers.length >= 3){
timer && clearInterval(timer);
}
nextGeneration();
}, 750);
nextGeneration();
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.