Creating a Smiley Preloader Animation Using HTML and CSS

Creating a Smiley Preloader Animation Using HTML and CSS

ยท

6 min read

Welcome to Day 8 of my #100DaysOfCode Challenge! Today, we're going to create a fun and eye-catching smiley preloader animation using SVG and CSS. This project will add a touch of personality to your website's loading screen, making it more engaging for your users.

Prerequisites

Before we begin, make sure you have a basic understanding of HTML, CSS, and SVG. You'll also need a text editor and a web browser for testing your code.

Step 1: Set Up Your Project

  1. Create a new directory for your project.

  2. Inside the project directory, create three files: index.html, style.css, and smiley.svg.

Step 2: Write HTML Structure

Open index.html in your text editor and set up the basic HTML structure:

<!DOCTYPE html>
<html lang="en">

<head>
    <!-- Meta tags for character encoding, browser compatibility, and viewport settings -->
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <!-- Link to external stylesheet -->
    <link rel="stylesheet" href="style.css">
    <!-- Title of the document -->
    <title>Smiley Preloader</title>
</head>

<body>
    <!-- SVG element representing the smiley preloader -->
    <svg role="img"
        aria-label="Mouth and eyes come from 9:00 and rotate clockwise into position, right eye blinks, then all parts rotate and merge into 3:00"
        class="smiley" viewBox="0 0 128 128" width="128px" height="128px">
        <!-- Definitions for reusable elements -->
        <defs>
            <!-- Clip path for the eyes -->
            <clipPath id="smiley-eyes">
                <!-- Left eye -->
                <circle class="smiley__eye1" cx="64" cy="64" r="8" transform="rotate(-40,64,64) translate(0,-56)" />
                <!-- Right eye -->
                <circle class="smiley__eye2" cx="64" cy="64" r="8" transform="rotate(40,64,64) translate(0,-56)" />
            </clipPath>
            <!-- Gradient for creating a mask -->
            <linearGradient id="smiley-grad" x1="0" y1="0" x2="0" y2="1">
                <!-- Start color of the gradient -->
                <stop offset="0%" stop-color="#000" />
                <!-- End color of the gradient -->
                <stop offset="100%" stop-color="#fff" />
            </linearGradient>
            <!-- Mask for applying gradient -->
            <mask id="smiley-mask">
                <!-- Masking rectangle -->
                <rect x="0" y="0" width="128" height="128" fill="url(#smiley-grad)" />
            </mask>
        </defs>
        <!-- Group for stroke settings -->
        <g stroke-linecap="round" stroke-width="12" stroke-dasharray="175.93 351.86">
            <!-- First part of the animation -->
            <g>
                <!-- Initial rectangle for the smiley face -->
                <rect fill="hsl(193,90%,50%)" width="128" height="64" clip-path="url(#smiley-eyes)" />
                <!-- Mouth elements -->
                <g fill="none" stroke="hsl(193,90%,50%)">
                    <!-- First mouth shape -->
                    <circle class="smiley__mouth1" cx="64" cy="64" r="56" transform="rotate(180,64,64)" />
                    <!-- Second mouth shape -->
                    <circle class="smiley__mouth2" cx="64" cy="64" r="56" transform="rotate(0,64,64)" />
                </g>
            </g>
            <!-- Second part of the animation -->
            <g mask="url(#smiley-mask)">
                <!-- Animated rectangle for the smiley face -->
                <rect fill="hsl(223,90%,50%)" width="128" height="64" clip-path="url(#smiley-eyes)" />
                <!-- Mouth elements for the second part of the animation -->
                <g fill="none" stroke="hsl(223,90%,50%)">
                    <!-- First mouth shape -->
                    <circle class="smiley__mouth1" cx="64" cy="64" r="56" transform="rotate(180,64,64)" />
                    <!-- Second mouth shape -->
                    <circle class="smiley__mouth2" cx="64" cy="64" r="56" transform="rotate(0,64,64)" />
                </g>
            </g>
        </g>
    </svg>
</body>

</html>

Step 3: Style Your Smiley Preloader

Open style.css and add the following CSS code to style the smiley preloader animation:

/* Resetting default styles for all elements */
* {
    border: 0;
    box-sizing: border-box;
    margin: 0;
    padding: 0;
}

/* Defining root variables for hue, background color, foreground color, and transition duration */
:root {
    --hue: 223;
    /* Default hue value */
    --bg: hsl(var(--hue), 90%, 90%);
    /* Background color derived from hue */
    --fg: hsl(var(--hue), 90%, 10%);
    /* Foreground color derived from hue */
    --trans-dur: 0.3s;
    /* Transition duration */
    /* Responsive font size calculation */
    font-size: calc(16px + (20 - 16) * (100vw - 320px) / (1280 - 320));
}

