How to trigger CSS animation [duplicate] - javascript

This question already has answers here:
Restart animation in CSS3: any better way than removing the element?
(14 answers)
Closed 4 years ago.
I am new to CSS but do know the basics, I want to trigger this animation by using a button. I cannot get it to work.
I used a couple of examples here in Stackoverflow, Jquery, Jscript, but none seem to refer to the #keyframes .
I see more about referring to an animation via classes and removing classes (As I understand this way to restart the animation by removing the element). I tried switching it to classes.
I also then wonder what is best practise?
What is the best way? I thought it would be simple, but I was mistaken.....
I have CSS like so:
#test {
margin-left: 20px;
margin-top: 20px;
width: 50px;
height: 0px;
background: maroon;
position: absolute;
animation-name: example;
animation-duration: 3s;
animation-fill-mode: forwards;
animation-delay: 0s;
}
#keyframes example {
from { transform: translateY(200px)}
to {height: 200px; background-color: teal;}
}

I am unable to reproduce the issue you described with your CSS.
See sample below:
This answer will be deleted once the question is edited with a mcve.
Please note:
If you question is about best practices, then it'd be off-topic for StackOverflow. See our how to ask page
$(function() {
$("#test-btn").on('click', function() {
$("#test").addClass('animation');
});
});
.animation {
margin-left: 20px;
margin-top: 20px;
width: 50px;
height: 0px;
background: maroon;
position: absolute;
animation-name: example;
animation-duration: 3s;
animation-fill-mode: forwards;
animation-delay: 0s;
}
#keyframes example {
from {
transform: translateY(200px)
}
to {
height: 200px;
background-color: teal;
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="test-btn">Animate</button>
<hr/>
<div id="test"></div>

In case you decide to scrap jQuery (or you have to work without it), in order to toggle the CSS animation on your #test element using vanilla JavaScript, separate your animation-related CSS properties into a class:
.animate {
animation-name: example;
animation-duration: 3s;
animation-fill-mode: forwards;
animation-delay: 0s;
}
Then toggle (add/remove) the .animate class on the #test element:
button.addEventListener('click', function() {
if (isAnimating) {
element.classList.remove('animate');
button.innerHTML = 'Add animation';
} else {
element.classList.add('animate');
button.innerHTML = 'Remove animation';
}
isAnimating = !isAnimating;
});
var element = document.getElementById('test');
var button = document.getElementById('toggle');
var isAnimating = false;
button.addEventListener('click', function() {
if (isAnimating) {
element.classList.remove('animate');
button.innerHTML = 'Add animation';
} else {
element.classList.add('animate');
button.innerHTML = 'Remove animation';
}
isAnimating = !isAnimating;
});
#test {
margin-left: 20px;
margin-top: 20px;
width: 50px;
height: 0px;
background: maroon;
position: absolute;
}
.animate {
animation-name: example;
animation-duration: 3s;
animation-fill-mode: forwards;
animation-delay: 0s;
}
#toggle {
margin-left: 100px;
}
#keyframes example {
from {
transform: translateY(200px)
}
to {
height: 200px;
background-color: teal;
}
}
<div id="test"></div>
<button id="toggle">Add animation</button>

Related

Toggle animation on click of button using js

