I have an issue on chrome in live but not in localhost (vs code live server). I'm making a countdown project with a flip animation. I have used a setInterval to add the class "active" and then after the animation I clone the node and remove the class. It works in firefox and safari in both localhost and live but not in chrome and edge for live; or at least not always.
Here there is my code:
function setEl(type) {
let flipNode = document.querySelector(`.countdown-${type}`);
flipNode.card = flipNode.querySelector(".card");
flipNode.CardFaces = flipNode.querySelectorAll(".card-face");
flipNode.digit = flipNode.querySelector(".digit");
flipNode.cardFaceFront = flipNode.querySelector(".card-face-front");
flipNode.cardFaceBack = flipNode.querySelector(".card-face-back");
//timer
let now = new Date().getTime();
let endDate = new Date("April 16, 2022 00:00:00");
let diff = endDate.getTime() - now;
//get seconds, minutes, hours and days in milliseconds
let s = 1000;
let m = s * 60;
let h = m * 60;
let d = h * 24;
//Check if the countdown is over
if (diff < 0) {
return
}
//get seconds, minutes, hours and days
let days = Math.floor(diff / d);
let hours = Math.floor((diff % d) / h);
let minutes = Math.floor((diff % h) / m);
let seconds = Math.floor((diff % m) / s);
let curr = null;
if (type === "seconds") {
curr = seconds;
if (diff > 0) {
flipNode.card.classList.add("active");
}
} else if (type === "minutes") {
curr = minutes;
if (seconds === 0) {
if (days !== 0 || hours !== 0) {
flipNode.card.classList.add("active");
}
}
} else if (type === "hours") {
curr = hours;
if (minutes === 0 && seconds === 0) {
flipNode.card.classList.add("active");
}
} else if (type === "days") {
curr = days;
if (hours === 0 && minutes === 0 && seconds === 0) {
flipNode.card.classList.add("active");
}
}
flipNode.digit.dataset.digitBefore = curr < 10 ? "0" + curr : curr;
flipNode.cardFaceFront.innerText = flipNode.digit.dataset.digitBefore;
if (curr === 0) {
if (type === "hours") {
flipNode.digit.dataset.digitAfter = 23;
} else {
flipNode.digit.dataset.digitAfter = 59;
}
flipNode.cardFaceBack.innerText = flipNode.digit.dataset.digitAfter;
} else {
flipNode.digit.dataset.digitAfter = (curr - 1) < 10 ? "0" + (curr - 1) : curr - 1;
flipNode.cardFaceBack.innerText = flipNode.digit.dataset.digitAfter;
}
flipNode.card.addEventListener("transitionend", function () {
if (curr === 0) {
if (type === "hours") {
flipNode.digit.dataset.digitBefore = 23;
} else {
flipNode.digit.dataset.digitBefore = 59;
}
} else {
flipNode.digit.dataset.digitBefore = (curr - 1) < 10 ? "0" + (curr - 1) : curr - 1;
}
flipNode.cardFaceFront.innerText = flipNode.digit.dataset.digitBefore;
//cone the node and replace it to have a new animation
let newFlipCard = flipNode.card.cloneNode(true);
newFlipCard.classList.remove("active");
flipNode.digit.replaceChild(newFlipCard, flipNode.card);
flipNode.card = newFlipCard;
//The var need to be reassigned or they will point out the old node and not the new one
flipNode.cardFaces = flipNode.querySelectorAll(".card-face");
flipNode.cardFaceFront = flipNode.cardFaces[0];
flipNode.cardFaceBack = flipNode.cardFaces[1];
flipNode.digit.dataset.digitAfter = (curr - 1) < 10 ? "0" + (curr - 1) : curr - 1;
flipNode.cardFaceBack.innerText = flipNode.digit.dataset.digitAfter;
}, { once: true });
}
function countdown() {
setEl("seconds");
setEl("minutes");
setEl("hours");
setEl("days");
}
countdown();
setInterval(() => {
countdown();
}, 1000);
/* font import */
@import url("https://fonts.googleapis.com/css2?family=Red+Hat+Text:wght@700&display=swap");
*,
::before,
::after {
margin: 0;
padding: 0;
box-sizing: border-box;
}
ul {
list-style-type: none;
}
body {
font-size: 14px;
font-family: "Red Hat Text", sans-serif;
}
.stars-background {
width: 100%;
height: 100%;
position: absolute;
overflow: hidden;
}
.app {
width: 100%;
height: calc(100vh - 220px);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.header-text {
position: relative;
top: -40px;
width: 90%;
font-size: 1.4rem;
letter-spacing: 5px;
margin-bottom: 50px;
text-align: center;
text-transform: uppercase;
color: white;
}
.countdown-container {
display: flex;
justify-content: center;
align-items: center;
width: 100%;
font-size: 40px;
line-height: 0;
}
@media (min-width: 600px) {
.countdown-container {
width: 100%;
}
}
@media (min-width: 1200px) {
.countdown-container {
width: 50%;
}
}
.countdown-container * {
user-select: none;
cursor: default;
width: 100%;
display: flex;
justify-content: space-around;
}
.countdown {
display: flex;
flex-wrap: wrap;
position: relative;
}
.countdown-time-text {
font-size: 0.5rem;
color: #8486a9;
line-height: normal;
padding-top: 5px;
text-transform: uppercase;
}
@media (min-width: 600px) {
.countdown-time-text {
font-size: 1.2rem;
}
}
.countdown .digit {
position: relative;
width: 70px;
height: 70px;
box-shadow: 0 5px 0px 0px black;
border-radius: 8px 8px 8px 8px;
perspective: 1000px;
backface-visibility: hidden;
color: #fb6087;
/* remove the persepective on firefox only due to a bug in the browser rendering with perspective and preseve 3d*/
}
@supports (-moz-appearance: none) {
.countdown .digit {
perspective: none;
}
}
@media (min-width: 600px) {
.countdown .digit {
width: 140px;
height: 140px;
}
}
.digit::before {
content: attr(data-digit-before);
bottom: 0;
align-items: flex-start;
background-color: #34364f;
padding-left: 1.2px;
}
@supports (-moz-appearance: none) {
.digit::before {
padding-left: 0;
}
}
.digit::after {
content: attr(data-digit-after);
background-color: #2c2c44;
color: #d3506f;
top: 0;
align-items: flex-end;
}
.digit::before,
.digit::after {
position: absolute;
z-index: 0;
display: flex;
justify-content: center;
width: 100%;
height: 50%;
overflow: hidden;
}
@media (min-width: 600px) {
.digit::before,
.digit::after {
font-size: 4rem;
}
}
.card {
position: relative;
z-index: 1;
width: 100%;
height: 50%;
transform-style: preserve-3d;
transform-origin: bottom;
transform: rotateX(0);
transition: transform 0.7s ease-in-out;
}
.card .bullet {
width: 100%;
}
.card::before, .card::after {
content: "";
position: absolute;
top: 32.5px;
z-index: 5;
width: 2.2px;
height: 5px;
background-color: black;
}
@media (min-width: 600px) {
.card::before, .card::after {
top: 65px;
width: 4.4px;
height: 10px;
}
}
.card::before {
left: 0;
border-radius: 0px 5px 5px 0px;
}
.card::after {
content: "";
right: 0;
border-radius: 5px 0px 0px 5px;
}
.card-face {
position: absolute;
display: flex;
justify-content: center;
width: 100%;
height: 100%;
overflow: hidden;
backface-visibility: hidden;
will-change: transform;
color: #fb6087;
}
@media (min-width: 600px) {
.card-face {
font-size: 4rem;
}
}
.card.active {
transform: rotateX(-180deg);
-moz-transform: rotateX(-180deg);
/* box-shadow: 10px 0px 10px #000; */
}
.card-face-front {
align-items: flex-end;
background-color: white;
background-color: #2c2c44;
color: #d3506f;
}
.card-face-back {
align-items: flex-start;
transform: rotateX(180deg);
-moz-transform: rotateX(-180deg);
background-color: #34364f;
}
.digit::before,
.card-face-back {
border-radius: 0 0 8px 8px;
}
.digit::after,
.card-face-front {
border-radius: 8px 8px 0 0;
}
.bottom-img {
width: 100%;
position: relative;
bottom: -20px;
overflow: hidden;
}
@media (min-width: 1440px) {
.bottom-img {
overflow: auto;
bottom: -30px;
}
}
.bottom-img img {
background-color: transparent;
transform: translateX(-55%);
}
@media (min-width: 600px) {
.bottom-img img {
transform: translateX(0);
}
}
@media (min-width: 1440px) {
.bottom-img img {
transform: scaleX(1.8);
height: 200px;
}
}
<div class="app">
<h1 class="header-text">We're launching soon</h1>
<div class="countdown-container">
<div class="countdown countdown-days">
<div class="digit" data-digit-before="0" data-digit-after="1">
<!--before-->
<div class="card">
<div class="card-face card-face-front">0</div>
<div class="card-face card-face-back">1</div>
<div class="bullet bullet-right"></div>
</div>
<!--after-->
</div>
<p class="countdown-time-text">days</p>
</div>
<div class="countdown countdown-hours">
<div class="digit" data-digit-before="0" data-digit-after="1">
<!--before-->
<div class="card">
<div class="card-face card-face-front">0</div>
<div class="card-face card-face-back">1</div>
</div>
<!--after-->
</div>
<p class="countdown-time-text">hours</p>
</div>
<div class="countdown countdown-minutes">
<div class="digit" data-digit-before="0" data-digit-after="1">
<!--before-->
<div class="card">
<div class="card-face card-face-front">0</div>
<div class="card-face card-face-back">1</div>
</div>
<!--after-->
</div>
<p class="countdown-time-text">minutes</p>
</div>
<div class="countdown countdown-seconds">
<div class="digit s" data-digit-before="0" data-digit-after="1">
<!--before-->
<div class="card s">
<div class="card-face card-face-front">0</div>
<div class="card-face card-face-back">1</div>
</div>
<!--after-->
</div>
<p class="countdown-time-text">seconds</p>
</div>
</div>
</div>
You can find my project here: https://github.com/PeteC88/countdown-frontend-mentor-challenge
and the live version here :
https://petec88.github.io/countdown-frontend-mentor-challenge/
Can you please help me?
Thank you so much