Reputation: 73938
In the following example I have 3 divs they need to be animated using CSS3 Keyframe Animation with the following rules (when I mention hidden/show in the text below actually use opacity 0.1/1 in the CSS):
A) When the page load
B) When User click btnCorrect
C) When User click btnWrong
Currently:
Sequence case A) and B) work fine.
Sequence case A) and C) work fine.
But I am not able to fix the following cases:
Sequence case A) and B) and C) does not work(ladyWrong is not shown).
Sequence case A) and C) and B) does not work (ladyCorrect is not shown).
I would like to know how to fix it possibly using only CSS 3.
Test the following example using only Google Chrome.
var btnCorrect = document.getElementById('btnCorrect');
var btnWrong = document.getElementById('btnWrong');
var ladyDefault = document.getElementById('ladyDefault');
var ladyCorrect = document.getElementById('ladyCorrect');
var ladyWrong = document.getElementById('ladyWrong');
btnCorrect.addEventListener('click', function(event) {
ladyDefault.classList.add('hideLadyDefault');
ladyWrong.classList.add('hideLadyWrong');
ladyCorrect.classList.add('showLadyCorrect');
});
btnWrong.addEventListener('click', function(event) {
ladyDefault.classList.add('hideLadyDefault');
ladyCorrect.classList.add('hideLadyCorrect');
ladyWrong.classList.add('showLadyWrong');
});
#ladyDefault,
#ladyCorrect,
#ladyWrong {
width: 100px;
height: 150px;
display: inline-block;
margin: 5px;
}
#ladyDefault {
background-color: blue;
}
#ladyCorrect {
background-color: green;
opacity: 0.1;
}
#ladyWrong {
background-color: red;
opacity: 0.1;
}
#btnCorrect,
#btnWrong {
height: 50px;
width: 100px;
display: inline-block;
margin: 5px;
}
#btnCorrect {
background-color: lime;
}
#btnWrong {
background-color: darkred;
}
/*
--------------------------- lady default
*/
@keyframes hideLadyDefault {
0% {
opacity: 1;
}
100% {
opacity: 0.1;
}
}
.hideLadyDefault {
animation-name: hideLadyDefault;
animation-duration: 0;
animation-iteration-count: 1;
animation-direction: normal;
animation-fill-mode: forwards;
animation-delay: 0;
}
/*
--------------------------- lady correct
*/
@keyframes showLadyCorrect {
0% {
opacity: 0.1;
}
100% {
opacity: 1;
}
}
.showLadyCorrect {
animation-name: showLadyCorrect;
animation-duration: 1s;
animation-iteration-count: 1;
animation-direction: normal;
animation-fill-mode: forwards;
animation-delay: 0;
}
@keyframes hideLadyCorrect {
0% {
opacity: 1;
}
100% {
opacity: 0.1;
}
}
.hideLadyCorrect {
animation-name: hideLadyCorrect;
animation-duration: 0;
animation-iteration-count: 1;
animation-direction: normal;
animation-fill-mode: both
animation-delay: 0;
}
/*
--------------------------- lady wrong
*/
@keyframes showLadyWrong {
0% {
opacity: 0.1;
}
100% {
opacity: 1;
}
}
.showLadyWrong {
animation-name: showLadyWrong;
animation-duration: 1s;
animation-iteration-count: 1;
animation-direction: normal;
animation-fill-mode: forwards;
animation-delay: 0;
}
@keyframes hideLadyWrong {
0% {
opacity: 1;
}
100% {
opacity: 0.1;
}
}
.hideLadyWrong {
animation-name: hideLadyWrong;
animation-duration: 0;
animation-iteration-count: 1;
animation-direction: normal;
animation-fill-mode: both;
animation-delay: 0;
}
<div id="ladyDefault">ladyDefault</div>
<div id="ladyCorrect">ladyCorrect</div>
<div id="ladyWrong">ladyWrong</div>
<div id="btnCorrect">btnCorrect</div>
<div id="btnWrong">btnWrong</div>
Upvotes: 2
Views: 68
Reputation: 89770
Original Answer:
You need to remove the previous classes also before adding the new ones. When you don't remove the other class before adding a new one, each of them try to set an animation
on the same element and as is always the case with CSS, the selector (class) which is defined later in the CSS wins.
var btnCorrect = document.getElementById('btnCorrect');
var btnWrong = document.getElementById('btnWrong');
var ladyDefault = document.getElementById('ladyDefault');
var ladyCorrect = document.getElementById('ladyCorrect');
var ladyWrong = document.getElementById('ladyWrong');
btnCorrect.addEventListener('click', function(event) {
ladyDefault.classList.add('hideLadyDefault');
ladyWrong.classList.remove('showLadyWrong');
ladyWrong.classList.add('hideLadyWrong');
ladyCorrect.classList.remove('hideLadyCorrect');
ladyCorrect.classList.add('showLadyCorrect');
});
btnWrong.addEventListener('click', function(event) {
ladyDefault.classList.add('hideLadyDefault');
ladyCorrect.classList.remove('showLadyCorrect');
ladyCorrect.classList.add('hideLadyCorrect');
ladyWrong.classList.remove('hideLadyWrong');
ladyWrong.classList.add('showLadyWrong');
});
#ladyDefault,
#ladyCorrect,
#ladyWrong {
width: 100px;
height: 150px;
display: inline-block;
margin: 5px;
}
#ladyDefault {
background-color: blue;
}
#ladyCorrect {
background-color: green;
opacity: 0.1;
}
#ladyWrong {
background-color: red;
opacity: 0.1;
}
#btnCorrect,
#btnWrong {
height: 50px;
width: 100px;
display: inline-block;
margin: 5px;
}
#btnCorrect {
background-color: lime;
}
#btnWrong {
background-color: darkred;
}
/*
--------------------------- lady default
*/
@keyframes hideLadyDefault {
0% {
opacity: 1;
}
100% {
opacity: 0.1;
}
}
.hideLadyDefault {
animation-name: hideLadyDefault;
animation-duration: 0;
animation-iteration-count: 1;
animation-direction: normal;
animation-fill-mode: forwards;
animation-delay: 0;
}
/*
--------------------------- lady correct
*/
@keyframes showLadyCorrect {
0% {
opacity: 0.1;
}
100% {
opacity: 1;
}
}
.showLadyCorrect {
animation-name: showLadyCorrect;
animation-duration: 1s;
animation-iteration-count: 1;
animation-direction: normal;
animation-fill-mode: forwards;
animation-delay: 0;
}
@keyframes hideLadyCorrect {
0% {
opacity: 1;
}
100% {
opacity: 0.1;
}
}
.hideLadyCorrect {
animation-name: hideLadyCorrect;
animation-duration: 0;
animation-iteration-count: 1;
animation-direction: normal;
animation-fill-mode: both animation-delay: 0;
}
/*
--------------------------- lady wrong
*/
@keyframes showLadyWrong {
0% {
opacity: 0.1;
}
100% {
opacity: 1;
}
}
.showLadyWrong {
animation-name: showLadyWrong;
animation-duration: 1s;
animation-iteration-count: 1;
animation-direction: normal;
animation-fill-mode: forwards;
animation-delay: 0;
}
@keyframes hideLadyWrong {
0% {
opacity: 1;
}
100% {
opacity: 0.1;
}
}
.hideLadyWrong {
animation-name: hideLadyWrong;
animation-duration: 0;
animation-iteration-count: 1;
animation-direction: normal;
animation-fill-mode: both;
animation-delay: 0;
}
<div id="ladyDefault">ladyDefault</div>
<div id="ladyCorrect">ladyCorrect</div>
<div id="ladyWrong">ladyWrong</div>
<div id="btnCorrect">btnCorrect</div>
<div id="btnWrong">btnWrong</div>
Solution with only one keyframe rule:
You can also achieve the same effect with a single @keyframes
rule instead of using multiple. All that would be needed is to set the animation-direction
as reverse
for the hide. But the old class must still be removed because once an animation is set on the element, the UA remembers its execution as mentioned in this answer of mine.
var btnCorrect = document.getElementById('btnCorrect');
var btnWrong = document.getElementById('btnWrong');
var ladyDefault = document.getElementById('ladyDefault');
var ladyCorrect = document.getElementById('ladyCorrect');
var ladyWrong = document.getElementById('ladyWrong');
btnCorrect.addEventListener('click', function(event) {
ladyDefault.classList.add('hideLadyDefault');
ladyWrong.classList.remove('showLadyWrong');
ladyWrong.classList.add('hideLadyWrong');
ladyCorrect.classList.remove('hideLadyCorrect');
ladyCorrect.classList.add('showLadyCorrect');
});
btnWrong.addEventListener('click', function(event) {
ladyDefault.classList.add('hideLadyDefault');
ladyCorrect.classList.remove('showLadyCorrect');
ladyCorrect.classList.add('hideLadyCorrect');
ladyWrong.classList.remove('hideLadyWrong');
ladyWrong.classList.add('showLadyWrong');
});
#ladyDefault,
#ladyCorrect,
#ladyWrong {
width: 100px;
height: 150px;
display: inline-block;
margin: 5px;
}
#ladyDefault {
background-color: blue;
}
#ladyCorrect {
background-color: green;
opacity: 0.1;
}
#ladyWrong {
background-color: red;
opacity: 0.1;
}
#btnCorrect,
#btnWrong {
height: 50px;
width: 100px;
display: inline-block;
margin: 5px;
}
#btnCorrect {
background-color: lime;
}
#btnWrong {
background-color: darkred;
}
/*
--------------------------- lady default
*/
.hideLadyDefault {
animation-name: show;
animation-duration: 0;
animation-iteration-count: 1;
animation-direction: reverse;
animation-fill-mode: forwards;
animation-delay: 0;
}
/*
--------------------------- lady correct
*/
@keyframes show {
0% {
opacity: 0.1;
}
100% {
opacity: 1;
}
}
.showLadyCorrect {
animation-name: show;
animation-duration: 1s;
animation-iteration-count: 1;
animation-direction: normal;
animation-fill-mode: forwards;
animation-delay: 0;
}
.hideLadyCorrect {
animation-direction: reverse;
}
/*
--------------------------- lady wrong
*/
.showLadyWrong {
animation-name: show;
animation-duration: 1s;
animation-iteration-count: 1;
animation-direction: normal;
animation-fill-mode: forwards;
animation-delay: 0;
}
.hideLadyWrong {
animation-direction: reverse;
}
<div id="ladyDefault">ladyDefault</div>
<div id="ladyCorrect">ladyCorrect</div>
<div id="ladyWrong">ladyWrong</div>
<div id="btnCorrect">btnCorrect</div>
<div id="btnWrong">btnWrong</div>
Solution with transition: (might be better fit)
The better option would be to use transition
if you could instead of animation
. Here you could just set the opacity
via inline style attributes and let the transition
property handle the rest. Unlike the animations, transitions can execute the reverse state by default. (This is the best bet if it only a simple change of opacity from 0.1 to 1, if it is a complex multi-step change the transitions are out of scope.)
var btnCorrect = document.getElementById('btnCorrect');
var btnWrong = document.getElementById('btnWrong');
var ladyDefault = document.getElementById('ladyDefault');
var ladyCorrect = document.getElementById('ladyCorrect');
var ladyWrong = document.getElementById('ladyWrong');
btnCorrect.addEventListener('click', function(event) {
ladyDefault.style["opacity"] = "0.1";
ladyWrong.style["opacity"] = "0.1";
ladyCorrect.style["opacity"] = "1";
});
btnWrong.addEventListener('click', function(event) {
ladyDefault.style["opacity"] = "0.1";
ladyCorrect.style["opacity"] = "0.1";
ladyWrong.style["opacity"] = "1";
});
#ladyDefault,
#ladyCorrect,
#ladyWrong {
width: 100px;
height: 150px;
display: inline-block;
margin: 5px;
}
#ladyDefault {
background-color: blue;
transition: all 1s ease;
}
#ladyCorrect {
background-color: green;
opacity: 0.1;
transition: all 1s ease;
}
#ladyWrong {
background-color: red;
opacity: 0.1;
transition: all 1s ease;
}
#btnCorrect,
#btnWrong {
height: 50px;
width: 100px;
display: inline-block;
margin: 5px;
}
#btnCorrect {
background-color: lime;
}
#btnWrong {
background-color: darkred;
}
<div id="ladyDefault">ladyDefault</div>
<div id="ladyCorrect">ladyCorrect</div>
<div id="ladyWrong">ladyWrong</div>
<div id="btnCorrect">btnCorrect</div>
<div id="btnWrong">btnWrong</div>
Upvotes: 2
Reputation: 6642
You are adding all classes correctly, but you are not removing the added classes later, thats the issue. Change your listeners to
btnCorrect.addEventListener('click', function(event) {
ladyDefault.classList.add('hideLadyDefault');
ladyWrong.classList.add('hideLadyWrong');
ladyCorrect.classList.add('showLadyCorrect');
ladyCorrect.classList.remove('hideLadyCorrect'); //added
});
btnWrong.addEventListener('click', function(event) {
ladyDefault.classList.add('hideLadyDefault');
ladyCorrect.classList.add('hideLadyCorrect');
ladyWrong.classList.add('showLadyWrong');
ladyWrong.classList.remove('hideLadyWrong'); //added
});
var btnCorrect = document.getElementById('btnCorrect');
var btnWrong = document.getElementById('btnWrong');
var ladyDefault = document.getElementById('ladyDefault');
var ladyCorrect = document.getElementById('ladyCorrect');
var ladyWrong = document.getElementById('ladyWrong');
btnCorrect.addEventListener('click', function(event) {
ladyDefault.classList.add('hideLadyDefault');
ladyWrong.classList.add('hideLadyWrong');
ladyCorrect.classList.add('showLadyCorrect');
ladyCorrect.classList.remove('hideLadyCorrect');
});
btnWrong.addEventListener('click', function(event) {
ladyDefault.classList.add('hideLadyDefault');
ladyCorrect.classList.add('hideLadyCorrect');
ladyWrong.classList.add('showLadyWrong');
ladyWrong.classList.remove('hideLadyWrong');
});
#ladyDefault,
#ladyCorrect,
#ladyWrong {
width: 100px;
height: 150px;
display: inline-block;
margin: 5px;
}
#ladyDefault {
background-color: blue;
}
#ladyCorrect {
background-color: green;
opacity: 0.1;
}
#ladyWrong {
background-color: red;
opacity: 0.1;
}
#btnCorrect,
#btnWrong {
height: 50px;
width: 100px;
display: inline-block;
margin: 5px;
}
#btnCorrect {
background-color: lime;
}
#btnWrong {
background-color: darkred;
}
/*
--------------------------- lady default
*/
@keyframes hideLadyDefault {
0% {
opacity: 1;
}
100% {
opacity: 0.1;
}
}
.hideLadyDefault {
animation-name: hideLadyDefault;
animation-duration: 0;
animation-iteration-count: 1;
animation-direction: normal;
animation-fill-mode: forwards;
animation-delay: 0;
}
/*
--------------------------- lady correct
*/
@keyframes showLadyCorrect {
0% {
opacity: 0.1;
}
100% {
opacity: 1;
}
}
.showLadyCorrect {
animation-name: showLadyCorrect;
animation-duration: 1s;
animation-iteration-count: 1;
animation-direction: normal;
animation-fill-mode: forwards;
animation-delay: 0;
}
@keyframes hideLadyCorrect {
0% {
opacity: 1;
}
100% {
opacity: 0.1;
}
}
.hideLadyCorrect {
animation-name: hideLadyCorrect;
animation-duration: 0;
animation-iteration-count: 1;
animation-direction: normal;
animation-fill-mode: both
animation-delay: 0;
}
/*
--------------------------- lady wrong
*/
@keyframes showLadyWrong {
0% {
opacity: 0.1;
}
100% {
opacity: 1;
}
}
.showLadyWrong {
animation-name: showLadyWrong;
animation-duration: 1s;
animation-iteration-count: 1;
animation-direction: normal;
animation-fill-mode: forwards;
animation-delay: 0;
}
@keyframes hideLadyWrong {
0% {
opacity: 1;
}
100% {
opacity: 0.1;
}
}
.hideLadyWrong {
animation-name: hideLadyWrong;
animation-duration: 0;
animation-iteration-count: 1;
animation-direction: normal;
animation-fill-mode: both;
animation-delay: 0;
}
<div id="ladyDefault">ladyDefault</div>
<div id="ladyCorrect">ladyCorrect</div>
<div id="ladyWrong">ladyWrong</div>
<div id="btnCorrect">btnCorrect</div>
<div id="btnWrong">btnWrong</div>
Upvotes: 1