This is a submission for Frontend Challenge - Halloween Edition, CSS Art.
👻 The Friendly Floating Ghost.
Hello, Everyone! Here is my submission for the CSS Art: Halloween Challenge.
I wanted to create a design that was clean, simple, and captured a classic Halloween spirit. This is my "Friendly Floating Ghost," created entirely with HTML and CSS.
You can view the live demo here: https://codepen.io/abusofianid/pen/LEGgLpb
Key Features & CSS Techniques
My main goal was to bring the ghost to life using only CSS animations.
- Effective Use of CSS (Animation):
- Main Float Effect: The ghost's entire body gently floats up and down using a @keyframes animation (float) with ease-in-out timing for a smooth, spooky hover effect.
- Dynamic Wavy Bottom: The "tail" of the ghost isn't just one static shape. It's made of four separate div elements. Each one has its own wave animation, but I used animation-delay on them at different intervals. This makes them bob up and down unevenly, creating a much more fluid and realistic "waving" motion.
- Creativity & Aesthetic (The Shape):
- The ghost's shape is built using border-radius in different ways: a large value creates the perfectly round head, while a different border-radius setting on the mouth creates the simple, hollow "O" shape.
- The design is intentionally minimal and uses high contrast (a white ghost on a dark purple background) for a clean and clear aesthetic outcome. I had a lot of fun on this challenge and focused on making the CSS animations the star of the show. I hope you enjoy it! Complete Code (HTML + CSS) Here is the complete code. You can copy and paste this into a single file (e.g., ghost.html) and open it in any browser.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Floating Ghost</title>
<style>
/* Scene Setup */
body {
background-color: #0d001a; /* Very dark purple */
display: grid;
place-items: center;
min-height: 100vh;
margin: 0;
overflow: hidden;
}
/* Ghost Body */
.ghost {
position: relative;
width: 150px;
height: 200px;
background-color: #f0f0f0; /* Off-white */
/* Creates the rounded head */
border-radius: 75px 75px 0 0;
/* Adds the floating animation */
animation: float 3s ease-in-out infinite;
/* Shadow for a slight 3D effect */
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3);
}
/* Ghost Eyes */
.ghost-eyes {
position: absolute;
top: 60px;
width: 100%;
display: flex;
justify-content: space-around;
}
.eye {
width: 25px;
height: 25px;
background-color: #222;
border-radius: 50%;
}
/* Ghost Mouth */
.ghost-mouth {
position: absolute;
top: 100px;
left: 50%;
transform: translateX(-50%);
width: 40px;
height: 20px;
background-color: #222;
border-radius: 0 0 20px 20px; /* Inverted half-circle */
}
/* Wavy Ghost Bottom */
.ghost-bottom {
position: absolute;
bottom: -20px; /* Sits just below the main body */
left: 0;
width: 100%;
display: flex;
}
.ghost-bottom .wave {
width: 25%; /* 4 waves */
height: 20px;
background-color: #f0f0f0;
border-radius: 0 0 15px 15px; /* Half-circle */
/* Animates the bottom wave */
animation: wave 1s ease-in-out infinite alternate;
}
/* Stagger the animation delays so they don't move together */
.ghost-bottom .wave:nth-child(2) {
animation-delay: 0.2s;
}
.ghost-bottom .wave:nth-child(3) {
animation-delay: 0.4s;
}
.ghost-bottom .wave:nth-child(4) {
animation-delay: 0.6s;
}
/* -- Keyframe Animations -- */
/* Floating animation (up and down) */
@keyframes float {
0%, 100% {
transform: translateY(0);
}
50% {
transform: translateY(-20px); /* Moves up 20px */
}
}
/* Waving animation for the bottom pieces */
@keyframes wave {
0% {
transform: translateY(0);
}
100% {
transform: translateY(-8px); /* Moves up and down slightly */
}
}
</style>
</head>
<body>
<div class="ghost">
<div class="ghost-eyes">
<div class="eye"></div>
<div class="eye"></div>
</div>
<div class="ghost-mouth"></div>
<div class="ghost-bottom">
<div class="wave"></div>
<div class="wave"></div>
<div class="wave"></div>
<div class="wave"></div>
</div>
</div>
</body>
</html>
Top comments (0)