/* Styling for the body */
body {
    background-color: var(--bg);
    /* Background color */
    color: var(--fg);
    /* Foreground color */
    font: 1em/1.5 sans-serif;
    /* Font settings */
    height: 100vh;
    /* Full height */
    display: grid;
    /* Grid layout */
    place-items: center;
    /* Center alignment */
    transition: background-color var(--trans-dur), color var(--trans-dur);
    /* Transition effect for color changes */
}

/* Styling for the smiley SVG element */
.smiley {
    width: 8em;
    /* Width */
    height: 8em;
    /* Height */
}

/* Animation for eyes */
.smiley__eye1,
.smiley__eye2,
.smiley__mouth1,
.smiley__mouth2 {
    animation: eye1 3s ease-in-out infinite;
    /* Eye animation */
}

/* Eye styles */
.smiley__eye1,
.smiley__eye2 {
    transform-origin: 64px 64px;
    /* Transform origin */
}

/* Second eye animation */
.smiley__eye2 {
    animation-name: eye2;
}

/* First mouth animation */
.smiley__mouth1 {
    animation-name: mouth1;
}

/* Second mouth animation */
.smiley__mouth2 {
    animation-name: mouth2;
    visibility: hidden;
    /* Initially hidden */
}

/* Dark theme media query */
@media (prefers-color-scheme: dark) {
    :root {
        --bg: hsl(var(--hue), 90%, 10%);
        /* Dark background color */
        --fg: hsl(var(--hue), 90%, 90%);
        /* Dark foreground color */
    }
}

/* Eye animations */
@keyframes eye1 {
    from {
        transform: rotate(-260deg) translate(0, -56px);
        /* Initial position */
    }

    50%,
    60% {
        animation-timing-function: cubic-bezier(0.17, 0, 0.58, 1);
        /* Timing function */
        transform: rotate(-40deg) translate(0, -56px) scale(1);
        /* Intermediate position */
    }

    to {
        transform: rotate(225deg) translate(0, -56px) scale(0.35);
        /* Final position */
    }
}

@keyframes eye2 {
    from {
        transform: rotate(-260deg) translate(0, -56px);
        /* Initial position */
    }

    50% {
        transform: rotate(40deg) translate(0, -56px) rotate(-40deg) scale(1);
        /* Intermediate position */
    }

    52.5% {
        transform: rotate(40deg) translate(0, -56px) rotate(-40deg) scale(1, 0);
        /* Intermediate position */
    }

    55%,
    70% {
        animation-timing-function: cubic-bezier(0, 0, 0.28, 1);
        /* Timing function */
        transform: rotate(40deg) translate(0, -56px) rotate(-40deg) scale(1);
        /* Intermediate position */
    }

    to {
        transform: rotate(150deg) translate(0, -56px) scale(0.4);
        /* Final position */
    }
}

/* Mouth animations */
@keyframes mouth1 {
    from {
        animation-timing-function: ease-in;
        /* Timing function */
        stroke-dasharray: 0 351.86;
        /* Initial stroke dash array */
        stroke-dashoffset: 0;
        /* Initial stroke dash offset */
    }

    25% {
        animation-timing-function: ease-out;
        /* Timing function */
        stroke-dasharray: 175.93 351.86;
        /* Intermediate stroke dash array */
        stroke-dashoffset: 0;
        /* Intermediate stroke dash offset */
    }

    50% {
        animation-timing-function: steps(1, start);
        /* Timing function */
        stroke-dasharray: 175.93 351.86;
        /* Final stroke dash array */
        stroke-dashoffset: -175.93;
        /* Final stroke dash offset */
        visibility: visible;
        /* Make visible */
    }

    75%,
    to {
        visibility: hidden;
        /* Hidden */
    }
}

@keyframes mouth2 {
    from {
        animation-timing-function: steps(1, end);
        /* Timing function */
        visibility: hidden;
        /* Hidden */
    }

    50% {
        animation-timing-function: ease-in-out;
        /* Timing function */
        visibility: visible;
        /* Make visible */
        stroke-dashoffset: 0;
        /* Final stroke dash offset */
    }

    to {
        stroke-dashoffset: -351.86;
        /* Initial stroke dash offset */
    }
}

Step 6: Preview Your Smiley Preloader

Open index.html in your web browser to see the smiley preloader animation in action.

Step 7: Download Full Source Code

You can download the full source code for this project from the following link: Download Source Code

Conclusion

Congratulations! You've successfully created a smiley preloader animation using SVG and CSS. This fun animation will add a delightful touch to your website's loading screen, enhancing the user experience. Feel free to customize the animation further to match your website's design.

If you have any questions or feedback, don't hesitate to reach out to me:

Stay tuned for more exciting coding projects as I continue my #100DaysOfCode Challenge. Happy coding! ๐Ÿ˜Š๐Ÿš€

Did you find this article valuable?

Support Aarzoo Islam by becoming a sponsor. Any amount is appreciated!

ย