Is your CSS animation not functioning properly?

As the holiday season approaches, I decided to create a Christmas countdown using JavaScript and HTML. However, I encountered some difficulties with the CSS styling. Here is the code I have been working on:

//Code for Christmas Countdown
var head = document.getElementById('head');
var subhead = document.getElementById('subhead');
var counter = document.getElementById('counter');

var christmas = new Date('December 25, 2016 00:00:00');

//Function to update timer
function updateTimer(christmas) {
    
    var time = christmas - new Date();
    
    return {
        'days': Math.floor(time / (1000 * 60 * 60 * 24)),
        'hours': Math.floor((time/(1000 * 60 * 60)) % 24),
        'minutes': Math.floor((time / 1000 / 60) % 60),
        'seconds': Math.floor((time / 1000) % 60),
        'total': time
    };
};

//Starts the timer
function startTimer(counter, christmas) {
    
    var timerInterval = setInterval(function() {
        var timer = updateTimer(christmas);
        
        //Update the timer display
        counter.innerHTML = '<span>' + timer.days + '</span>'
                       + '<span>' + timer.hours + '</span>'
                        + '<span>' + timer.minutes + '</span>'
                        + '<span>' + timer.seconds + '</span>';
        
        //Display messages when it's Christmas or Christmas Eve
        if(timer.total < 1) {
            clearInterval(timerInterval);
            counter.innerHTML = '<span>0</span><span>0</span><span>0</span><span>0</span>';
            
            head.innerHTML = "It's Christmas!!!";
            subhead.innerHTML = "Merry Christmas to all!!!";
        }
        else if (timer.days < 1){
            subhead.innerHTML = "It is currently Christmas Eve! How much longer until Christmas Day???";
        }
   
    }, 1000); //timer updates every second
};

window.onload = function() {
    
    startTimer(counter, christmas);
};  
*:focus {
    outline: none;
}

body {
  background-color: #991f00;
  text-shadow: 2px 2px 8px #000000;
}

header {
    color: white;
    text-align: center;
    font-family: 'Cinzel Decorative', sans-serif;
}

#clock span {
    float: left;
    text-align: center;
    margin: 0 2.5%;
    padding: 20px;
    width: 20%;
    box-sizing: border-box;
    color: white;
    font-family: 'Mountains of Christmas', sans-serif;
    font-size: 40px;
}

#counter span {
    background-color: #000000;
    border-radius: 100%;
    animation-name: colorChange;
    animation-duration: 6s;
    animation-fill-mode: both;
    animation-iteration-count: infinite;
    
}

@keyframes colorChange {
    0%, 100% {
        background-color: #42f471;
    }
    50% {
        background-color: #ea524f;
    }
}
<!DOCTYPE html>
<html>
    <head>
        <title>Christmas Countdown</title>
        <script type="text/javascript" src="scripts/script.js" async></script>
        <link rel="stylesheet" type="text/css" href="style.css">
        <link href="https://fonts.googleapis.com/css?family=Cinzel+Decorative|Mountains+of+Christmas" rel="stylesheet">
    </head>
    <body>
        <div id="wrapper">
            <div id="clock">
                <header>
                    <h1 id="head">Christmas Countdown!</h1>
                    <h4 id="subhead">How much longer until Christmas? Check the clock to find out!</h4>
                </header>
                <div id="count-container">
                    <div id="counter"></div>
                    <div id="labels">
                        <span>Days</span>
                        <span>Hours</span>
                        <span>Minutes</span>
                        <span>Seconds</span>
                    </div>
                </div>
            </div>
        </div>
    </body>
</html>

