How to Create Soccer Preloader Animation using HTML & CSS

How to Create Soccer Preloader Animation using HTML & CSS

Let’s create a Soccer Preloader Animation using HTML and CSS. This preloader will feature a fun soccer ball animation, perfect for adding a sporty and engaging touch to your website’s loading screen.

We’ll use HTML to structure the soccer ball and CSS to animate it, simulating movement and rotation for a dynamic and playful effect.

Let’s get started on building the Soccer Preloader Animation. Whether you’re a beginner or an experienced developer, this project offers a fun way to practice your animation skills and create a lively preloader. Let’s kick-start creativity with this sporty animation!

HTML :

This code creates a visually dynamic soccer ball preloader animation using SVG and CSS. It defines complex shapes, patterns, and gradients through <defs> and reusable <g> groups to design a rotating soccer ball with hexagonal textures and colored stripes. Filters like Gaussian blur add shadow effects, while transformations create a smooth animated appearance, making it suitable for enhancing user experience during loading times.

<!DOCTYPE html>
<html lang="en" >
<head>
  <meta charset="UTF-8">
  <title>Soccer Preloader</title>
  <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"><link rel="stylesheet" href="./style.css">

</head>
<body>

<svg class="pl" viewBox="0 0 56 56" width="56px" height="56px" role="img" aria-label="Soccer ball">
    <clipPath id="ball-clip">
        <circle r="8" />
    </clipPath>
    <defs>
        <path id="hex" d="M 0 -9.196 L 8 -4.577 L 8 4.661 L 0 9.28 L -8 4.661 L -8 -4.577 Z" />
        <g id="hex-chunk" fill="none" stroke="hsl(var(--hue),10%,10%)" stroke-width="0.5">
            <use href="#hex" fill="hsl(var(--hue),10%,10%)" />
            <use href="#hex" transform="translate(16,0)"/>
            <use href="#hex" transform="rotate(60) translate(16,0)"/>
        </g>
        <g id="hex-pattern" transform="scale(0.333)">
            <use href="#hex-chunk" />
            <use href="#hex-chunk" transform="rotate(30) translate(0,48) rotate(-30)" />
            <!-- use 16 * (Math.sqrt(3) / 2) * 2 for these y-translations -->
            <use href="#hex-chunk" transform="rotate(-180) translate(0,27.7) rotate(180)" />
            <use href="#hex-chunk" transform="rotate(-120) translate(0,27.7) rotate(120)" />
            <use href="#hex-chunk" transform="rotate(-60) translate(0,27.7) rotate(60)" />
            <use href="#hex-chunk" transform="translate(0,27.7)" />
            <use href="#hex-chunk" transform="rotate(60) translate(0,27.7) rotate(-60)" />
            <use href="#hex-chunk" transform="rotate(120) translate(0,27.7) rotate(-120)" />
        </g>
        <g id="ball-texture" transform="translate(0,-3.5)">
            <use href="#hex-pattern" transform="translate(-48,0)" />
            <use href="#hex-pattern" transform="translate(-32,0)" />
            <use href="#hex-pattern" transform="translate(-16,0)" />
            <use href="#hex-pattern" transform="translate(0,0)" />
            <use href="#hex-pattern" transform="translate(16,0)" />
        </g>
    </defs>
    <filter id="ball-shadow-inside">
        <feGaussianBlur in="SourceGraphic" stdDeviation="2" />
    </filter>
    <filter id="ball-shadow-outside">
        <feGaussianBlur in="SourceGraphic" stdDeviation="1" />
    </filter>
    <g transform="translate(28,28)">
        <g class="pl__stripe-dot-group" fill="var(--red)">
            <circle class="pl__stripe-dot" transform="rotate(32) translate(-18.25,0)" />
            <circle class="pl__stripe-dot" transform="rotate(87) translate(-18.25,0)" />
            <circle class="pl__stripe-dot" transform="rotate(103) translate(-18.25,0)" />
            <circle class="pl__stripe-dot" transform="rotate(138) translate(-18.25,0)" />
            <circle class="pl__stripe-dot" transform="rotate(228) translate(-18.25,0)" />
            <circle class="pl__stripe-dot" transform="rotate(243) translate(-18.25,0)" />
            <circle class="pl__stripe-dot" transform="rotate(328) translate(-18.25,0)" />
        </g>
        <g class="pl__stripe-dot-group" fill="var(--white)">
            <circle class="pl__stripe-dot" transform="rotate(41) translate(-15.75,0)" />
            <circle class="pl__stripe-dot" transform="rotate(77) translate(-15.75,0)" />
            <circle class="pl__stripe-dot" transform="rotate(92) translate(-15.75,0)" />
            <circle class="pl__stripe-dot" transform="rotate(146) translate(-15.75,0)" />
            <circle class="pl__stripe-dot" transform="rotate(175) translate(-15.75,0)" />
            <circle class="pl__stripe-dot" transform="rotate(293) translate(-15.75,0)" />
            <circle class="pl__stripe-dot" transform="rotate(314) translate(-15.75,0)" />
            <circle class="pl__stripe-dot" transform="rotate(340) translate(-15.75,0)" />
        </g>
        <g class="pl__stripe-dot-group" fill="var(--blue)">
            <circle class="pl__stripe-dot" transform="rotate(20) translate(-13.25,0)" />
            <circle class="pl__stripe-dot" transform="rotate(55) translate(-13.25,0)" />
            <circle class="pl__stripe-dot" transform="rotate(77) translate(-13.25,0)" />
            <circle class="pl__stripe-dot" transform="rotate(106) translate(-13.25,0)" />
            <circle class="pl__stripe-dot" transform="rotate(128) translate(-13.25,0)" />
            <circle class="pl__stripe-dot" transform="rotate(174) translate(-13.25,0)" />
            <circle class="pl__stripe-dot" transform="rotate(279) translate(-13.25,0)" />
        </g>
        <g fill="none" stroke-linecap="round" stroke-width="2.5" transform="rotate(-90)">
            <g class="pl__stripe-rotate">
                <circle class="pl__stripe pl__stripe--1" r="18.25" stroke="var(--red)" stroke-dasharray="114.7 114.7" />
            </g>
            <g class="pl__stripe-rotate">
                <circle class="pl__stripe pl__stripe--2" r="15.75" stroke="var(--white)" stroke-dasharray="106.8 106.8" />
            </g>
            <g class="pl__stripe-rotate">
                <circle class="pl__stripe pl__stripe--3" r="13.25" stroke="var(--blue)" stroke-dasharray="99 99" />
            </g>
        </g>
        <g class="pl__ball" transform="translate(0,-15.75)">
            <circle class="pl__ball-shadow" filter="url(#ball-shadow-outside)" fill="hsla(var(--hue),10%,10%,0.5)" r="8" cx="1" cy="1" />
            <circle fill="var(--white)" r="8" />
            <g clip-path="url(#ball-clip)">
                <use class="pl__ball-texture" href="#ball-texture" />
            </g>
            <circle class="pl__ball-shadow" clip-path="url(#ball-clip)" filter="url(#ball-shadow-inside)" fill="none" stroke="hsla(var(--hue),10%,10%,0.3)" stroke-width="5" r="12" cx="-4" cy="-4" />
        </g>
    </g>
