<main class="room">
<div class="floating-container">
<section class="obj obj_name_rail">
<div class="spr spr_name_rail"></div>
</section>
<section class="obj obj_name_loco">
<div class="spr spr_name_loco"></div>
</section>
<button class="obj obj_name_wagon obj_type_btn" type="button">
<div class="spr spr_name_wagon"></div>
</button>
<section class="obj obj_name_tunnel">
<div class="spr spr_name_tunnel"></div>
</section>
<button class="obj obj_name_arrow obj_type_btn" type="button">
<div class="spr spr_name_arrow"></div>
</button>
<section class="obj obj_name_tree">
<div class="spr spr_name_tree"></div>
</section>
<button class="obj obj_name_gifts obj_type_btn" type="button">
<div class="spr spr_name_gifts"></div>
</button>
<button class="obj obj_name_snowman obj_type_btn" type="button">
<div class="spr spr_name_snowman"></div>
</button>
<section class="obj obj_name_snowman-dec">
<div class="spr spr_name_snowman-dec"></div>
</section>
</div>
<section class="overlay overlay_name_start">
<div class="modal">
<div class="modal__person">
<div class="santa"></div>
<h3>Santa</h3>
</div>
<p>
Ho-ho-ho, Hello!
<br />I hid the presents.
<br />Can you find them?
</p>
<button class="modal__btn js_scr_start" type="button">Start</button>
</div>
</section>
<section class="overlay overlay_name_end overlay_state_disabled">
<div class="modal">
<div class="modal__person">
<div class="santa"></div>
<h3>Santa</h3>
</div>
<p>
Congratulations! 🥳
<br />You found them!
<br />You can open your gifts
<br /><span class="timer"></span>.
</p>
</div>
</section>
<!-- snowflakes by @codeconvey | begin -->
<section class="snowflakes" aria-hidden="true">
<div class="snowflake">❅</div>
<div class="snowflake">❅</div>
<div class="snowflake">❆</div>
<div class="snowflake">❄</div>
<div class="snowflake">❅</div>
<div class="snowflake">❆</div>
<div class="snowflake">❄</div>
<div class="snowflake">❅</div>
<div class="snowflake">❆</div>
<div class="snowflake">❄</div>
</section>
<!-- snowflakes by @codeconvey | end -->
<section class="toggle-song">
<button type="button" class="toggle-song__btn gg-play-button-o"></button>
<span class="toggle-song__text">Music</span>
</section>
</main>
<audio id="song">
<source src="https://opengameart.org/sites/default/files/Christmas%20synths.ogg" type="audio/ogg">
Your browser does not support the audio element.
</audio>
@import url("https://fonts.googleapis.com/css2?family=Ranchers&display=swap");
@import url("https://fonts.googleapis.com/css2?family=Nerko+One&display=swap");
// ---------------------------------------
// | resets
// ---------------------------------------
html {
box-sizing: border-box;
}
*,
*:before,
*:after {
box-sizing: inherit;
}
body {
margin: 0;
padding: 0;
overflow: hidden;
cursor: url(https://raw.githubusercontent.com/elsemeow/cdn/main/img/cdpn/gOwYMNR/cursor-default.png),
default;
}
// ---------------------------------------
// | room
// ---------------------------------------
.room {
width: 100vw;
height: 100vh;
overflow: hidden;
display: flex;
align-items: center;
justify-content: center;
background-image: linear-gradient(147deg, #ff6666 0%, #db3445 74%);
}
// ---------------------------------------
// | floating
// ---------------------------------------
.floating-container {
z-index: 1;
position: absolute;
display: flex;
align-items: center;
justify-content: center;
animation: aFloating 2s ease-in-out alternate infinite;
}
// ---------------------------------------
// | pop-up
// ---------------------------------------
.overlay {
z-index: 100;
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
background-color: rgba(255, 255, 255, 0.35);
transition: 1s ease-in-out;
transition-property: opacity, z-index;
animation: aModal 1s ease-in-out;
&_state {
&_disabled {
z-index: -1;
opacity: 0;
animation: none;
}
}
}
.modal {
width: 100%;
max-width: 280px;
position: absolute;
top: 50%;
left: 50%;
margin-right: -50%;
transform: translate(-50%, -50%);
text-align: center;
background-color: #f5f5f5;
padding: 20px;
border-radius: 5px;
border-bottom: 5px solid rgba(0, 0, 0, 0.15);
box-shadow: rgba(0, 0, 0, 0.15) 0 4px 4px, rgba(0, 0, 0, 0.15) 0 8px 8px,
rgba(0, 0, 0, 0.15) 0 16px 16px, rgba(0, 0, 0, 0.15) 0 32px 32px;
& p {
font-family: "Nerko One", cursive;
margin: 0;
margin-top: 20px;
font-size: 20px;
line-height: 120%;
color: #333;
& .timer {
display: inline-block;
color: #e0455f;
font-size: 24px;
margin-top: 8px;
}
}
&__person {
display: flex;
align-items: center;
& .santa {
background-repeat: no-repeat;
background-position: center;
background-size: contain;
background-image: url(https://raw.githubusercontent.com/elsemeow/cdn/main/img/cdpn/mdrrZPe/santa.png);
width: 70px;
height: 70px;
border: 3px solid rgba(0, 0, 0, 0.15);
background-color: rgba(0, 0, 0, 0.05);
margin-right: 20px;
}
& h3 {
margin: 0;
font-family: "Ranchers", cursive;
font-size: 30px;
color: #009b77;
text-shadow: 2px 2px 0 #232323;
}
}
&__btn {
font-family: "Ranchers", cursive;
display: inline-block;
margin: 0;
margin-top: 20px;
padding: 8px 32px;
font-size: 20px;
color: #fff;
background-color: #e0455f;
border: 2px solid rgba(0, 0, 0, 0.3);
border-radius: 10px;
box-shadow: 4px 4px 0 #333;
transition: 0.1s ease-in-out;
transition-property: box-shadow, transform;
cursor: url(https://raw.githubusercontent.com/elsemeow/cdn/main/img/cdpn/gOwYMNR/cursor-pointer.png),
pointer;
&:focus {
outline: none;
}
&:hover,
&:focus {
transform: translate(4px, 4px);
box-shadow: 0 0 0 transparent;
}
}
}
// ---------------------------------------
// | sprites
// ---------------------------------------
.spr {
background-repeat: no-repeat;
background-position: center;
background-size: contain;
&_name {
&_rail {
width: 90vmin;
height: 90vmin;
background-image: url(https://raw.githubusercontent.com/elsemeow/cdn/main/img/cdpn/mdrrZPe/railway.svg);
filter: drop-shadow(0 18vmin 3vmin rgba(0, 0, 0, 0.35));
}
&_loco {
width: 4vmin;
height: 4vmin;
background-image: url(https://raw.githubusercontent.com/elsemeow/cdn/main/img/cdpn/mdrrZPe/locomotive.svg);
}
&_wagon {
width: 4vmin;
height: 4vmin;
background-image: url(https://raw.githubusercontent.com/elsemeow/cdn/main/img/cdpn/mdrrZPe/wagon-gift.svg);
}
&_tunnel {
width: 25vmin;
height: 25vmin;
background-image: url(https://raw.githubusercontent.com/elsemeow/cdn/main/img/cdpn/mdrrZPe/tunnel-bottom.svg);
filter: drop-shadow(10vmin 0 3vmin rgba(0, 0, 0, 0.35));
}
&_arrow {
width: 6vmin;
height: 6vmin;
background-image: url(https://raw.githubusercontent.com/elsemeow/cdn/main/img/cdpn/mdrrZPe/arrow.svg);
transform: rotateY(180deg);
transition: 0.35s ease-in-out;
transition-property: transform;
}
&_tree {
width: 16vmin;
height: 16vmin;
background-image: url(https://raw.githubusercontent.com/elsemeow/cdn/main/img/cdpn/mdrrZPe/decorated-tree.svg);
animation: aTree 3s ease-in-out alternate infinite;
filter: drop-shadow(0vmin 1vmin 1vmin rgba(0, 0, 0, 0.6));
}
&_gifts {
width: 6vmin;
height: 6vmin;
background-image: url(https://raw.githubusercontent.com/elsemeow/cdn/main/img/cdpn/mdrrZPe/gifts.svg);
display: none;
}
&_snowman {
width: 7vmin;
height: 7vmin;
background-image: url(https://raw.githubusercontent.com/elsemeow/cdn/main/img/cdpn/mdrrZPe/snowman.svg);
}
&_snowman-dec {
width: 7vmin;
height: 7vmin;
background-image: url(https://raw.githubusercontent.com/elsemeow/cdn/main/img/cdpn/mdrrZPe/snowman-active.png);
animation: aSnowmanAppear 0.35s ease-in-out;
}
}
}
// ---------------------------------------
// | objects and layers
// ---------------------------------------
.obj {
position: absolute;
&_type {
&_btn {
border: none;
border-radius: 0;
padding: 0;
margin: 0;
background-color: transparent;
transition: 0.15s ease-in-out;
transition-property: filter;
filter: drop-shadow(0 0 0.3vmin #ff0);
cursor: url(https://raw.githubusercontent.com/elsemeow/cdn/main/img/cdpn/gOwYMNR/cursor-pointer.png),
pointer;
&:focus {
outline: none;
}
&:hover,
&:focus {
filter: drop-shadow(0 0 0.4vmin #0f0);
}
}
}
&_name {
&_rail {
z-index: 1;
}
&_loco {
z-index: 2;
display: none;
}
&_wagon {
z-index: 3;
display: none;
}
&_tunnel {
z-index: 4;
transform: translate(-31.5vmin, 11.5vmin);
}
&_arrow {
z-index: 5;
transform: translate(-5vmin, 5vmin);
}
&_tree {
z-index: 5;
transform: translate(28vmin, -17vmin);
}
&_gifts {
z-index: 6;
transform: translate(25vmin, -9vmin);
&.obj_type_btn {
cursor: url(https://raw.githubusercontent.com/elsemeow/cdn/main/img/cdpn/gOwYMNR/cursor-default.png),
default;
}
}
&_snowman {
z-index: 6;
transform: translate(-31vmin, 4vmin);
transition: 0.35s ease-in-out;
transition-property: filter, opacity;
}
&_snowman-dec {
display: none;
z-index: 7;
transform: translate(-31vmin, 3.5vmin);
}
}
&_state {
&_run {
&.obj_name_loco {
display: block;
animation: aLoco 10s ease-in-out infinite;
}
&.obj_name_wagon {
display: block;
animation: aWagon 10s ease-in-out infinite;
}
&.obj_name_gifts {
animation: aGiftsBounce 1s ease-in-out;
&.obj_type_btn {
cursor: url(https://raw.githubusercontent.com/elsemeow/cdn/main/img/cdpn/gOwYMNR/cursor-pointer.png),
pointer;
}
}
& .spr_name_gifts {
display: block;
}
}
&_active {
&.obj_type_btn {
cursor: url(https://raw.githubusercontent.com/elsemeow/cdn/main/img/cdpn/gOwYMNR/cursor-default.png),
default;
}
&.obj_name_loco,
&.obj_name_wagon {
animation-play-state: paused;
}
& .spr_name_loco,
& .spr_name_wagon {
opacity: 0;
animation: aSprZoomOut 1.5s ease-in-out;
}
&.obj_name_arrow {
filter: none;
animation: aArrowBounce 0.5s ease-in-out;
}
& .spr_name_arrow {
transform: none;
}
&.obj_name_gifts {
&.obj_type_btn {
filter: none;
cursor: url(https://raw.githubusercontent.com/elsemeow/cdn/main/img/cdpn/gOwYMNR/cursor-default.png),
default;
}
}
&.obj_name_snowman {
opacity: 0;
}
&.obj_name_snowman-dec {
display: block;
}
& .spr_name_snowman-dec {
opacity: 1;
}
}
}
}
// ---------------------------------------
// | animations
// ---------------------------------------
@keyframes aFloating {
0% {
transform: translateY(0) translateX(1vmin);
}
100% {
transform: translateY(-1vmin) translateX(-1vmin);
}
}
@keyframes aModal {
0% {
transform: scale(1);
opacity: 0;
}
50% {
transform: scale(1.2);
}
100% {
transform: scale(1);
opacity: 1;
}
}
@keyframes aLoco {
0% {
transform: translate(-27vmin, 11vmin);
}
80% {
opacity: 1;
}
100% {
opacity: 0;
transform: translate(29vmin, -18vmin);
}
}
@keyframes aWagon {
0% {
transform: translate(-30vmin, 12.5vmin);
}
90% {
opacity: 1;
}
100% {
opacity: 0;
transform: translate(26vmin, -16.5vmin);
}
}
@keyframes aSprZoomOut {
0% {
opacity: 1;
transform: rotate(0deg) scale(1);
}
15% {
transform: rotate(-10deg) scale(1.2);
}
100% {
opacity: 0;
transform: rotate(360deg) scale(0);
}
}
@keyframes aArrowBounce {
0% {
transform: translate(-5vmin, 5vmin) scale(1);
}
50% {
transform: translate(-5vmin, 5vmin) scale(0.8);
}
100% {
transform: translate(-5vmin, 5vmin) scale(1);
}
}
@keyframes aTree {
0% {
transform: skewX(3deg);
}
100% {
transform: skewX(-2deg);
}
}
@keyframes aGiftsBounce {
0% {
opacity: 0;
transform: translate(25vmin, -9vmin) scale(0);
}
50% {
transform: translate(25vmin, -9vmin) scale(1.3);
}
100% {
opacity: 1;
transform: translate(25vmin, -9vmin) scale(1);
}
}
@keyframes aSnowmanAppear {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
// ---------------------------------------
// | customizable snowflake styling
// | by @codeconvey
// ---------------------------------------
.snowflakes {
color: #fff;
font-size: 1em;
font-family: Arial;
text-shadow: 0 0 1px #000;
}
@keyframes snowflakes-fall {
0% {
top: -10%;
}
100% {
top: 100%;
}
}
@keyframes snowflakes-shake {
0% {
transform: translateX(0px);
}
50% {
transform: translateX(80px);
}
100% {
transform: translateX(0px);
}
}
.snowflake {
position: fixed;
top: -10%;
user-select: none;
animation-name: snowflakes-fall, snowflakes-shake;
animation-duration: 10s, 3s;
animation-timing-function: linear, ease-in-out;
animation-iteration-count: infinite, infinite;
animation-play-state: running, running;
}
.snowflake:nth-of-type(0) {
left: 1%;
animation-delay: 0s, 0s;
}
.snowflake:nth-of-type(1) {
left: 10%;
animation-delay: 1s, 1s;
}
.snowflake:nth-of-type(2) {
left: 20%;
animation-delay: 6s, 0.5s;
}
.snowflake:nth-of-type(3) {
left: 30%;
animation-delay: 4s, 2s;
}
.snowflake:nth-of-type(4) {
left: 40%;
animation-delay: 2s, 2s;
}
.snowflake:nth-of-type(5) {
left: 50%;
animation-delay: 8s, 3s;
}
.snowflake:nth-of-type(6) {
left: 60%;
animation-delay: 6s, 2s;
}
.snowflake:nth-of-type(7) {
left: 70%;
animation-delay: 2.5s, 1s;
}
.snowflake:nth-of-type(8) {
left: 80%;
animation-delay: 1s, 0s;
}
.snowflake:nth-of-type(9) {
left: 90%;
animation-delay: 3s, 1.5s;
}
// end of snowflakes
// ---------------------------------------
// | play / pause button
// ---------------------------------------
.toggle-song {
z-index: 1000;
position: absolute;
top: 20px;
left: 20px;
display: flex;
align-items: center;
&__btn {
border: none;
background-color: transparent;
color: #fafafa;
transition: 0.2s ease-in-out;
transition-property: transform, opacity;
cursor: url(https://raw.githubusercontent.com/elsemeow/cdn/main/img/cdpn/gOwYMNR/cursor-pointer.png),
pointer;
&:focus {
outline: none;
}
&:hover,
&:focus {
transform: translateY(2px);
opacity: 0.7;
}
}
&__text {
font-family: "Nerko One", cursive;
font-size: 14px;
color: #f1f1f1;
margin-left: 8px;
text-shadow: 1px 1px 0 #333;
}
}
// icons from https://css.gg/
.gg-play-button-o,
.gg-play-pause-o {
box-sizing: border-box;
position: relative;
display: block;
transform: scale(var(--ggs, 1));
width: 22px;
height: 22px;
border: 2px solid;
border-radius: 22px;
}
.gg-play-button-o::before {
content: "";
display: block;
box-sizing: border-box;
position: absolute;
width: 0;
height: 10px;
border-top: 5px solid transparent;
border-bottom: 5px solid transparent;
border-left: 6px solid;
top: 4px;
left: 7px;
}
.gg-play-pause-o::before {
content: "";
display: block;
box-sizing: border-box;
position: absolute;
width: 6px;
height: 6px;
left: 6px;
top: 6px;
border-left: 2px solid;
border-right: 2px solid;
}
View Compiled
(() => {
// constants
const timeEl = document.querySelector(".timer");
const start = document.querySelector(".js_scr_start");
const startOverlay = document.querySelector(".overlay_name_start");
const endOverlay = document.querySelector(".overlay_name_end");
const arrow = document.querySelector(".obj_name_arrow");
const loco = document.querySelector(".obj_name_loco");
const wagon = document.querySelector(".obj_name_wagon");
const gifts = document.querySelector(".obj_name_gifts");
const snowman = document.querySelector(".obj_name_snowman");
const snowmanDec = document.querySelector(".obj_name_snowman-dec");
const song = document.querySelector("#song");
const toggleSong = document.querySelector(".toggle-song__btn");
// sequence of events
start.addEventListener("click", () => {
startOverlay.classList.add("overlay_state_disabled");
});
arrow.addEventListener("click", () => {
arrow.classList.add("obj_state_active");
loco.classList.add("obj_state_run");
wagon.classList.add("obj_state_run");
});
wagon.addEventListener("click", () => {
loco.classList.add("obj_state_active");
wagon.classList.add("obj_state_active");
gifts.classList.add("obj_state_run");
});
gifts.addEventListener("click", () => {
gifts.classList.add("obj_state_active");
endOverlay.classList.remove("overlay_state_disabled");
});
snowman.addEventListener("click", () => {
snowman.classList.add("obj_state_active");
snowmanDec.classList.add("obj_state_active");
});
// countdown
const countDownDate = new Date("Jan 1, 2021 00:00:00").getTime();
let x = setInterval(() => {
const now = new Date().getTime();
const distance = countDownDate - now;
const days = Math.floor(distance / (1000 * 60 * 60 * 24));
const hours = Math.floor(
(distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)
);
const minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
timeEl.innerHTML = ` in ${days}d ${hours}h ${minutes}m`;
if (distance < 0) {
clearInterval(x);
timeEl.innerHTML = " right now";
}
}, 1000);
// song
song.volume = 0.1;
song.loop = true;
toggleSong.addEventListener("click", () => {
if (song.paused) {
song.play();
toggleSong.classList.remove("gg-play-button-o");
toggleSong.classList.add("gg-play-pause-o");
} else {
song.pause();
toggleSong.classList.remove("gg-play-pause-o");
toggleSong.classList.add("gg-play-button-o");
}
});
})();
View Compiled
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.