I attempted to add a CSS animation using @keyframes, inspired by the effects seen on this website. My goal was to transition between two colors (#42f471 and #ea524f) in a loop. Despite setting the duration to 6s, the animation did not complete before abruptly reverting to the initial color. Adjusting the duration only impacted the speed of the flash, with shorter durations completing more cycles but appearing too fast. As someone unfamiliar with animations, my attempts based on online research have not resolved the issue.

Any assistance regarding this matter would be greatly appreciated. I am also open to implementing solutions using JavaScript or Jquery if necessary.

Answer №1

Take note that the animation restarts every time the timer updates because your JavaScript is recreating those DOM elements, causing the animation to start from the beginning each time. To fix this issue, target your spans by giving them individual IDs like so:

//Get the HTML Elements
var head = document.getElementById('head');
var subhead = document.getElementById('subhead');
var counterDays = document.getElementById('days');
var counterHours = document.getElementById('hours');
var counterMinutes = document.getElementById('minutes');
var counterSeconds = document.getElementById('seconds');
//Find Christmas date
var christmas = new Date('December 25, 2016 00:00:00');

//Update Timer function
function updateTimer(christmas) {
    
    var time = christmas - new Date();
    //Define what to update
    return {
        'days': Math.floor(time / (1000 * 60 * 60 * 24)),
        'hours': Math.floor((time/(1000 * 60 * 60)) % 24),
        'minutes': Math.floor((time / 1000 / 60) % 60),
        'seconds': Math.floor((time / 1000) % 60),
        'total': time
    };
};

//Start the timer
function startTimer(counterDays, counterHours, counterMinutes, counterSeconds, christmas) {
    
    var timerInterval = setInterval(function() {
        var timer = updateTimer(christmas);
        
        //Change the text of the counters
        counterDays.innerHTML = timer.days;
        counterHours.innerHTML = timer.hours;
        counterMinutes.innerHTML = timer.minutes;
        counterSeconds.innerHTML = timer.seconds;
        
        //Christmas message
        if(timer.total < 1) {
            clearInterval(timerInterval);
            counterDays.innerHTML = 0;
            counterHours.innerHTML = 0;
            counterMinutes.innerHTML = 0;
            counterSeconds.innerHTML = 0;
            
            head.innerHTML = "It's Christmas!!!";
            subhead.innerHTML = "Merry Christmas to all!!!";
        }
        
        //Christmas Eve message
        else if (timer.days < 1){
            subhead.innerHTML = "It is currently Christmas Eve! How much longer until Christmas Day???";
        }
   
    }, 1000); //update every second
};

window.onload = function() {
    
    startTimer(counterDays, counterHours, counterMinutes, counterSeconds, christmas);
};
*:focus {
    outline: none;
}

body {
  background-color: #991f00;
  text-shadow: 2px 2px 8px #000000;
}

header {
    color: white;
    text-align: center;
    font-family: 'Cinzel Decorative', sans-serif;
}

#clock span {
    float: left;
    text-align: center;
    margin: 0 2.5%;
    padding: 20px;
    width: 20%;
    box-sizing: border-box;
    color: white;
    font-family: 'Mountains of Christmas', sans-serif;
    font-size: 40px;
}

#counter span {
    background-color: #000000;
    border-radius: 100%;
    animation-name: colorChange;
    animation-duration: 6s;
    animation-fill-mode: both;
    animation-iteration-count: infinite;
    
}

@keyframes colorChange {
    0%, 100% {
        background-color: #42f471;
    }
    50% {
        background-color: #ea524f;
    }
}
<!DOCTYPE html>
<html>
    <head>
        <title>Christmas Countdown</title>
        <!--<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>!-->
        <script type="text/javascript" src="scripts/script.js" async></script>
        <!--<script type="text/javascript" src="scripts/color.js" async></script>!-->
        <link rel="stylesheet" type="text/css" href="style.css">
        <link href="https://fonts.googleapis.com/css?family=Cinzel+Decorative|Mountains+of+Christmas" rel="stylesheet">
    </head>
    <body>
        <div id="wrapper">
            <div id="clock">
                <header>
                    <h1 id="head">Christmas Countdown!</h1>
                    <h4 id="subhead">How much longer until Christmas? Check the clock to find out!</h4>
                </header>
                <div id="count-container">
                    <div id="counter">
                        <span id="days">&nbsp;</span>
                        <span id="hours">&nbsp;</span>
                        <span id="minutes">&nbsp;</span>
                        <span id="seconds">&nbsp;</span>
                    </div>
                    <div id="labels">
                        <span>Days</span>
                        <span>Hours</span>
                        <span>Minutes</span>
                        <span>Seconds</span>
                    </div>
                </div>
            </div>
        </div>
    </body>
</html>

Answer №2

The main issue lies in continuously rebuilding the DOM elements every second, while the animation is only set for 6 seconds.

Instead of reconstructing the entire DOM structure like this:

counter.innerHTML = '<span>' + timer.days + '</span>'
                   + '<span>' + timer.hours + '<span>'
                    + '<span>' + timer.minutes + '<span>'
                    + '<span>' + timer.seconds + '</span>';

The solution is to update the inner text of each span individually, rather than recreating them altogether.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

The ValidationEngine fails to validate a dynamically generated form