</svg>
  
</body>
</html>

CSS :

This code defines a responsive, animated ball with stripes using CSS. It starts with a universal reset and global variables for colors, fonts, and animation durations. The :root sets theme variables, body applies styles and transitions for a flexible layout, and the .pl class centers the loader. The .pl__ball and related elements are animated with @keyframes, creating a spinning, bouncing ball effect with dynamic stripes and dots, using calculated delays and infinite iterations for smooth looping.

* {
  border: 0;
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

:root {
  --hue: 210;
  --bg: hsl(var(--hue),10%,85%);
  --fg: hsl(var(--hue),10%,15%);
  --red: hsl(344,75%,40%);
  --white: hsl(0,0%,100%);
  --blue: hsl(213,81%,21%);
  --trans-dur: 0.3s;
  font-size: clamp(1rem,0.95rem + 0.25vw,1.25rem);
}

body {
  background-color: var(--bg);
  color: var(--fg);
  display: flex;
  font: 1em/1.5 sans-serif;
  height: 100vh;
  transition: background-color var(--trans-dur), color var(--trans-dur);
}

.pl {
  --dur: 3s;
  display: block;
  margin: auto;
  width: 14em;
  height: auto;
}

.pl__ball, 
.pl__ball-shadow, 
.pl__ball-texture, 
.pl__stripe, 
.pl__stripe-dot, 
.pl__stripe-rotate {
  animation-duration: var(--dur);
  animation-timing-function: linear;
  animation-iteration-count: infinite;
}
.pl__ball {
  animation-name: ball;
}
.pl__ball-shadow {
  animation-name: ball-shadow;
}
.pl__ball-texture {
  animation-name: ball-texture;
}
.pl__stripe {
  animation-name: stripe;
}
.pl__stripe--1 {
  animation-name: stripe1;
}
.pl__stripe--2 {
  animation-name: stripe2;
}
.pl__stripe--3 {
  animation-name: stripe3;
}
.pl__stripe-dot {
  animation-name: stripe-dot;
}
.pl__stripe-dot-group:nth-child(1) .pl__stripe-dot:nth-child(2) {
  animation-delay: calc(var(--dur) * 0.2333333333);
}
.pl__stripe-dot-group:nth-child(1) .pl__stripe-dot:nth-child(3) {
  animation-delay: calc(var(--dur) * 0.3);
}
.pl__stripe-dot-group:nth-child(1) .pl__stripe-dot:nth-child(4) {
  animation-delay: calc(var(--dur) * 0.45);
}
.pl__stripe-dot-group:nth-child(1) .pl__stripe-dot:nth-child(5) {
  animation-delay: calc(var(--dur) * 0.6833333333);
}
.pl__stripe-dot-group:nth-child(1) .pl__stripe-dot:nth-child(6) {
  animation-delay: calc(var(--dur) * 0.7083333333);
}
.pl__stripe-dot-group:nth-child(1) .pl__stripe-dot:nth-child(7) {
  animation-delay: calc(var(--dur) * 0.8416666667);
}
.pl__stripe-dot-group:nth-child(2) .pl__stripe-dot:nth-child(1) {
  animation-delay: calc(var(--dur) * 0.1083333333);
}
.pl__stripe-dot-group:nth-child(2) .pl__stripe-dot:nth-child(2) {
  animation-delay: calc(var(--dur) * 0.3333333333);
}
.pl__stripe-dot-group:nth-child(2) .pl__stripe-dot:nth-child(3) {
  animation-delay: calc(var(--dur) * 0.425);
}
.pl__stripe-dot-group:nth-child(2) .pl__stripe-dot:nth-child(4) {
  animation-delay: calc(var(--dur) * 0.6);
}
.pl__stripe-dot-group:nth-child(2) .pl__stripe-dot:nth-child(5) {
  animation-delay: calc(var(--dur) * 0.6583333333);
}
.pl__stripe-dot-group:nth-child(2) .pl__stripe-dot:nth-child(6) {
  animation-delay: calc(var(--dur) * 0.8083333333);
}
.pl__stripe-dot-group:nth-child(2) .pl__stripe-dot:nth-child(7) {
  animation-delay: calc(var(--dur) * 0.8416666667);
}
.pl__stripe-dot-group:nth-child(2) .pl__stripe-dot:nth-child(8) {
  animation-delay: calc(var(--dur) * 0.8916666667);
}
.pl__stripe-dot-group:nth-child(3) .pl__stripe-dot:nth-child(1) {
  animation-delay: calc(var(--dur) * -0.0666666667);
}
.pl__stripe-dot-group:nth-child(3) .pl__stripe-dot:nth-child(2) {
  animation-delay: calc(var(--dur) * 0.0583333333);
}
.pl__stripe-dot-group:nth-child(3) .pl__stripe-dot:nth-child(3) {
  animation-delay: calc(var(--dur) * 0.2083333333);
}
.pl__stripe-dot-group:nth-child(3) .pl__stripe-dot:nth-child(4) {
  animation-delay: calc(var(--dur) * 0.4);
}
.pl__stripe-dot-group:nth-child(3) .pl__stripe-dot:nth-child(5) {
  animation-delay: calc(var(--dur) * 0.5166666667);
}
.pl__stripe-dot-group:nth-child(3) .pl__stripe-dot:nth-child(6) {
  animation-delay: calc(var(--dur) * 0.625);
}
.pl__stripe-dot-group:nth-child(3) .pl__stripe-dot:nth-child(7) {
  animation-delay: calc(var(--dur) * 0.7666666667);
}
.pl__stripe-rotate {
  animation-name: stripe-rotate;
}

/* Animation */
@keyframes ball {
  from {
    transform: rotate(0) translate(0, -15.75px);
  }
  to {
    transform: rotate(1turn) translate(0, -15.75px);
  }
}
@keyframes ball-shadow {
  from {
    transform: rotate(0);
  }
  to {
    transform: rotate(-1turn);
  }
}
@keyframes ball-texture {
  from {
    transform: translate(-16px, 0);
  }
  to {
    transform: translate(48px, 0);
  }
}
@keyframes stripe-dot {
  from {
    r: 1.25px;
  }
  16.67%, to {
    r: 0;
  }
}
@keyframes stripe-rotate {
  from {
    transform: rotate(0);
  }
  to {
    transform: rotate(1turn);
  }
}
@keyframes stripe1 {
  from, to {
    stroke-dashoffset: -95.7745;
  }
  50% {
    animation-timing-function: cubic-bezier(0.65, 0, 0.35, 1);
    stroke-dashoffset: -75.702;
  }
}
@keyframes stripe2 {
  from, to {
    stroke-dashoffset: -80.1;
  }
  50% {
    animation-timing-function: cubic-bezier(0.65, 0, 0.35, 1);
    stroke-dashoffset: -53.4;
  }
}
@keyframes stripe3 {
  from, to {
    stroke-dashoffset: -72.765;
  }
  50% {
    animation-timing-function: cubic-bezier(0.65, 0, 0.35, 1);
    stroke-dashoffset: -48.51;
  }
}

In conclusion, creating a Soccer Preloader Animation using HTML and CSS has been an enjoyable and educational project. By combining HTML for structure and CSS for styling and animations, we’ve crafted a dynamic and engaging preloader that adds personality to the user experience. This project is perfect for showcasing creativity and enhancing web designs with playful elements.

If your project has problems, don’t worry. Just click to download the source code and face your coding challenges with excitement. Have fun coding!

Comments (0)
Login or create account to leave comments