How to Create Table Tennis Loader using CSS

ping pong loader

In this tutorial, we’ll create an animated table tennis SVG using HTML, CSS (SCSS), and SVG. This SVG will showcase a bouncing ball and a moving paddle, simulating a table tennis game.


SVG Structure

The SVG structure consists of a ball and a paddle within two groups. A linear gradient and a mask are also defined to provide a visual effect to the ball and paddle.

<svg class="table-tennis" viewBox="0 0 128 128" width="128px" height="128px">
	<defs>
		<linearGradient id="table-tennis-grad" x1="0" y1="0" x2="1" y2="1">
			<stop offset="0%" stop-color="#000" />
			<stop offset="100%" stop-color="#fff" />
		</linearGradient>
		<mask id="table-tennis-mask">
			<rect x="0" y="0" width="128" height="128" fill="url(#table-tennis-grad)" />
		</mask>
	</defs>
	<g fill="var(--primary)">
		<g class="table-tennis__ball-x">
			<circle class="table-tennis__ball-y" r="10" />
		</g>
		<g class="table-tennis__paddle-x">
			<rect class="table-tennis__paddle-y" x="-30" y="-2" rx="1" ry="1" width="60" height="4" />
		</g>
	</g>
	<g fill="hsl(163,90%,40%)" mask="url(#table-tennis-mask)">
		<g class="table-tennis__ball-x">
			<circle class="table-tennis__ball-y" r="10" />
		</g>
		<g class="table-tennis__paddle-x">
			<rect class="table-tennis__paddle-y" x="-30" y="-2" rx="1" ry="1" width="60" height="4" />
		</g>
	</g>
</svg>
HTML

SCSS Styling

The SCSS styling defines the layout, colors, and animations for the table tennis SVG.

* {
	border: 0;
	box-sizing: border-box;
	margin: 0;
	padding: 0;
}
:root {
	--hue: 223;
	--bg-color: hsl(var(--hue),90%,90%);
	--fg-color: hsl(var(--hue),90%,10%);
	--primary-color: hsl(var(--hue),90%,50%);
	--transition-duration: 0.3s;
	font-size: calc(16px + (32 - 16) * (100vw - 320px) / (2560 - 320));
}
body {
	background-color: var(--bg-color);
	color: var(--fg-color);
	display: flex;
	font: 1em/1.5 sans-serif;
	height: 100vh;
	transition:
		background-color var(--transition-duration),
		color var(--transition-duration);
}

$isDebug: false;
$timingLinear: linear;
$timingEaseIn: cubic-bezier(0.32,0,0.67,0);
$timingEaseOut: cubic-bezier(0.33,1,0.68,1);

.table-tennis {
	@if $isDebug == true {
		outline: 1px solid;
		overflow: visible;
	}
	display: block;
	margin: auto;
	width: 8em;
	height: 8em;

	&__ball,
	&__paddle {
		&-x,
		&-y {
			animation: table-tennis-ball-x 1.5s $timingLinear infinite;
		}
	}
	&__ball {
		&-y {
			animation-name: table-tennis-ball-y;
		}
	}
	&__paddle {
		&-x {
			animation-name: table-tennis-paddle-x;
			animation-timing-function: $timingEaseOut;
		}
		&-y {
			animation-name: table-tennis-paddle-y;
		}
	}
}

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

/* Animation */
@keyframes table-tennis-ball-x {
	from,
	to {
		transform: translate(40px,80px);
	}
	50% {
		transform: translate(88px,80px);
	}
}
@keyframes table-tennis-ball-y {
	from,
	50%,
	to {
		animation-timing-function: $timingEaseOut;
		transform: translate(0,0);
	}
	25%,
	75% {
		animation-timing-function: $timingEaseIn;
		transform: translate(0,-68px);
	}
}
@keyframes table-tennis-paddle-x {
	from,
	to {
		transform: translate(36px,92px) rotate(6deg);
	}
	50% {
		transform: translate(92px,92px) rotate(-6deg);
	}
}
@keyframes table-tennis-paddle-y {
	from,
	50%,
	to {
		animation-timing-function: $timingEaseOut;
		transform: translate(0,0);
	}
	25%,
	75% {
		animation-timing-function: $timingEaseIn;
		transform: translate(0,28px);
	}
}
SCSS

Conclusion

This tutorial provided a foundation for creating an animated table tennis SVG using HTML, SCSS, and SVG. By utilizing CSS animations and SVG elements, we were able to simulate a table tennis game with a bouncing ball and moving paddle.

Feel free to customize the styling, adjust the animations, or add more features to further enhance this SVG component based on your project requirements.

Happy coding!

Comments

No comments yet. Why don’t you start the discussion?

Leave a Reply

Your email address will not be published. Required fields are marked *