After dynamically creating a form, the validationEngine stops working. $(window).load(function($) { var form = document.createElement('form'); form.setAttribute('id', 'xform'); var lbl_usr = do ...

When running the `npm run dev` command, Tailwind does not seem to function

I have been given a task to create forms using tailwindcss, but when I try to run `npm run build`, it doesn't work. Can anyone assist me with this? npm ERR! code ELIFECYCLE npm ERR! errno 9 npm ERR! <a href="/cdn-cgi/l/email-protection" class="__cf ...

Setting the selected option in a Razor HTML Select/Option after a postback

Currently, I have a HTML select element with 3 options. My goal is to specify which option should be selected after a post back on my form. The technologies I am using include Razor (C#), HTML, jQuery, and CSS. If possible, I would like to achieve this ...

Enhancing the Search Bar in Bootstrap 4 Dashboard Template: A Step-by-Step Guide

Recently got my hands on the Bootstrap 4 Dashboard template and decided to enhance it by adding a form to the top search bar. However, I encountered an issue where the search bar shrinks and loses its original design. If you want to check out the Bootstra ...

Exploring the CSS transitions using jQuery to create fade-in fade-out effects

I'm currently developing an app using Cordova and incorporating jQuery effects like fadein and fadeout. However, I've noticed that these effects are quite slow on my android device. To address this, I'm considering converting them to CSS and ...

Click the closest checkbox when the value equals the Jquery datatable

I am facing an issue where I need to add a class and click on a specific element in each row of my jQuery datatable if a certain value is equal. However, I am unable to successfully add the class to that element and trigger a click event. <table id="us ...

Creating beautifully formatted HTML text in a PDF document using JavaFX and iText

Can you convert a styled HTML text (with color, alignment, etc.) from an editor like HTMLEditor to an editable PDF using iText? I've searched online but couldn't find any information on this. Appreciate any help. Thank you. ...

Maintaining a fixed header that remains visible while scrolling through a dropdown menu in Angular

In my application, I have a mat-select widget that displays a list of options. When scrolling within the list, I find it difficult to keep track of all the options. I am looking to enhance the user experience by adding a fixed header at the top of the opt ...

Is there a way to ensure my JQuery .on('click', ) function can be used multiple times?

Attempting to create a sliding pop-up feature where clicking on a label will reveal and slide out the content, then clicking the same label again will hide the content. Using JQuery for animating the div class, however the animation only triggers once per ...

Optimizing Video for HTML5: A Guide to Best

My website is filled with videos, but I've been experiencing slow loading times on some of them. Could the resolution be the cause? Any tips on how to optimize video loading speed? What are your thoughts and experiences with html5 video settings? Whi ...

What is the best way to ensure an element fills the entire height of its container?

Is there a way to handle the overflow of a div when it exceeds its container's size without specifying the height? Requirements: .Wrap must adjust in height and should not have a fixed height. .Head needs to have a fixed height. .Body should become ...

Disabling the default validation message in HTML form inputs

Is there a way to change the default message that appears when submitting an empty HTML text input? I would like the box border to turn red instead. Can anyone help me achieve this? Below is the code for the text input box: <div class="input-group ...

The MySQL query is returning a blank result with only the column headings displaying

I have been working on improving my skills in PHP and AJAX by developing an application that enables users to search a database for real-time product stock information. Currently, I am facing an issue where the headings are displayed when a user types a le ...

Adjust the text color when hovering with the style tag

When it comes to customizing the color of a link on hover, CSS makes it simple with code like this: .myId:hover{ color:green; } But what if you're using inline styles? Is there a way to achieve the same effect without just plain HTML and CSS? & ...

Executing JavaScript function from external SVG file globally

I am working on an HTML page that includes an external JavaScript module <script type="text/javascript" src="js/js.js"></script> and also an external SVG map called "img/map.svg". My goal is to create clickable objects on the map that will t ...

Issue with vertical alignment in form input text area not functioning properly

Need some help aligning inputted text with the top of a textarea on an HTML form. I've scoured forums for solutions, but no luck so far. I attempted using: textarea{ vertical-align:top;} and input["textarea"]{ vertical-align:top;} Tried adding ...

Looking for tips on resolving issues with the bootstrap navigation bar?

Check out this code snippet: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport ...

Is there a way to pass an HTMLDivElement as a child in React components?

Scenario Currently, I am in the process of developing a React application (rails-react) where the main component is called GameTracker. Within this parent component, there are two child components: EquipmentPanel and PinnedPanels. To achieve a specific fu ...

Unsuccessful passing of the popstate event in jQuery bind

Currently, I am working on a small demo using the History API, but I seem to be facing some challenges: $(window).bind('popstate', function(event) { console.log('pop: ' + event.state); }); When I click on the 'P ...

Drag and Drop Functionality in ReactJS for Organizing Multiple Lists

After hours of searching, I have yet to find a React library that can handle sorting between multiple lists. The closest solution I came across was in this article: There is also an example provided here: The issue with this solution is that you have to ...