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:
- Building a Currency Converter App in React
- Creating an Amazing Frying Pan Preloader utilizing HTML and SCSS
- How to Create a Sticky Cursor Effect using HTML, CSS, & JavaScript
- Building an Amazing Birthday Card with CSS 3D Effects
- How to Build a Spin Wheel App with Chart.js and JavaScript
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!