I'm trying to get a square to 'fold out' on click of a button -- kind of like a drop-down.
Right now I have this, but it doesn't seem to do anything...
function toggle() {
let classList = document.getElementById('box').classList;
if (classList.contains('expand')) {
classList.remove('expand');
classList.add('retract');
} else if (classList.contains('retract')) {
classList.remove('retract');
classList.add('expand');
}
}
#keyframes anim {
0%: {
visibility: hidden;
}
1%: {
visibility: visible;
max-height: 0px;
}
100%: {
visibility: visible;
max-height: 100px; /* or something bigger than we'll 'ever need' */
}
}
.expand .retract {
animation-name: anim;
animation-duration: 500ms;
animation-iteration-count: 1;
}
.expand {
animation-fill-mode: forwards;
}
.retract {
animation-direction: reverse;
animation-fill-mode: backwards;
}
#box {
background-color: red;
height: 0px;
visibility: hidden;
width: 50px;
}
<button onclick="toggle()">toggle</button>
<div id="box"></div>
Note, that I need to have visibility: hidden here!
How can I achieve this?
OK, your problem is solved. This tryit from W3Schools helped me a lot. I didn't need two class names. Also, as #tao said, there is no point in animating visibility (look at the comments below). Here is the CodePen pen with this code. I guess this is what you want, am I right?
const toggle = () => box?.classList.toggle('expand')
#box.expand {
height: 100px;
}
#box {
width: 50px;
height: 0;
overflow: hidden;
background: red;
transition: height 1s;
}
<button onclick="toggle()">toggle</button>
<div id="box"></div>

How to set keyframes 50% using jquery(or javascript)?

I'm making time(second) bar.
When opening page, bar's width should be (second/60)*100%.
I want to start from 50% instead of the beginning.
Using jquery or javascript.
Please tell me about.
#loader {
width: 50%;
height: 5px;
background-color: #fff;
animation-name: loadingBar;
animation-duration: 60s;
animation-timing-function: steps(60, end);
animation-direction: normal;
animation-play-state: running;
animation-iteration-count: infinite;
#keyframes loadingBar {
0% {
width: 0%;
}
100% {
width: 100%;
}
}
Hi Could you try this overwrite the style existing.And also remove it if required to get old behavior
function setStyle() {
let st = document.createElement("style");
st.id="RemoveMeInFuture";
const stext=`#keyframes loadingBar {
50% {
width: 0%;
}
100% {
width: 100%;
}
}
.foo{background:red}`;
document.querySelector("head").appendChild(st);
if (st.styleSheet){
// This is required for IE8 and below.
st.styleSheet.cssText = stext;
} else {
st.appendChild(document.createTextNode(stext));
}
}

Fade the same image in and out in one line of CSS automatically

I have an image that I want to fade in and out automatically. I've read about transitions and animations and would like to use one or two styles (not style declarations). It's OK to start the animation via JavaScript.
In this example on MDN you can see that the items are animated on page load by switching classes. I would like it to be simpler than that.
Here is what I have so far and it seems like it should work but it's not.
function updateTransition(id) {
var myElement = document.getElementById(id);
var opacity = myElement.style.opacity;
if (opacity==null || opacity=="") opacity = 1;
myElement.style.opacity = opacity==0 && opacity!="" ? 1 : 0;
}
var id = window.setInterval(updateTransition, 5000, "myElement");
updateTransition("myElement");
#myElement {
background-color:#f3f3f3;
width:100px;
height:100px;
top:40px;
left:40px;
font-family: sans-serif;
position: relative;
animation: opacity 3s linear 1s infinite alternate;
}
<div id="myElement"></div>
Also, here is an example of an animation on infinite loop using a slide animation (3 example in the list). I'd like the same but with opacity.
https://developer.mozilla.org/en-US/docs/Web/CSS/animation
The linked question is not the same as this. As I stated, "single line styles (not style declarations)".
What you need is to define your animation using keyframes. If you are trying to apply multiple animations, you can provide a list of parameters to the animation CSS properites. Here's an example that applies a slide in and fade animation.
.fade {
width:100px;
height:100px;
background-color:red;
position:relative;
animation-name:fadeinout, slidein;
animation-duration:2s, 1s;
animation-iteration-count:infinite, 1;
animation-direction:alternate, normal;
}
#keyframes fadeinout {
0% {
opacity:0
}
100% {
opacity:100
}
}
#keyframes slidein {
from {
left:-100px;
}
to {
left:0px;
}
}
<div class='fade'>
</div>
You can use animation-iteration-count :
#myElement {
background-color: #f3f3f3;
width: 100px;
height: 100px;
top: 40px;
left: 40px;
font-family: sans-serif;
position: relative;
animation: slidein 2s linear alternate;
animation-iteration-count: infinite;
}
#keyframes slidein {
0% {
opacity: 0;
left: -100px;
}
50% {
opacity: 1;
left: 40px;
}
100% {
opacity: 0;
left: -100px;
}
}
<div id="myElement"></div>

