I built a card game where upon clicking a button the display will either be "Correct!" or "Wrong!" I would like the display to flash and then go away after a couple second but not rearrange the content below it, which in this case is the #winStreak and #longestStreak. I do not want to use jQuery. I have tried adding transitions to CSS, but that does not seem to work.
HTML:
<p id="displayResult"></p>
<p id="winStreak"></p>
<p id="longestStreak"></p>
CSS:
#displayResult {
margin-bottom: 1rem;
transition: 2s ease-in-out;
}
JavaScript:
let foldButton = document.getElementById("foldBTN")
foldButton.addEventListener("click", function(){
if (!table[position].includes(completeHand) && !table[position].includes(completeHand2)) {
document.getElementById("displayResult").innerHTML = "Correct!";
I believe you might use CSS animation:
var result = document.getElementById('displayResult');
result.addEventListener('animationend', function() {
result.classList.remove('flashit');
});
let foldButton = document.getElementById('foldBTN');
foldButton.addEventListener('click', function() {
result.innerHTML = 'Correct!';
result.classList.add('flashit');
});
#displayResult {
font-size:3rem;
height: 1.3em;
margin-bottom: 1rem;
opacity: 0;
}
#displayResult.flashit {
animation: flashit 3s;
}
#keyframes flashit {
5% {opacity:.5}
10% {opacity:1}
15% {opacity:.2}
20% {opacity:1}
40% {opacity:1}
100% {opacity:0}
}
<div id="displayResult"></div>
<button id="foldBTN">CLICK ME</button>
Related
so I have a simple side bar that I want to slide in and out using css animation, now the slide animation in is working the problem that I am facing is making the animation for the slideout to work.
Can I please get help on that..
Html(Sidebar)
<div class="SideBarMenu" id="SideBarMenu">
<div class="sidebar-menu-header">
<h2 class="nav-bleft-companyname">
Sofast<span class="nav-bleft-periodmark">Cart.</span>
</h2>
</div>
<hr />
<h4 class="sidebar-menuLink">MenuItem1</h4>
<h4 class="sidebar-menuLink">MenuItem2</h4>
<h4 class="sidebar-menuLink">MenuItem3</h4>
<h4 class="sidebar-menuLink">MenuItem4</h4>
<h4 class="sidebar-menuLink">MenuItem5</h4>
</div>
JS Function triggered to toggle menu
const OpenMenu = () => {
const menu = document.getElementById("SideBarMenu");
if (menu.style.display === "block") {
menu.classList.add("sidebar-closed");
menu.style.animation = "slideOut 0.4s backwards";
menu.style.display = "none";
} else {
menu.style.display = "block";
menu.style.animation = "slideIn 0.4s forwards";
menu.classList.remove("sidebar-closed");
}
};
Side Bar css
.SideBarMenu {
top: 0% !important;
z-index: 999;
position: fixed;
background-color: #333333;
height: 100vh;
color: white;
width: 20%;
transform: translateX(-350px);
padding: 2rem;
}
.sidebar-menuLink {
margin-top: 1rem;
}
#keyframes slideIn {
100% {
transform: translateX(0px);
}
}
#keyframes slideOut {
100% {
transform: translateX(-350px);
}
}
You can use css transition to achieve that. I also advise you to put all your styles in css classes, you don't need to apply the styles in javascript.
const animate = () => {
const elem = document.getElementById("my-elem");
if (!elem.classList.contains('elem-out')) {
elem.classList.add("elem-out");
} else {
elem.classList.remove("elem-out");
}
};
const btn = document.getElementById("my-btn");
btn.addEventListener("click", animate)
.elem {
width: 300px;
height: 50px;
background-color: red;
margin-bottom: 10px;
}
.elem:not(.elem-out) {
transition: transform 0.4s ease-in;
transform: translateX(0px);
}
.elem-out {
transition: transform 0.4s ease-out;
transform: translateX(-350px);
}
<div id="my-elem" class="elem"></div>
<button id="my-btn">toggle animate</button>
Do not change the display property, the transition will brake. There's no transition for propperty like display, if you want a fadeIn / fadeOut effect too, you can put a transition on opacity property
my code looks like this:
var text = document.getElementById('text');
var toggle = true;
setInterval(function(){
if (toggle){
text.innerHTML = 'text1';
} else {
text.innerHTML = 'text2';
}
toggle = !toggle;
}, 500)
#text{
position: relative;
background-color: white;
z-index: 2;
padding: 0 10px;
}
#marqueeContainer{
z-index: 1;
}
#keyframes marquee{
from {
transform: translateX(100%);
}
to {
transform: translateX(-100%);
}
}
#marquee {
animation: marquee 10s linear infinite;
display: inline-block;
}
<span id="text">
text
</span>
<span id="marqueeContainer">
<span id="marquee">
marquee
marquee
marquee
marquee
marquee
</span>
</span>
or take a look here:
https://codepen.io/jacquesknie/pen/ZEExZNy
There is this text which is toggled with a setInterval and as soon as there is an animation running underneath Safari is not updating/repainting the text. Chrome and Firefox are behaving just fine. What is going on, am I overlooking something obvious?
Thank a lot,
Jacques
On Safari you must use
#-webkit-keyframes
See https://developer.apple.com/library/archive/documentation/AppleApplications/Reference/SafariCSSRef/Articles/OtherStandardCSS3Features.html
I made this
http://codepen.io/adamchenwei/pen/dOvJNX
and I try to apply a certain way of moving for a dom so it move for a fixed distance and stop, instead of animate and move through the whole width of the dom. However, I don't really want to fix the distance inside the css keyframe because I need to detect that distance dynamically, since my div that got animated ideally will change the width dynamically as well since that is not going always be 100% or any specific px fixed.
Is there way I can do that in JavaScript instead and not let css to take charge in this transform distance part?
Cross browser capacity will be great.
SCSS
.myItem {
height: 100px;
width: 501px;
background-color: beige;
animation: to-left-transition 300ms;
animation-iteration-count: 1;
animation-fill-mode: forwards;
animation-timing-function: ease-in-out;
}
#keyframes to-left-transition {
0% {
transform: translate(0);
}
100% {
transform: translate(100%);
}
}
HTML
<div class="myItem">
stuff here
</div>
Found out a better way. Soooooo much easier!
I should have been using transition instead of animation. As that give me the flexibility to adjust the animation accordingly.
Hope it helps someone else to save couple hours!
http://codepen.io/adamchenwei/pen/xRqYNj
HTML
<div class="myItem">
stuff here
</div>
CSS
.myItem {
position: absolute;
height: 100px;
width: 501px;
background-color: beige;
transition: transform 1s;
}
JS
setTimeout(function() {
document.getElementsByClassName('myItem')[0].style.transform="translateX(400px)";
console.log('ran');
}, 3000);
EDIT
Below is a method sugguested by Dennis Traub
setTimeout(function() {
console.log('ran');
$("head").append('<style type="text/css"></style>');
var new_stylesheet = $("head").children(':last');
new_stylesheet.html('.myItem{animation: to-left-transition 600ms;}');
}, 3000);
.myItem {
position: absolute;
height: 100px;
width: 501px;
background-color: beige;
animation-iteration-count: 1;
animation-fill-mode: forwards;
animation-timing-function: ease-in-out;
}
#keyframes to-left-transition {
0% {
transform: translate(0);
}
100% {
transform: translate(100%);
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="item" class="myItem">
stuff here
</div>
Answer Before EDIT
Here is a good reference for something similar to what i think you are trying to accomplish.
Based on your dynamic input you could have a function that controls how far the div transitions. Still use your code for transition in the css, but compute how far you want in the jquery or JavaScript. Then call the css transition for how far or long you want to transition.
var boxOne = document.getElementsByClassName('box')[0],
$boxTwo = $('.box:eq(1)');
document.getElementsByClassName('toggleButton')[0].onclick = function() {
if(this.innerHTML === 'Play')
{
this.innerHTML = 'Pause';
boxOne.classList.add('horizTranslate');
} else {
this.innerHTML = 'Play';
var computedStyle = window.getComputedStyle(boxOne),
marginLeft = computedStyle.getPropertyValue('margin-left');
boxOne.style.marginLeft = marginLeft;
boxOne.classList.remove('horizTranslate');
}
}
$('.toggleButton:eq(1)').on('click', function() {
if($(this).html() === 'Play')
{
$(this).html('Pause');
$boxTwo.addClass('horizTranslate');
} else {
$(this).html('Play');
var computedStyle = $boxTwo.css('margin-left');
$boxTwo.removeClass('horizTranslate');
$boxTwo.css('margin-left', computedStyle);
}
});
.box {
margin: 30px;
height: 50px;
width: 50px;
background-color: blue;
}
.box.horizTranslate {
-webkit-transition: 3s;
-moz-transition: 3s;
-ms-transition: 3s;
-o-transition: 3s;
transition: 3s;
margin-left: 100% !important;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h3>Pure Javascript</h3>
<div class='box'></div>
<button class='toggleButton' value='play'>Play</button>
<h3>jQuery</h3>
<div class='box'></div>
<button class='toggleButton' value='play'>Play</button>
This code was written by Zach Saucier on codepen
This is a good reference for manipulating css with JS: https://css-tricks.com/controlling-css-animations-transitions-javascript/
Naturally, we can create a CSS animation using keyframes, and control it from there.
However, ideally, I would like to trigger this animation from a button click - so the button click would be an event...
#keyframes fade-in {
0% {opacity: 0;}
100% {opacity: 1;}
}
Now, on click, I want to trigger this animation; as opposed to from within the CSS animation property.
see here jsfiddle
if you want your animation to work every time you press the button use this code :
$('button').click(function() {
$(".fademe").addClass('animated');
setTimeout(function() {
$(".fademe").removeClass('animated');
}, 1500);
});
where 1500 is the animation-duration in this case, 1.5s
$('button').click(function() {
$(".fademe").addClass('animated');
setTimeout(function() {
$(".fademe").removeClass('animated');
}, 1500);
});
.fademe {
width: 100px;
height: 100px;
background: red;
}
.fademe.animated {
animation: fade-in 1.5s ease;
}
#keyframes fade-in {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="fademe">
</div>
<button>CLICK ME</button>
EXPLANATION :
on click on the button add class animated ( or any other class ) to the element you want to apply the animation to , .fademe
make a setTimeout(function() to delay the removeClass for the duration of the animation 1.5s or 1500ms
write in CSS the declaration of the animation , #keyframes, and add it to the element with the class added by the JQ .fademe.animated
$("#move-button").on("click", function(){
$("#ship").removeClass("moving");
$("#ship")[0].offsetWidth = $("#ship")[0].offsetWidth;
$("#ship").addClass("moving");
});//
#ship
{
background: green;
color: #fff;
height: 60px;
line-height: 60px;
text-align: center;
width: 100px;
}
#move-button
{
margin-top: 20px;
}
#ship.moving
{
animation: moving 2s ease;
}
#keyframes moving
{
0%{ transform: translate(0px);}
50%{ transform: translate(20px);}
100%{ transform: translate(0px);}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="ship">Ship</div>
<button id="move-button">Push</button>
If you want to make the animation happen and always end before allowing the event listener to trigger it again, I would suggest to control the behaviour like this:
// Add this to your event listener
if (!element.classList.contains("myClass")) {
element.className = "myClass";
setTimeout(function() {
element.classList.remove("myClass");
}, 1000); //At least the time the animation lasts
}
There is a toggle method that works just fine for this, hope it helps:
function Fade() {
document.getElementById("box").classList.toggle("animate");
}
#box {
background-color: black;
height: 50px;
width: 50px;
}
.animate {
animation: fademe 0.5s;
}
#keyframes fademe {
from {
opacity: 1;
}
to {
opacity: 0;
}
}
<html>
<head>
<title>
Animation Trigger
</title>
</head>
<body>
<div id="box"></div>
<button onclick="Fade()"> Fade above Box</button>
</body>
I'll try to explain what I'm trying to do but I think checking out the jsfiddle link would make the point more clearly.
It's a number of phrases (HTML divs) stacked vertically on each other. When the button is clicked, the top phrase disappears while the lower phrases appear to slide up to take the place of the phrase previously above themselves.
Is there a better way to do this? It looks really ugly as it is.
EDIT: also note that the code only works once, then you have to hit 'run' again since the list of phrases is not infinite like in my actual application
https://jsfiddle.net/deddnbrh/1/
HTML:
<br>
<br>
<br>
<div id="phrase1" style="font-size:50px;color:black">Phrase 1</div>
<div id="phrase2" style="font-size:25px;color:gray">Phrase 2</div>
<div id="phrase3" style="font-size:25px;color:gray">Phrase 3</div>
<div id="phrase4" style="font-size:25px;color:gray;opacity:0">Phrase 4</div>
<br>
<br>
<br>
<button id="button" onclick="myFunc2()" onmousedown="myFunc()">CLICK ME</button>
javascript:
document.getElementById('phrase2').addEventListener("webkitAnimationEnd", switchPhraseText);
function switchPhraseText() {
document.getElementById('phrase1').innerHTML = "Phrase 2";
document.getElementById('phrase2').innerHTML = "Phrase 3";
document.getElementById('phrase3').innerHTML = "Phrase 4";
document.getElementById('phrase4').innerHTML = "Phrase 5";
}
function myFunc2() {
document.getElementById('phrase1').style.webkitAnimationName = 'phrase1Anim';
document.getElementById('phrase2').style.webkitAnimationName = 'phrase2Anim';
document.getElementById('phrase3').style.webkitAnimationName = 'phrase3Anim';
document.getElementById('phrase4').style.webkitAnimationName = 'phrase4Anim';
}
function myFunc() {
document.getElementById('phrase1').style.webkitAnimationName = "";
document.getElementById('phrase2').style.webkitAnimationName = "";
document.getElementById('phrase3').style.webkitAnimationName = "";
document.getElementById('phrase4').style.webkitAnimationName = "";
}
css:
#phrase1 {
position: relative;
-webkit-animation-duration: .8s;
}
#phrase2 {
position: relative;
-webkit-animation-duration: 1s;
}
#phrase3 {
position: relative;
-webkit-animation-duration: 1s;
}
#phrase4 {
position: relative;
-webkit-animation-duration: 1s;
}
#-webkit-keyframes phrase1Anim {
0% {left:0px;}
100% {left:250px; opacity:0}
}
#-webkit-keyframes phrase2Anim {
0% {font-size:25px; top:0px;}
100% {color:black; font-size:50px; top:-50px;}
}
#-webkit-keyframes phrase3Anim {
0% {top:0px;}
100% {top:-50px;}
}
#-webkit-keyframes phrase4Anim {
0% {top:0px;}
100% {top:-50px; opacity:1;}
}
This will support an indefinite amount of elements inside of the list. Of course, it's not perfect, and you have to tweak it to your needs, but hopefully it'll get you started. The code is pretty self explanatory, I think.
This will only work with Chrome, in its current state, but for it to work in other browsers, all you need to do is add the relevant vendor-prefixes to the CSS rules and to the animation events. For multi-browser support, just add the relevant CSS fallbacks and listener fixes.
It animates (right/fade-out) the element with class active
It clones said element and pushes it to the bottom, fading it in.
It removes the clone and appends the original one (as the clone was just for aesthetics)
It animates (up, font-size, color) the element next to active.
jsFiddle for Chrome
jsFiddle for Firefox (apparently, FF is awesome and doesn't need vendor prefixes).
Finally, this is the Chrome version in snippet form:
var phrases = document.getElementById('phrases'),
next = document.getElementById('next'),
ongoing = false;
function animList() {
var active = document.getElementsByClassName('active')[0],
next = active.nextElementSibling,
clone;
if(ongoing) return;
ongoing = true;
function animationStart() {
clone = this.cloneNode(true);
clone.id = '_tmp';
clone.className = '';
clone.style.transition = 'opacity 1s';
clone.style.opacity = '0';
setTimeout(function () { clone.style.opacity = '1' }, 50);
phrases.appendChild(clone);
this.removeEventListener('webkitAnimationStart', animationStart);
}
function animationEnd() {
clone.parentNode.removeChild(clone);
phrases.appendChild(active);
this.classList.remove('active', 'animActive', 'slideUp');
this.removeEventListener('webkitAnimationEnd', animationEnd);
this.removeEventListener('webkitAnimationStart', animationStart);
next.classList.remove('slideUp');
next.classList.add('active');
ongoing = false;
}
active.classList.add('animActive');
next.classList.add('slideUp');
active.addEventListener('webkitAnimationStart', animationStart);
active.addEventListener('webkitAnimationEnd', animationEnd);
}
next.onclick = animList;
#next {
position: relative;
display: inline-block;
top: 2.5em;
background: transparent;
border: 0;
font-size: 2em;
}
#phrases {
display: inline-block;
vertical-align: top;
max-height: 11em;
}
#phrases div {
font-size: 2em;
color: gray;
position: relative;
}
#phrases div.active {
font-size: 3em;
color: black;
}
.animActive {
-webkit-animation: animActive 1s ease-in-out;
}
.slideUp {
-webkit-animation: slideUp 1s;
}
#phrases div.slideUp ~ div:nth-child(n+3) {
-webkit-animation: slideUpRest 1s;
}
#-webkit-keyframes animActive {
0% {
left: 0;
}
100% {
left: 4em;
opacity: 0
}
}
#-webkit-keyframes slideUp {
0% {
top: 0;
}
100% {
top: -1.15em;
font-size: 3em;
color: black;
}
}
#-webkit-keyframes slideUpRest {
0% {
top: 0;
}
100% {
top: -1.7em;
}
}
<link href="//maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css" rel="stylesheet"/>
<div id="phrases">
<div id="phrase1" class="active">Phrase 1</div>
<div id="phrase2">Phrase 2</div>
<div id="phrase3">Phrase 3</div>
<div id="phrase4">Phrase 4</div>
<div id="phrase5">Phrase 5</div>
</div>
<button id="next">
<i class="fa fa-angle-right"></i>
</button>