A little self-set challenge to create a xmas advent calendar using javascript and css grid with a little animation and a hint of 3d. Works best in desktop.
Merry Christmas! I hope you enjoy!
<div class="calendar-bg"> | |
<h1 class="title">🎄 MERRY 🎅<br>CHRISTMAS</h1> | |
<div id="grid" class="grid"></div> | |
</div> |
const days = 25; | |
const daysArray = []; | |
const randomDaysArray = []; | |
const grid = document.getElementById('grid'); | |
const images = [ | |
'https://s3-us-west-2.amazonaws.com/s.cdpn.io/2175134/ball.svg', | |
'https://s3-us-west-2.amazonaws.com/s.cdpn.io/2175134/ball2.svg', | |
'https://s3-us-west-2.amazonaws.com/s.cdpn.io/2175134/hat.svg', | |
'https://s3-us-west-2.amazonaws.com/s.cdpn.io/2175134/snowman.svg', | |
'https://s3-us-west-2.amazonaws.com/s.cdpn.io/2175134/snowman2.svg', | |
'https://s3-us-west-2.amazonaws.com/s.cdpn.io/2175134/star.svg', | |
'https://s3-us-west-2.amazonaws.com/s.cdpn.io/2175134/star2.svg', | |
'https://s3-us-west-2.amazonaws.com/s.cdpn.io/2175134/stocking.svg', | |
'https://s3-us-west-2.amazonaws.com/s.cdpn.io/2175134/stocking2.svg', | |
'https://s3-us-west-2.amazonaws.com/s.cdpn.io/2175134/tree.svg', | |
'https://s3-us-west-2.amazonaws.com/s.cdpn.io/2175134/tree2.svg', | |
'https://s3-us-west-2.amazonaws.com/s.cdpn.io/2175134/snowflake.svg', | |
'https://s3-us-west-2.amazonaws.com/s.cdpn.io/2175134/holly.svg' | |
]; | |
// create an array of numbers 1-25 | |
for (let i=1; i<=days; i+=1) { | |
daysArray.push(i); | |
} | |
let randomDay = 0; | |
// get today's date in dd format | |
const today = new Date().getDate(); | |
for (let i=1; i <= days; i+=1) { | |
// picks a random day from array of days | |
randomDay = Math.floor(Math.random() * daysArray.length); | |
let randomImageNum = Math.floor(Math.random()*images.length); | |
grid.innerHTML += ` | |
<div class="day"> | |
<span class="door door-${daysArray[randomDay]}"> | |
<span class="number">${daysArray[randomDay]}</span> | |
</span> | |
<div class="bg-img" style="background-image: url(${images[randomImageNum]})"></div> | |
</div> | |
`; | |
// populate new array with randomly selected dates | |
randomDaysArray.push(daysArray[randomDay]); | |
// remove random day from array | |
daysArray.splice(randomDay, 1); | |
} | |
let doors = document.getElementsByClassName('door'); | |
for (let i=0; i<=days; i+=1) { | |
if (randomDaysArray[i] <= today) { | |
doors[i].addEventListener('click', () => { | |
doors[i].classList.add('open'); | |
}); | |
} | |
} |
* { | |
box-sizing: border-box; margin: 0; | |
font-family: montserrat, sans-serif; | |
} | |
.calendar-bg { | |
background: #042f5f; | |
background-image: linear-gradient(30deg, white 15%, #042f5f 85%); | |
background-size: 20px 100%; | |
background-position: center; | |
padding-bottom: 50px; | |
} | |
.title { | |
text-align: center; | |
color: white; | |
letter-spacing: 0.3vw; | |
font-size: 10vw; | |
line-height: 1; | |
padding-top: 30px; | |
margin: 0px auto 30px; | |
@media screen and (min-width: 440px) { | |
letter-spacing: 3px; | |
font-size: 3em; | |
} | |
@media screen and (min-width: 768px) { | |
letter-spacing: 4px; | |
font-size: 4em; | |
} | |
} | |
.grid { | |
padding: 20px; | |
max-width: 960px; | |
margin: 0px auto; | |
display: grid; | |
grid-template-columns: 1fr 1fr 1fr; | |
grid-gap: 3vw; | |
perspective: 1500px; | |
@media screen and (min-width: 440px) { | |
grid-template-columns: 1fr 1fr 1fr; | |
grid-gap: 16px; | |
} | |
@media screen and (min-width: 600px) { | |
grid-template-columns: 1fr 1fr 1fr 1fr; | |
grid-gap: 20px; | |
} | |
@media screen and (min-width: 768px) { | |
grid-template-columns: 1fr 1fr 1fr 1fr 1fr; | |
} | |
} | |
.day { | |
min-height: 123px; | |
box-sizing: border-box; | |
position: relative; | |
box-shadow: 0 0 20px rgba(80,80,120,0.5) inset, 0 0 5px 2px rgba(80,80,120,0.3) inset; | |
&:nth-last-child(1) { | |
grid-column: 2; | |
@media screen and (min-width: 600px) { | |
left: calc(50% + 10px); | |
} | |
@media screen and (min-width: 768px) { | |
grid-column: unset; | |
left: unset; | |
} | |
} | |
} | |
.door { | |
background-color: #dd0707; | |
background-image: linear-gradient(45deg, white, transparent 5%, transparent 45%, white 50%, transparent 55%, transparent 95%, white 100%); | |
background-size: 20px 20px; | |
position: absolute; | |
width: 100%; | |
height: 100%; | |
top: 0; | |
left: 0; | |
transform-origin: left center; | |
transform-style: preserve-3d; | |
transform: rotateY(0deg); | |
cursor: pointer; | |
} | |
/* back of door */ | |
.door:after { | |
content: ""; | |
position: absolute; | |
width: 100%; | |
height: 100%; | |
background: rgb(170,10,10); | |
transform: translateZ(-1px); | |
} | |
.open { | |
z-index: 100; | |
animation: open-door 1s forwards; | |
} | |
@keyframes open-door { | |
from { | |
transform: rotateY(0deg); | |
} | |
to { | |
transform: rotateY(-90deg); | |
z-index: 200; | |
} | |
} | |
.number { | |
position: absolute; | |
top: 6px; | |
right: 6px; | |
text-align: center; | |
color: #fff; | |
font-size: 5vw; | |
font-weight: 600; | |
min-width: 30px; | |
background: #dd0707; | |
padding: 5px 7px; | |
border-radius: 50% 50%; | |
@media screen and (min-width: 440px) { | |
font-size: 1.5em; | |
} | |
@media screen and (min-width: 768px) { | |
font-size: 1.8em; | |
} | |
} | |
.bg-img { | |
position: absolute; | |
width: 100%; | |
height: 100%; | |
background-color: rgba(216,226,210,1); | |
background-position: center; | |
background-repeat: no-repeat; | |
background-size: 70%; | |
z-index: -1; | |
} |