This is a submission for Frontend Challenge - December Edition, Glam Up My Markup: Winter Solstice
Note: During the development of this project, I noticed that the theme of the winter solstice has also inspired other participants in the challenge. This highlights how inspiring nature and the magic of this season can be. My inspiration comes from my personal vision of winter, focusing on the details and interpretation of its charm. I hope this project contributes to the diversity of ideas in this challenge.
What I Built
"Winter Solstice Magic" is an interactive web scene designed to capture the essence and enchantment of the winter solstice. The project features animated elements like a sun, moon, stars, aurora borealis, falling snow, and additional festive touches such as a glowing fire, twinkling lights, and shooting comets. The goal was to create a visually engaging experience that immerses the viewer in the magic of winter while showcasing the power of modern web technologies.
Demo
You can experience the project live here: Winter Solstice Magic Demo
The full code is available The is here:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Winter Solstice Scene</title>
<style>
body {
margin: 0;
overflow: hidden;
background: linear-gradient(to bottom, #003366, #000);
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
color: white;
font-family: Arial, sans-serif;
}
.sky {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: linear-gradient(to top, #1e3c72, #2a5298);
z-index: -1;
animation: skyTransition 20s infinite alternate;
}
.sun {
position: absolute;
width: 80px;
height: 80px;
background: radial-gradient(circle, #ffcc00, #ff9900);
border-radius: 50%;
animation: moveSun 8s infinite;
z-index: 1;
}
.moon {
position: absolute;
width: 60px;
height: 60px;
background: radial-gradient(circle, #ffffff, #cccccc);
border-radius: 50%;
animation: moveMoon 8s infinite;
z-index: 1;
opacity: 0.8;
}
.stars {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
pointer-events: none;
z-index: 0;
}
.star {
position: absolute;
width: 3px;
height: 3px;
background: white;
border-radius: 50%;
opacity: 0;
animation: twinkle 3s infinite;
}
.aurora {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: radial-gradient(circle, rgba(0, 255, 150, 0.3), transparent);
opacity: 0.4;
animation: auroraEffect 10s infinite alternate;
z-index: -1;
}
.comet {
position: absolute;
width: 10px;
height: 10px;
background: radial-gradient(circle, #ffffff, transparent);
border-radius: 50%;
box-shadow: 0 0 10px 5px #ffffff;
opacity: 0.8;
animation: flyComet 6s infinite;
}
.light-string {
position: absolute;
bottom: 10%;
width: 100%;
display: flex;
justify-content: space-evenly;
}
.light {
width: 15px;
height: 15px;
background: red;
border-radius: 50%;
animation: blinkLight 2s infinite alternate;
}
.title {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
font-size: 3.5rem;
font-family: 'Cinzel Decorative', cursive;
color: #ffddcc;
text-shadow: 3px 3px 10px #000;
opacity: 0;
animation: fadeInOut 10s infinite;
}
.fire {
position: absolute;
bottom: 5%;
left: 50%;
transform: translateX(-50%);
width: 50px;
height: 100px;
background: radial-gradient(circle, rgba(255, 165, 0, 1), rgba(255, 69, 0, 0.7));
border-radius: 50%;
animation: flicker 0.5s infinite;
}
@keyframes flicker {
0%, 100% {
transform: scale(1);
opacity: 0.8;
}
50% {
transform: scale(1.2);
opacity: 1;
}
}
.tree {
position: absolute;
bottom: 10%;
left: calc(10% + var(--position, 0%));
width: 40px;
height: 60px;
background: linear-gradient(to bottom, #228B22, #006400);
clip-path: polygon(50% 0%, 0% 100%, 100% 100%);
}
@keyframes fadeInOut {
0%, 100% {
opacity: 0;
}
50% {
opacity: 1;
}
}
@keyframes moveSun {
0% {
top: 80%;
left: 10%;
}
50% {
top: 20%;
left: 50%;
}
100% {
top: 80%;
left: 90%;
}
}
@keyframes moveMoon {
0% {
top: 20%;
left: 90%;
}
50% {
top: 10%;
left: 50%;
}
100% {
top: 20%;
left: 10%;
}
}
@keyframes skyTransition {
0% {
background: linear-gradient(to top, #1e3c72, #2a5298);
}
50% {
background: linear-gradient(to top, #000428, #004e92);
}
100% {
background: linear-gradient(to top, #2c3e50, #4ca1af);
}
}
@keyframes twinkle {
0%, 100% {
opacity: 0;
}
50% {
opacity: 1;
}
}
@keyframes auroraEffect {
0% {
transform: translateX(-20px) scale(1.2);
}
100% {
transform: translateX(20px) scale(1.5);
}
}
@keyframes flyComet {
0% {
top: -10%;
left: 110%;
}
100% {
top: 110%;
left: -10%;
}
}
@keyframes blinkLight {
0% {
background: red;
}
100% {
background: yellow;
}
}
</style>
<link href="https://fonts.googleapis.com/css2?family=Cinzel+Decorative:wght@400;700&display=swap" rel="stylesheet">
</head>
<body>
<div class="sky"></div>
<div class="aurora"></div>
<div class="sun"></div>
<div class="moon"></div>
<div class="stars"></div>
<div class="light-string">
<div class="light"></div>
<div class="light"></div>
<div class="light"></div>
<div class="light"></div>
<div class="light"></div>
</div>
<div class="title">Winter Solstice Magic</div>
<div class="fire"></div>
<div class="tree" style="--position: 10%;"></div>
<div class="tree" style="--position: 30%;"></div>
<div class="tree" style="--position: 70%;"></div>
<script>
// Add twinkling stars
const starContainer = document.querySelector('.stars');
for (let i = 0; i < 100; i++) {
const star = document.createElement('div');
star.classList.add('star');
star.style.top = `${Math.random() * 100}%`;
star.style.left = `${Math.random() * 100}%`;
star.style.animationDelay = `${Math.random() * 5}s`;
starContainer.appendChild(star);
}
// Create a comet
const createComet = () => {
const comet = document.createElement('div');
comet.classList.add('comet');
comet.style.top = `-${Math.random() * 50}px`;
comet.style.left = `${Math.random() * window.innerWidth}px`;
document.body.appendChild(comet);
setTimeout(() => comet.remove(), 6000);
};
setInterval(createComet, 8000);
// Interactive snow effect
const createSnowflake = () => {
const snowflake = document.createElement('div');
snowflake.classList.add('snowflake');
snowflake.style.position = 'absolute';
snowflake.style.top = `-5px`;
snowflake.style.left = `${Math.random() * window.innerWidth}px`;
snowflake.style.width = snowflake.style.height = `${Math.random() * 5 + 2}px`;
snowflake.style.background = 'white';
snowflake.style.borderRadius = '50%';
snowflake.style.opacity = `${Math.random() * 0.8 + 0.2}`;
snowflake.style.transition = 'top 3s linear';
document.body.appendChild(snowflake);
setTimeout(() => {
snowflake.style.top = `${window.innerHeight + 10}px`;
}, 50);
setTimeout(() => {
snowflake.remove();
}, 3000);
};
setInterval(createSnowflake, 150);
</script>
</body>
</html>
Below is a preview image of the project:
Journey
Creating "Winter Solstice Magic" was an exciting and challenging process. Here is an overview of my journey:
The Idea
I wanted to bring the beauty and mystique of the winter solstice to life through an immersive web experience. The project was inspired by the natural elements of winter and the peaceful yet vibrant atmosphere of the season.
Technologies Used
- HTML for the basic structure.
- CSS for animations, gradients, and styling.
- JavaScript for dynamic interactivity, including the generation of snowflakes, stars, and comets.
- Google Fonts to enhance the aesthetic appeal of the title text with the "Cinzel Decorative" font.
Key Features
Dynamic Background: The sky transitions smoothly between gradients to mimic different times of the day.
Interactive Elements: Stars twinkle, snowflakes fall, and comets streak across the screen to add life to the scene.
Festive Details: Twinkling lights and a glowing fire enhance the seasonal charm.
Accessibility: The project was designed to be visually engaging and lightweight, ensuring it works seamlessly across devices.
Challenges and Learnings
One challenge was optimizing animations to ensure smooth performance on various devices. I learned a lot about managing animation performance using CSS and JavaScript. I am particularly proud of the seamless integration of multiple animated elements without compromising the responsiveness of the page.
What’s Next
In the future, I would like to:
Add audio elements, such as subtle winter-themed background music or sound effects.
Introduce user interactivity, allowing viewers to customize aspects of the scene.
Expand the project into a series featuring different seasonal themes.
License
The code for this project is licensed under the MIT License, making it free and open for anyone to use or adapt.
Acknowledgments
Special thanks to the DEV Community for hosting this challenge and providing inspiration through their platform. Thank you for considering my submission! I hope you enjoy "Winter Solstice Magic."
Top comments (0)