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; | |
| } |