<!-- original-source: https://codepen.io/ethancopping/pen/ExrGYGG -->
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Happy Holidays</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/all.min.css"
integrity="sha512-Evv84Mr4kqVGRNSgIGL/F/aIDqQb7xQ2vcrdIwxfjThSH8CSR7PBEakCr51Ck+w+/U6swU2Im1vVX0SVk9ABhg=="
crossorigin="anonymous" referrerpolicy="no-referrer" />
background-color: rgba(20, 20, 25, 1);
transform: translateY(0);
transform: translateY(100vh);
@keyframes diagonal-fall {
transform: translate(0, 0);
transform: translate(10vw, 100vh);
font-family: Arial, Helvetica, sans-serif;
<div class="snow-container"></div>
<div style="height: 200vh;" />
<div style="font-size: 3rem; margin-bottom: 20px;">Happy Holidays</div>
<i class="fa-brands fa-youtube fa-2xl" style="color: #ff0000;"></i>
document.addEventListener("DOMContentLoaded", function () {
const snowContainer = document.querySelector(".snow-container");
const particlesPerThousandPixels = 0.1;
const pauseWhenNotActive = true;
const maxSnowflakes = 200;
function resetSnowflake(snowflake) {
const size = Math.random() * 5 + 1;
const viewportWidth = window.innerWidth - size; // Adjust for snowflake size
const viewportHeight = window.innerHeight;
snowflake.style.width = `${size}px`;
snowflake.style.height = `${size}px`;
snowflake.style.left = `${Math.random() * viewportWidth}px`; // Constrain within viewport width
snowflake.style.top = `-${size}px`;
const animationDuration = (Math.random() * 3 + 2) / fallSpeed;
snowflake.style.animationDuration = `${animationDuration}s`;
snowflake.style.animationTimingFunction = "linear";
snowflake.style.animationName =
Math.random() < 0.5 ? "fall" : "diagonal-fall";
if (parseInt(snowflake.style.top, 10) < viewportHeight) {
resetSnowflake(snowflake);
snowflake.remove(); // Remove when it goes off the bottom edge
}, animationDuration * 1000);
function createSnowflake() {
if (snowflakes.length < maxSnowflakes) {
const snowflake = document.createElement("div");
snowflake.classList.add("snowflake");
snowflakes.push(snowflake);
snowContainer.appendChild(snowflake);
resetSnowflake(snowflake);
function generateSnowflakes() {
const numberOfParticles =
Math.ceil((window.innerWidth * window.innerHeight) / 1000) *
particlesPerThousandPixels;
const interval = 5000 / numberOfParticles;
clearInterval(snowflakeInterval);
snowflakeInterval = setInterval(() => {
if (isTabActive && snowflakes.length < maxSnowflakes) {
requestAnimationFrame(createSnowflake);
function handleVisibilityChange() {
if (!pauseWhenNotActive) return;
isTabActive = !document.hidden;
clearInterval(snowflakeInterval);
window.addEventListener("resize", () => {
clearInterval(snowflakeInterval);
setTimeout(generateSnowflakes, 1000);
document.addEventListener("visibilitychange", handleVisibilityChange);