How to control the transform distance with pure JavaScript

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/

How to set 0% css of keyframes as current css value for the element?

I am trying to make a progress indicator div using CSS animations. Please refer to the linked JSBin. The behavior I am trying to achieve is, when the user clicks on stage3 after stage1, the div width should increase from current 30% to 100% and not start from 0% as it is doing right now. I know if i set the 0% value as width: 30%, I can get that. But it won't work so well if I have many stages. I want the animation to start from final width of last stage to the width specified in new stage.
Progress indicator snippet
document.getElementById('stage1').addEventListener('click', function() {
document.getElementById('progress').classList.add('stage1');
}, false);
document.getElementById('stage2').addEventListener('click', function() {
document.getElementById('progress').classList.add('stage2');
}, false);
document.getElementById('stage3').addEventListener('click', function() {
document.getElementById('progress').classList.add('stage3');
}, false);
.progress-wrapper {
height: 10px;
width: 400px;
background-color: #BBDEFB;
}
#progress {
background-color: #AADE00;
height: 10px;
width: 0;
}
.stage1 {
animation-name: stage1;
animation-duration: 1s;
animation-fill-mode: forwards;
}
#keyframes stage1 {
to {
width: 30%;
}
}
.stage2 {
animation-name: stage2;
animation-duration: 1s;
animation-fill-mode: forwards;
}
#keyframes stage2 {
to {
width: 70%;
}
}
.stage3 {
animation-name: stage3;
animation-duration: 1s;
animation-fill-mode: forwards;
}
#keyframes stage3 {
to {
width: 100%;
}
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JS Bin</title>
</head>
<body>
<div class="progress-wrapper">
<div id="progress"></div>
</div>
<pre>
</pre>
<button id="stage1">stage1</button>
<button id="stage2">stage2</button>
<button id="stage3">stage3</button>
</body>
</html>
I'm not aware of a CSS-only solution, but you could set the width of the progress element before adding the class.
In doing so, it will transition from the previous width rather than from 0.
var progress = document.getElementById('progress');
document.getElementById('stage1').addEventListener('click', function() {
setPreviousWidth();
progress.classList.add('stage1');
}, false);
document.getElementById('stage2').addEventListener('click', function() {
setPreviousWidth();
progress.classList.add('stage2');
}, false);
document.getElementById('stage3').addEventListener('click', function() {
setPreviousWidth();
progress.classList.add('stage3');
}, false);
function setPreviousWidth () {
progress.style.width = progress.offsetWidth + 'px';
}
.progress-wrapper {
height: 10px;
width: 400px;
background-color: #BBDEFB;
}
#progress {
background-color: #AADE00;
height: 10px;
width: 0;
}
.stage1 {
animation-name: stage1;
animation-duration: 1s;
animation-fill-mode: forwards;
}
#keyframes stage1 {
to {
width: 30%;
}
}
.stage2 {
animation-name: stage2;
animation-duration: 1s;
animation-fill-mode: forwards;
}
#keyframes stage2 {
to {
width: 70%;
}
}
.stage3 {
animation-name: stage3;
animation-duration: 1s;
animation-fill-mode: forwards;
}
#keyframes stage3 {
to {
width: 100%;
}
}
<div class="progress-wrapper">
<div id="progress"></div>
</div>
<pre>
</pre>
<button id="stage1">stage1</button>
<button id="stage2">stage2</button>
<button id="stage3">stage3</button>

Categories