Sakura petals take shape


by Jeremy Caudle
code

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;}

            }