Introduction: Loading animations play a crucial role in enhancing user experience on websites. They not only entertain users during wait times but also give a sense of progress. One such creative loading animation is the pencil preloader, which mimics the movement of a pencil writing or drawing. In this tutorial, we’ll delve into how to create a captivating pencil preloader animation using SVG (Scalable Vector Graphics) and CSS (Cascading Style Sheets).
Latest Posts:
- [2025] Free OpenAI AI Courses to Learn ChatGPT, Prompt Engineering & Sora
- Master Generative AI in 2025: 6 Free YouTube Courses That Will Make You an AI Pro
- How to Master Full Stack Web Development in 2025: Top 5 Free Courses on YouTube
- Build an Amazing Comic-Style Image Converter with JavaScript
- How to Build a Modern Password Input Field with Toggle Visibility
Explanation:
HTML Structure: The HTML structure is minimal and consists of a single SVG element that contains various elements representing different parts of the pencil, such as the body, eraser, and point.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Pencil preloader</title>
</head>
<body>
<svg
class="pencil"
viewBox="0 0 200 200"
width="200px"
height="200px"
xmlns="http://www.w3.org/2000/svg"
>
<defs>
<clipPath id="pencil-eraser">
<rect rx="5" ry="5" width="30" height="30"></rect>
</clipPath>
</defs>
<circle
class="pencil__stroke"
r="70"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-dasharray="439.82 439.82"
stroke-dashoffset="439.82"
stroke-linecap="round"
transform="rotate(-113,100,100)"
/>
<g class="pencil__rotate" transform="translate(100,100)">
<g fill="none">
<circle
class="pencil__body1"
r="64"
stroke="hsl(223,90%,50%)"
stroke-width="30"
stroke-dasharray="402.12 402.12"
stroke-dashoffset="402"
transform="rotate(-90)"
/>
<circle
class="pencil__body2"
r="74"
stroke="hsl(223,90%,60%)"
stroke-width="10"
stroke-dasharray="464.96 464.96"
stroke-dashoffset="465"
transform="rotate(-90)"
/>
<circle
class="pencil__body3"
r="54"
stroke="hsl(223,90%,40%)"
stroke-width="10"
stroke-dasharray="339.29 339.29"
stroke-dashoffset="339"
transform="rotate(-90)"
/>
</g>
<g class="pencil__eraser" transform="rotate(-90) translate(49,0)">
<g class="pencil__eraser-skew">
<rect
fill="hsl(223,90%,70%)"
rx="5"
ry="5"
width="30"
height="30"
/>
<rect
fill="hsl(223,90%,60%)"
width="5"
height="30"
clip-path="url(#pencil-eraser)"
/>
<rect fill="hsl(223,10%,90%)" width="30" height="20" />
<rect fill="hsl(223,10%,70%)" width="15" height="20" />
<rect fill="hsl(223,10%,80%)" width="5" height="20" />
<rect fill="hsla(223,10%,10%,0.2)" y="6" width="30" height="2" />
<rect fill="hsla(223,10%,10%,0.2)" y="13" width="30" height="2" />
</g>
</g>
<g class="pencil__point" transform="rotate(-90) translate(49,-30)">
<polygon fill="hsl(33,90%,70%)" points="15 0,30 30,0 30" />
<polygon fill="hsl(33,90%,50%)" points="15 0,6 30,0 30" />
<polygon fill="hsl(223,10%,10%)" points="15 0,20 10,10 10" />
</g>
</g>
</svg>
</body>
</html>
HTMLSVG Elements:
- Pencil Body:
- The pencil body is represented by three concentric circles of varying sizes and stroke widths. Each circle is styled with different stroke colors to create a realistic pencil appearance.
- Pencil Eraser:
- The eraser is created using a rectangle element with rounded corners (defined by
rx
andry
attributes). - To create a 3D effect, the eraser is skewed using CSS transformations.
- The eraser is created using a rectangle element with rounded corners (defined by
- Pencil Point:
- The pencil point is represented by a triangular polygon shape, mimicking the tip of a pencil.
CSS Styling and Animations:
* {
border: 0;
box-sizing: border-box;
margin: 0;
padding: 0;
}
:root {
--hue: 223;
--bg: hsl(var(--hue), 90%, 90%);
--fg: hsl(var(--hue), 90%, 10%);
--trans-dur: 0.3s;
font-size: calc(20px + (30 - 20) * (100vw - 320px) / (1280 - 320));
}
body {
background-color: #1e1c27;
color: white;
font: 1em/1.5 sans-serif;
height: 100vh;
display: grid;
place-items: center;
}
.pencil {
display: block;
width: 10em;
height: 10em;
}
.pencil__body1,
.pencil__body2,
.pencil__body3,
.pencil__eraser,
.pencil__eraser-skew,
.pencil__point,
.pencil__rotate,
.pencil__stroke {
animation-duration: 3s;
animation-timing-function: linear;
animation-iteration-count: infinite;
}
.pencil__body1,
.pencil__body2,
.pencil__body3 {
transform: rotate(-90deg);
}
.pencil__body1 {
animation-name: pencilBody1;
}
.pencil__body2 {
animation-name: pencilBody2;
}
.pencil__body3 {
animation-name: pencilBody3;
}
.pencil__eraser {
animation-name: pencilEraser;
transform: rotate(-90deg) translate(49px, 0);
}
.pencil__eraser-skew {
animation-name: pencilEraserSkew;
animation-timing-function: ease-in-out;
}
.pencil__point {
animation-name: pencilPoint;
transform: rotate(-90deg) translate(49px, -30px);
}
.pencil__rotate {
animation-name: pencilRotate;
}
.pencil__stroke {
animation-name: pencilStroke;
transform: translate(100px, 100px) rotate(-113deg);
}
/* Animations */
@keyframes pencilBody1 {
from,
to {
stroke-dashoffset: 351.86;
transform: rotate(-90deg);
}
50% {
stroke-dashoffset: 150.8; /* 3/8 of diameter */
transform: rotate(-225deg);
}
}
@keyframes pencilBody2 {
from,
to {
stroke-dashoffset: 406.84;
transform: rotate(-90deg);
}
50% {
stroke-dashoffset: 174.36;
transform: rotate(-225deg);
}
}
@keyframes pencilBody3 {
from,
to {
stroke-dashoffset: 296.88;
transform: rotate(-90deg);
}
50% {
stroke-dashoffset: 127.23;
transform: rotate(-225deg);
}
}
@keyframes pencilEraser {
from,
to {
transform: rotate(-45deg) translate(49px, 0);
}
50% {
transform: rotate(0deg) translate(49px, 0);
}
}
@keyframes pencilEraserSkew {
from,
32.5%,
67.5%,
to {
transform: skewX(0);
}
35%,
65% {
transform: skewX(-4deg);
}
37.5%,
62.5% {
transform: skewX(8deg);
}
40%,
45%,
50%,
55%,
60% {
transform: skewX(-15deg);
}
42.5%,
47.5%,
52.5%,
57.5% {
transform: skewX(15deg);
}
}
@keyframes pencilPoint {
from,
to {
transform: rotate(-90deg) translate(49px, -30px);
}
50% {
transform: rotate(-225deg) translate(49px, -30px);
}
}
@keyframes pencilRotate {
from {
transform: translate(100px, 100px) rotate(0);
}
to {
transform: translate(100px, 100px) rotate(720deg);
}
}
@keyframes pencilStroke {
from {
stroke-dashoffset: 439.82;
transform: translate(100px, 100px) rotate(-113deg);
}
50% {
stroke-dashoffset: 164.93;
transform: translate(100px, 100px) rotate(-113deg);
}
75%,
to {
stroke-dashoffset: 439.82;
transform: translate(100px, 100px) rotate(112deg);
}
}
CSS- Global Styles:
- The global styles reset default browser styles and ensure consistent rendering across different platforms.
- Custom Properties:
- Custom properties (CSS variables) are used to define the hue, background color, and foreground color, allowing for easy customization.
- Keyframe Animations:
- Various keyframe animations are defined to animate different parts of the pencil.
- Animations are applied to elements using the
animation-name
,animation-duration
,animation-timing-function
, andanimation-iteration-count
properties.
Conclusion: In conclusion, the pencil preloader animation created using SVG and CSS adds a delightful touch to web pages while providing visual feedback during loading periods. By leveraging SVG’s scalability and CSS’s powerful animation capabilities, developers can craft engaging and interactive loading animations that enhance the overall user experience. Feel free to customize the provided code to match your website’s design and branding. With a bit of creativity and CSS animation expertise, you can create stunning loading animations that leave a lasting impression on your audience.
This tutorial provides a step-by-step guide to creating a pencil preloader animation, along with detailed explanations of the HTML structure, SVG elements, CSS styling, and animations involved. By following this tutorial, developers can implement similar loading animations in their web projects, making them more engaging and user-friendly.
Happy Coding!