Close Menu

    Subscribe to Updates

    Get the latest creative news from FooBar about art, design and business.

    What's Hot

    How to make Helmet Reveal Animation using HTML CSS & JS

    3 January 2026

    How to make Animated Login Form with Glowing Input using HTML & CSS

    1 January 2026

    How to make Image Color Picker using HTML CSS & JS

    30 December 2025
    Facebook X (Twitter) Instagram YouTube Telegram Threads
    Coding StellaCoding Stella
    • Home
    • Blog
    • HTML & CSS
      • Login Form
    • JavaScript
    • Hire us!
    Coding StellaCoding Stella
    Home - JavaScript - How to make 10+ Christmas Tree Animation using HTML CSS & JS
    JavaScript

    How to make 10+ Christmas Tree Animation using HTML CSS & JS

    Coding StellaBy Coding Stella24 December 2025Updated:4 January 2026No Comments8 Mins Read
    Share Facebook Twitter Pinterest LinkedIn Tumblr Reddit Email WhatsApp Copy Link

    Let’s create 10+ Christmas Tree Animations using HTML, CSS, and JavaScript. This festive project will showcase multiple animated Christmas tree designs with smooth effects and cheerful visuals.

    We’ll use:

    • HTML to structure the trees and layout
    • CSS to style the trees, lights, and animations
    • JavaScript to add dynamic effects like blinking lights and movement

    This project is perfect for adding a holiday vibe to your website while practicing animations and creativity. Whether you’re a beginner or an experienced developer, these Christmas tree animations are fun to build and great for learning. Let’s spread some holiday cheer with code! 🎄✨

    HTML :

    This HTML file sets up a basic web page for a generative CSS Christmas tree animation. The <!DOCTYPE html> and <html lang="en"> define a modern HTML5 document, while the <head> includes character encoding, the page title, and links to a normalize CSS file for consistent styling across browsers and a custom style.css for design. The <body> itself has no visible HTML because everything is created using JavaScript, and the script.js file is loaded as a module, meaning it can use modern JS features and generates the entire visual effect dynamically.

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
      <meta charset="UTF-8">
      <title>10+ Christmas Tree Animation 🎄 @coding.stella</title>
      <link rel="stylesheet" href="https://public.codepenassets.com/css/normalize-5.0.0.min.css">
      <link rel="stylesheet" href="./style.css">
    
    </head>
    
    <body>
    
      <script type="module" src="./script.js"></script>
    
    </body>
    </html>

    CSS :

    This CSS creates a 3D animated Christmas tree made of glowing lights and a rotating star. The body sets a dark background and 3D perspective, while the .tree spins continuously using a rotateY animation. Each .tree__light is a small circular bulb positioned in 3D space using CSS variables, appearing one by one and flashing through different colors with glow effects. The star at the top is drawn with strokes, animates its outline and fill, and rotates smoothly. Overall, CSS variables plus keyframe animations handle positioning, timing, color changes, and 3D rotation to generate the full animated tree without extra HTML.

    * {
      box-sizing: border-box;
      transform-style: preserve-3d;
    }
    
    body {
      background: #14191f;
      min-height: 100vh;
      display: flex;
      align-items: center;
      justify-content: center;
      perspective: 100vmin;
      transform-style: preserve-3d;
    }
    
    .tree {
      position: relative;
      height: 50vmin;
      width: 25vmin;
      transform-style: preserve-3d;
      -webkit-animation: spin calc(var(--spin-speed, 2) * 1s) infinite linear var(--direction, normal);
      animation: spin calc(var(--spin-speed, 2) * 1s) infinite linear var(--direction, normal);
    }
    
    .tree__light {
      transform-style: preserve-3d;
      position: absolute;
      aspect-ratio: 1;
      width: calc(var(--light-size, 1) * 1vmin);
      border-radius: 50%;
      -webkit-animation: flash calc(var(--speed) * 1s) calc(var(--delay) * 1s) infinite var(--flash-timing-function, steps(1)), appear calc(var(--appear-speed, 0.1) * 1s) calc((var(--appear) * var(--appear-delay-step, 0.05)) * 1s) both;
      animation: flash calc(var(--speed) * 1s) calc(var(--delay) * 1s) infinite var(--flash-timing-function, steps(1)), appear calc(var(--appear-speed, 0.1) * 1s) calc((var(--appear) * var(--appear-delay-step, 0.05)) * 1s) both;
      left: 50%;
      transform: translate(-50%, 50%) rotateY(calc(var(--rotate, 0) * 1deg)) translate3d(0, 0, calc(var(--radius, 0) * 1vmin));
      bottom: calc(var(--y, 0) * 1%);
    }
    
    .tree__star {
      stroke-width: 1.25vmin;
      stroke-linejoin: round;
      stroke-linecap: round;
      stroke: #f5e0a3;
      filter: drop-shadow(0 0 2vmin #fcf1cf);
      height: 5vmin;
      width: 5vmin;
      overflow: visible !important;
      bottom: calc(100% + (var(--light-size) * 0.5vmin));
      left: 50%;
      transform: translate(-50%, 0) rotateY(20deg);
      position: absolute;
      stroke-dasharray: 1000 1000;
      fill: none;
      -webkit-animation: stroke 1s calc(((var(--delay) * 0.95) * var(--appear-delay-step, 0.05)) * 1s) both, fill 1s calc(((var(--delay) + 10) * var(--appear-delay-step, 0.05)) * 1s) both, star-spin calc(var(--spin-speed, 2) * 1s) infinite linear var(--star-direction, normal);
      animation: stroke 1s calc(((var(--delay) * 0.95) * var(--appear-delay-step, 0.05)) * 1s) both, fill 1s calc(((var(--delay) + 10) * var(--appear-delay-step, 0.05)) * 1s) both, star-spin calc(var(--spin-speed, 2) * 1s) infinite linear var(--star-direction, normal);
    }
    
    @-webkit-keyframes star-spin {
      to {
        transform: translate(-50%, 0) rotateY(calc(20deg + (var(--counter-star, 0) * 360deg)));
      }
    }
    
    @keyframes star-spin {
      to {
        transform: translate(-50%, 0) rotateY(calc(20deg + (var(--counter-star, 0) * 360deg)));
      }
    }
    
    @-webkit-keyframes fill {
      to {
        fill: hsla(45, 80%, 80%, var(--fill-star, 0));
      }
    }
    
    @keyframes fill {
      to {
        fill: hsla(45, 80%, 80%, var(--fill-star, 0));
      }
    }
    
    @-webkit-keyframes stroke {
      from {
        stroke-dashoffset: -1000;
      }
    }
    
    @keyframes stroke {
      from {
        stroke-dashoffset: -1000;
      }
    }
    
    @-webkit-keyframes spin {
      to {
        transform: rotateY(360deg);
      }
    }
    
    @keyframes spin {
      to {
        transform: rotateY(360deg);
      }
    }
    
    @-webkit-keyframes appear {
      from {
        opacity: 0;
      }
    }
    
    @keyframes appear {
      from {
        opacity: 0;
      }
    }
    
    @-webkit-keyframes flash {
    
      0%,
      100% {
        background: var(--color-one, #f00);
        box-shadow: 0 0 calc(var(--light-size) * 0.5vmin) var(--color-one);
      }
    
      20% {
        background: var(--color-two, #fff);
        box-shadow: 0 0 calc(var(--light-size) * 0.5vmin) var(--color-two);
      }
    
      40% {
        background: var(--color-three, #f00);
        box-shadow: 0 0 calc(var(--light-size) * 0.5vmin) var(--color-three);
      }
    
      60% {
        background: var(--color-four, #fff);
        box-shadow: 0 0 calc(var(--light-size) * 0.5vmin) var(--color-four);
      }
    
      80% {
        background: var(--color-five, #f00);
        box-shadow: 0 0 calc(var(--light-size) * 0.5vmin) var(--color-five);
      }
    }
    
    @keyframes flash {
    
      0%,
      100% {
        background: var(--color-one, #f00);
        box-shadow: 0 0 calc(var(--light-size) * 0.5vmin) var(--color-one);
      }
    
      20% {
        background: var(--color-two, #fff);
        box-shadow: 0 0 calc(var(--light-size) * 0.5vmin) var(--color-two);
      }
    
      40% {
        background: var(--color-three, #f00);
        box-shadow: 0 0 calc(var(--light-size) * 0.5vmin) var(--color-three);
      }
    
      60% {
        background: var(--color-four, #fff);
        box-shadow: 0 0 calc(var(--light-size) * 0.5vmin) var(--color-four);
      }
    
      80% {
        background: var(--color-five, #f00);
        box-shadow: 0 0 calc(var(--light-size) * 0.5vmin) var(--color-five);
      }
    }

    JavaScript :

    This JavaScript builds and controls a fully generative 3D Christmas tree using CSS variables and DOM elements. It randomly creates a configuration for lights, colors, rotation, speed, and effects, then renders the tree by programmatically adding light divs and an SVG star to the page. Each light gets its own position, delay, flash speed, and color, creating the spiral effect. The dat.GUI panel lets you tweak values like light count, size, colors, spin direction, and animation speed in real time, while updates are applied by syncing config values to CSS custom properties.

    import Color from 'https://cdn.skypack.dev/color';
    import { GUI } from 'https://cdn.skypack.dev/dat.gui';
    
    const CTRL = new GUI();
    
    const ASSIGN_COLORS = CONFIG => {
      ['one', 'two', 'three', 'four', 'five'].forEach(light => {
        CONFIG[`color-${light}`] = Color.rgb(Math.random() * 255, Math.random() * 255, Math.random() * 255).hex();
      });
    };
    
    const GEN_CONFIG = () => ({
      'lights': Math.random() * (100 - 30) + 30,
      'light-size': Math.random() * 2 + 0.5,
      'rotate': Math.floor(Math.random() * 10 + 5) * 360,
      'radius': Math.random() * (25 - 5) + 5,
      'height': 50,
      'fill-star': Math.random() > 0.5,
      'flash-speed-min': Math.random() * 2,
      'flash-speed-max': Math.random() * 10 + 2,
      'direction': Math.random() > 0.5,
      'counter-star': Math.random() > 0.5,
      'flash-steps': 1,
      'spin-speed': Math.random() * 5 + 1,
      'appear-speed': Math.random(),
      'appear-delay-step': 0.05,
      'color-one': '#ff0000',
      'color-two': '#ffffff',
      'color-three': '#ff0000',
      'color-four': '#ffffff',
      'color-five': '#ff0000'
    });
    
    
    let CONFIG = {
      random: () => {
        ASSIGN_COLORS(CONFIG);
        CTRL.updateDisplay();
        UPDATE();
      },
      render: () => RENDER(),
      generate: () => {
        const NEW_CONFIG = { ...CONFIG, ...GEN_CONFIG() };
        for (const key of Object.keys(CONFIG)) {
          CONFIG[key] = NEW_CONFIG[key];
        }
        ASSIGN_COLORS(CONFIG);
        CTRL.updateDisplay();
        RENDER();
      }
    };
    
    
    CONFIG = { ...CONFIG, ...GEN_CONFIG(), 'appear-speed': 0.5, 'appear-delay-step': 0.05 };
    
    
    const WHITELIST = ['spin-speed', 'counter-star', 'light-size', 'color-one', 'color-two', 'color-three', 'color-four', 'color-five', 'fill-star', 'appear-speed', 'appear-delay-step', 'flash-steps'];
    
    
    const UPDATE = () => {
      for (const key of Object.keys(CONFIG)) {
        if (WHITELIST.includes(key))
          document.documentElement.style.setProperty(`--${key}`, typeof CONFIG[key] === 'boolean' ? CONFIG[key] ? 1 : 0 : CONFIG[key]);
        if (key === 'flash-steps')
          if (CONFIG[key] === 0) document.documentElement.style.setProperty('--flash-timing-function', 'ease-in-out'); else
    
            document.documentElement.style.setProperty('--flash-timing-function', `steps(${CONFIG[key]})`);
        if (key === 'direction') {
          document.documentElement.style.setProperty('--direction', CONFIG[key] ? 'reverse' : 'normal');
          document.documentElement.style.setProperty('--star-direction', CONFIG[key] ? 'normal' : 'reverse');
        }
      }
    };
    
    const RENDER = () => {
      UPDATE();
      if (CONFIG['flash-speed-min'] > CONFIG['flash-speed-max']) {
        CONFIG['flash-speed-max'] = CONFIG['flash-speed-min'];
        CTRL.updateDisplay();
      }
      const FRAG = new DocumentFragment();
      const TREE = document.createElement('div');
      TREE.className = 'tree';
    
      for (let l = 0; l < CONFIG.lights; l++) {
        // Create a light and add it to the tree.
        const LIGHT = document.createElement('div');
        LIGHT.className = 'tree__light';
        LIGHT.style.setProperty('--appear', l);
        LIGHT.style.setProperty('--delay', -l);
        LIGHT.style.setProperty('--speed', Math.random() * (CONFIG['flash-speed-max'] - CONFIG['flash-speed-min']) + CONFIG['flash-speed-min']);
        LIGHT.style.setProperty('--y', 100 / CONFIG.lights * l);
        LIGHT.style.setProperty('--rotate', CONFIG.rotate / CONFIG.lights * (CONFIG.lights - l));
        LIGHT.style.setProperty('--radius', CONFIG.radius / CONFIG.lights * (CONFIG.lights - l));
        TREE.appendChild(LIGHT);
      }
    
      const STAR = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
      STAR.setAttribute('class', 'tree__star');
      STAR.setAttribute('viewBox', "0 0 113.32 108.44");
      STAR.style.setProperty('--delay', CONFIG.lights);
      const STAR_PATH = document.createElementNS(STAR.namespaceURI, 'path');
      STAR_PATH.setAttribute('d', 'M90.19 104.33L57.12 87.38 24.4 105l5.91-36.69L3.44 42.65l36.72-5.72 16.1-33.5L73.06 36.6l36.83 4.97-26.35 26.21z');
      STAR.appendChild(STAR_PATH);
      TREE.appendChild(STAR);
    
      FRAG.appendChild(TREE);
      const CURRENT_TREE = document.querySelector('.tree');
      if (CURRENT_TREE)
        CURRENT_TREE.parentNode.replaceChild(FRAG, CURRENT_TREE); else
    
        document.body.appendChild(FRAG);
    
    };
    
    const CFG = CTRL.addFolder('Tree Config');
    CFG.add(CONFIG, 'lights', 10, 200, 1).onChange(RENDER).name('Lights');
    CFG.add(CONFIG, 'light-size', 0.5, 3, 0.1).onChange(UPDATE).name('Light Size');
    CFG.add(CONFIG, 'rotate', 360, 5400, 10).onChange(RENDER).name('Distribution (deg)');
    CFG.add(CONFIG, 'radius', 4, 50, 0.1).onChange(RENDER).name('Radius (vmin)');
    CFG.add(CONFIG, 'fill-star').onChange(UPDATE).name('Fill Star');
    CFG.add(CONFIG, 'counter-star').onChange(UPDATE).name('Counter Star');
    CFG.add(CONFIG, 'direction').onChange(UPDATE).name('Reverse Spin');
    CFG.add(CONFIG, 'spin-speed', 0.5, 10, 0.1).onChange(UPDATE).name('Spin Speed');
    
    const CLR = CTRL.addFolder('Light Colors');
    CLR.addColor(CONFIG, 'color-one').onChange(UPDATE).name('One');
    CLR.addColor(CONFIG, 'color-two').onChange(UPDATE).name('Two');
    CLR.addColor(CONFIG, 'color-three').onChange(UPDATE).name('Three');
    CLR.addColor(CONFIG, 'color-four').onChange(UPDATE).name('Four');
    CLR.addColor(CONFIG, 'color-five').onChange(UPDATE).name('Five');
    CLR.add(CONFIG, 'random').name('Randomise');
    
    const FLS = CTRL.addFolder('Light Speed (Flash)');
    FLS.add(CONFIG, 'flash-speed-min', 0.1, 20, 0.1).onChange(RENDER).name('Min');
    FLS.add(CONFIG, 'flash-speed-max', 0.1, 20, 0.1).onChange(RENDER).name('Max');
    FLS.add(CONFIG, 'flash-steps', 0, 10, 1).onChange(UPDATE).name('Steps');
    
    const APP = CTRL.addFolder('Light Speed (Appear)');
    APP.add(CONFIG, 'appear-speed', 0.1, 2, 0.01).onChange(RENDER).name('Speed');
    APP.add(CONFIG, 'appear-delay-step', 0.01, 0.2, 0.01).onChange(RENDER).name('Delay Step');
    
    CTRL.add(CONFIG, 'generate').name('Generate New');
    CTRL.add(CONFIG, 'render').name('Render');
    
    RENDER();

    In conclusion, creating 10+ Christmas Tree Animations using HTML, CSS, and JavaScript is a fun and creative way to practice animations and visual effects. With simple code and festive ideas, you can bring holiday magic to your web projects. Keep experimenting and make your designs shine this Christmas! 🎅🎄

    If your project has problems, don’t worry. Just click to download the source code and face your coding challenges with excitement. Have fun coding!

    Animation Web Design
    Share. Copy Link Twitter Facebook LinkedIn Email WhatsApp
    Previous ArticleHow to make 3D Card Hover Animation in HTML CSS & JS
    Next Article How to make Juicy Hamburgers Menu using HTML and CSS
    Coding Stella
    • Website

    Related Posts

    JavaScript

    How to make Helmet Reveal Animation using HTML CSS & JS

    3 January 2026
    JavaScript

    How to make Image Color Picker using HTML CSS & JS

    30 December 2025
    JavaScript

    How to make 3D Card Hover Animation in HTML CSS & JS

    22 December 2025
    Add A Comment
    Leave A Reply Cancel Reply

    Trending Post

    Master Frontend in 100 Days Ebook

    2 March 202432K Views

    How to make Modern Login Form using HTML & CSS | Glassmorphism

    11 January 202430K Views

    How to make I love you Animation in HTML CSS & JavaScript

    14 February 202423K Views

    How to make Valentine’s Day Card using HTML & CSS

    13 February 202415K Views
    Follow Us
    • Instagram
    • Facebook
    • YouTube
    • Twitter
    ads
    Featured Post

    How to make Magnetic Button Hover Effect using HTML & CSS

    6 October 2025

    How to make QR Code Generator using HTML CSS & JavaScript

    14 January 2024

    How to make 3D Image Carousel using HTML & CSS

    11 November 2024

    How to make Awesome Cool Loading Animation in HTML CSS & JS

    15 December 2025
    Latest Post

    How to make Helmet Reveal Animation using HTML CSS & JS

    3 January 2026

    How to make Animated Login Form with Glowing Input using HTML & CSS

    1 January 2026

    How to make Image Color Picker using HTML CSS & JS

    30 December 2025

    How to make Happy New Year 2026 Animation using HTML and CSS

    28 December 2025
    Facebook X (Twitter) Instagram YouTube
    • About Us
    • Privacy Policy
    • Return and Refund Policy
    • Terms and Conditions
    • Contact Us
    • Buy me a coffee
    © 2026 Coding Stella. Made with 💙 by @coding.stella

    Type above and press Enter to search. Press Esc to cancel.

    Ad Blocker Enabled!
    Ad Blocker Enabled!
    Looks like you're using an ad blocker. We rely on advertising to help fund our site.
    Okay! I understood