Sakura petals take shape
I had an idea for a 404 page that features sakura petals that initially form 404 and then gradually animate into random positions on the page. I got part of the way there today. I built it using parts of a page I made last June, Sakura petals falling with CSS and JS. I made that before learning more about JavaScript and was able to refactor a good portion of the code. I’ll want to build the page in a way that still looks great for anyone that visits such a page with reduced motion settings. Laying things out with grid feels a bit overboard, but I’ll figure out an alternative some other time. I like refreshing the page and watching the petals float away.
View the code:
HTML and JS
<div class="code-block">
<!-- Original petal -->
<svg class="hidden">
<symbol id="petal" >
<path class="petal-size" d="M42.501,11.25c0,0-2.75-14.5-17.75-6.75S2.501,44.25,3.251,53s11.75,22.75,13.75,27
s21,15.75,26,15.75S65.751,82,69.251,77.5s8.25-13.5,7.5-19.25c1.75-8.75,7.5-18.75-0.25-32.25c-8.25-9-10.5-11.25-11.75-14.25
s-13-6.75-16-6.75S42.251,8.25,42.501,11.25z"/>
</symbol>
</svg>
<div class="fourohfour">
<svg class="petal" id="petal1" height="98" width="85" viewbox="0 0 85 98">
<use xlink:href="#petal" />
</svg>
<svg class="petal" id="petal2" height="98" width="85" viewbox="0 0 85 98">
<use xlink:href="#petal" />
</svg>
<svg class="petal" id="petal3" height="98" width="85" viewbox="0 0 85 98">
<use xlink:href="#petal" />
</svg>
<svg class="petal" id="petal4" height="98" width="85" viewbox="0 0 85 98">
<use xlink:href="#petal" />
</svg>
<svg class="petal" id="petal5" height="98" width="85" viewbox="0 0 85 98">
<use xlink:href="#petal" />
</svg>
<svg class="petal" id="petal6" height="98" width="85" viewbox="0 0 85 98">
<use xlink:href="#petal" />
</svg>
<svg class="petal" id="petal7" height="98" width="85" viewbox="0 0 85 98">
<use xlink:href="#petal" />
</svg>
<svg class="petal" id="petal8" height="98" width="85" viewbox="0 0 85 98">
<use xlink:href="#petal" />
</svg>
<svg class="petal" id="petal9" height="98" width="85" viewbox="0 0 85 98">
<use xlink:href="#petal" />
</svg>
<svg class="petal" id="petal10" height="98" width="85" viewbox="0 0 85 98">
<use xlink:href="#petal" />
</svg>
<svg class="petal" id="petal11" height="98" width="85" viewbox="0 0 85 98">
<use xlink:href="#petal" />
</svg>
</div>
</div>
<script>
// ---------
// Variables
// ---------
const petal1pos = document.querySelector('#petal1');
const petal2pos = document.querySelector('#petal2');
const petal3pos = document.querySelector('#petal3');
const petal4pos = document.querySelector('#petal4');
const petal5pos = document.querySelector('#petal5');
const petal6pos = document.querySelector('#petal6');
const petal7pos = document.querySelector('#petal7');
const petal8pos = document.querySelector('#petal8');
const petal9pos = document.querySelector('#petal9');
const petal10pos = document.querySelector('#petal10');
const petal11pos = document.querySelector('#petal11');
// ---------
// Functions
// ---------
function RandoNum(min, max) {
return Math.floor(Math.random() * (max - min + 1) + min);
};
function RandoDecNum(min, max) {
return Math.floor(Math.random() * (max - min + .1) + min);
};
function RotatePetal(petal) {
petal.setAttribute('style', `transform: rotate(${RandoNum(-360,360)}deg) translateX(${RandoNum(-15,15)}px) translateY(${RandoNum(-15,15)}px);`);
};
// ---------
// Events
// ---------
window.addEventListener('load', () => {
RotatePetal(petal1pos);
RotatePetal(petal2pos);
RotatePetal(petal3pos);
RotatePetal(petal4pos);
RotatePetal(petal5pos);
RotatePetal(petal6pos);
RotatePetal(petal7pos);
RotatePetal(petal8pos);
RotatePetal(petal9pos);
RotatePetal(petal10pos);
RotatePetal(petal11pos);
})
// Set left position to a random number between 85px and 210px
</script>
CSS
@keyframes wobble {
0% {
border-radius: 47% 49% 47% 49%;
}
33% {
border-radius: 49% 50% 49% 50%;
}
67% {
border-radius: 45% 46% 46% 45%;
}
100% {
border-radius: 50% 50% 50% 50%;
}
}
.code-block {
background-color: rgb(38, 79, 87, .33 );
padding: 3rem 1rem;
margin: 3rem auto;
border-radius: 100%;
animation: wobble 15s ease-in-out alternate infinite;
position: relative;
z-index: 1;
max-width: 300px;
}
.petal {
fill:rgba(255, 202, 211, 0.9);
stroke: rgba(255, 192, 203, 0.9);
transform-origin: center center;
position: relative;
z-index: 2;
width: 2rem;
height: auto;
transition: opacity 5s ease-out, transform 10s ease-out;
}
.hidden {
display: none;
visibility: hidden;
}
@supports (display: grid) {
.code-block {
display: grid;
place-items: center;
}
.fourohfour {
display: grid;
grid-template-columns: repeat(4, 1rem);
grid-template-rows: repeat(6, 35px);
row-gap: 8px;
column-gap: 1.4rem;
margin: 0 auto;
max-width: 10em;
}
#petal1 { grid-column: 1 / 2; grid-row: 1 / 2;}
#petal2 { grid-column: 3 / 4; grid-row: 1 / 2;}
#petal3 { grid-column: 1 / 2; grid-row: 3 / 4;}
#petal4 { grid-column: 2 / 3; grid-row: 3 / 4;}
#petal5 { grid-column: 3 / 4; grid-row: 3 / 4;}
#petal6 { grid-column: 3 / 4; grid-row: 2 / 3;}
#petal7 { grid-column: 4 / 5; grid-row: 3 / 4;}
#petal8 { grid-column: 3 / 4; grid-row: 4 / 5;}
#petal9 { grid-column: 3 / 4; grid-row: 5 / 6;}
#petal10 { grid-column: 3 / 4; grid-row: 6 / 7;}
#petal11 { grid-column: 1 / 2; grid-row: 2 / 3;}
}