This is a submission for Frontend Challenge - Halloween Edition, CSS Art._
Hey everyone! As the clock winds down on the Dev.to Frontend Challenge - Halloween Edition, I wanted to share my journey in creating a spooky, yet charming, Halloween scene purely with HTML and CSS. It's been a wild ride, a mix of pure frustration, "aha!" moments, and a lot of box-shadow tweaking.
Inspiration
I was inspired to create a "paper cutout" style halloween scene with layered elements, subtle shadows, and the vibrant yet muted color palette. I loved creating the central castle, the glowing pumpkin, the mischievous cat, and especially the creepy reaper on the right. My goal was clear: create this entire scene, capturing that papercraft feel, using only HTML and CSS. No img tags, no external assets – just pure code.
Demo
The image is made to be viewed in full screen on a Desktop, so please check it on a desktop.
CodePen:
Demo Image Fullscreen
Journey
This is my first submission for any Dev Challenge. I am a newbie at CSS art so the first step was to go through different CSS arts on Codepen and Google search and take some elements from them.
Here's a little peek into my journey, the (many) challenges I faced, and how I brought this haunted castle to life.
The Foundation: Setting the (Spooky) Scene
Every good scene needs a backdrop. I started simple:
The Sky: A linear-gradient from a dark navy to a deep purple.
The Ground: A simple, dark shape at the bottom.
The Moon: A radial-gradient for the color, border-radius: 50% for the shape, and a box-shadow for that eerie glow. The "glow" itself is animated to pulse gently.
The first real beast was the castle. This wasn't one div. This was a monster of position: absolute, z-index, and pseudo-elements.
The Structure: I built it piece by piece. A main body (.castle-main)
and three towers (.castle-tower)
.
The Challenge: The z-index! For a while, my center tower was behind the main building, and the bridge was floating in the sky. It took a lot of tweaking to get the layers right so everything sat perfectly on the ground line.
The Details: The battlements (the tooth-like things on top) aren't individual divs. That would be a nightmare. Instead, I used a repeating-linear-gradient on a pseudo-element (::before) to create the pattern. The windows use a flickering animation on their opacity and box-shadow to look like candlelight.
The Main Characters: From Pumpkins to Reapers
With the set built, I needed to populate it.
First up: the Jack-o'-Lantern. This was fun! The body is a radial-gradient and a funky border-radius to make it squat. The face elements are simple clip-path triangles, but the mouth was a cool trick. To get the "stitched" look with teeth, I used a repeating-linear-gradient on the ::after pseudo-element of the mouth div.
Next, the Grim Reaper. This is one of my favorite parts.
-
The Robe: I dreaded trying to make this shape. The solution?
clip-path: polygon(...)
. I just clicked out the points to create that flowy, tattered robe shape. -
The Eyes: The glowing red eyes are just two pseudo-elements (::before and ::after) on an empty
.reaper-eyes
div, with a box-shadow animation to make them pulse. - The "Float": The entire .grim-reaper container has a simple animation that shifts its transform: translateY up and down, giving it that classic, spooky float.
The "Magic": Bringing It All to Life with Animation
A static scene is boring. I wanted movement everywhere. This was the biggest challenge: orchestrating chaos.
-
The Bats: This was a double-animation challenge. Each bat has a fly animation that moves it from left: -50px to left: 110% across the screen. But! The wings (
.bat-wing-left
,.bat-wing-right
) have their own flap animation. I used animation-delay on the main .bat divs to make them fly out at different times. - The Ghost: Similar to the reaper, he has a float animation. But the whole .ghost-group also has a slide animation that moves it across the screen, pauses, and then moves back.
- The Spiders: These were tricky. Each leg is its own div with a pseudo-element for the second joint, all absolutely positioned. The whole .spider-group has a simple translateY animation to make it dangle.
- The Books & Candles: These were perfect "props" to fill the foreground. The candle flames use a flicker and flame animation to feel alive.
- The Cobwebs: Don't be fooled! These are just 4 rotated divs for the main lines and 5 concentric divs with a transparent background and a light border for the spirals. Simple, but super effective.
What I Learned
This project was a beast, but I'm so proud of the result. My biggest takeaways:
Pseudo-elements are your best friend. I built moon craters, pumpkin segments, reaper eyes, stems, and battlements all without adding a single extra div to the HTML. My HTML is super clean; my CSS file... less so. 😂
z-index is a dark art. When you have 20+ absolutely positioned elements, you will spend an hour trying to figure out why your cat is standing in front of a castle tower but behind a pumpkin.
animation-delay is key. Don't have everything happen at once. Staggering the bats, the window flickers, and the ghost's appearance makes the world feel more natural and less like a repetitive loop.
It was a ton of work, but seeing all the little pieces come together and move was one of the most satisfying coding moments I've had in a while.
Thanks for reading! What's your favorite part of the scene?
Top comments (0)