Stop CSS animation on second time page load - html

I am adding an this animation to a favorite button, which is working fine but when I reload the page then the animation once again runs and which is creating disturbance on listing page. So how can I control or stop the animation on page reload if the favorite button is clicked once and thing has become favorite.
CSS Code:
.event_box .eb_like i:after{
content: "";
position: absolute;
left: 0;
right: 0;
top: 0;
margin: 0 auto;
background: url(../img/alike.svg) 0 0 no-repeat;
background-size: 2900%;
height: 100px;
width: 100px;
}
.event_box .eb_like i.like:after{
-webkit-animation: heart-burst steps(28) 0.8s 1 both;
animation: heart-burst steps(28) 0.8s 1 both;
}
#-webkit-keyframes heart-burst {
0% {
background-position: left;
}
100% {
background-position: right;
}
}
#keyframes heart-burst {
0% {
background-position: left;
}
100% {
background-position: right;
}
}

Actually, one possible solution is to store a key in browser's local storage. You can do something like that:
https://jsfiddle.net/pablodarde/vojrcoa4/
var btn = document.getElementsByClassName('btn-love')[0];
btn.addEventListener('click', function(e) {
if (!window.localStorage.getItem('favorited')) {
setTimeout(function() {
document.getElementsByClassName('love')[0].setAttribute('id', '');
window.localStorage.setItem('favorited',true);
},1000);
}
});

no way you can do that by css only, there are two ways both involving some coding:
(easy) you can set a cookie via js and use it to check if that
element has been clicked
(over complicated) if the user is logged in you can save that action in a database and when he reload the page you check the db and print the appropriate class

Related

trigger CSS animations onlcick

I have created an animation for an element on my page and it always runs when the page is refreshed but i would like the animation to play when an element is clicked. How would i go about doing this?
CSS:
#login-or-signup-selection {
display: flex;
animation-name: test;
animation-duration: 5s;
position: relative;
height: 70%;
}
#keyframes test {
0% {top: 0px;}
50% {top:300px}
100% {top: 0;}
}
HTML:
<p id="clickMe">Element to click</p>
$('#clickMe').click(function () {
$(this).addClass('login-or-signup-selection');
$(this).on("animationend", function(event) {
$(this).removeClass('login-or-signup-selection')
});
});
.login-or-signup-selection {
display: flex;
animation-name: test;
animation-duration: 5s;
position: relative;
height: 70%;
}
#keyframes test {
0% {top: 0px;}
50% {top:300px}
100% {top: 0;}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<p id="clickMe">Element to click</p>
If you want only css and don't even care about js onclick events for now,
use the :active pseudo selector.
The only downside is that it only plays while (=during) e.g. the mouse button is down.
You would need some JavaScript for this.
First off, separate the CSS animation properties, and anything else related to your animation, and add them to their own class.
Next up, the JavaScript. You'll want to add an event listener to your element to add the animation class when clicked, and a timeout to remove the class afterwards so it will animate when clicked again.
const yourElement = document.getElementById('clickMe');
yourElement.addEventListener('click', _=> {
yourElement.classList.add('animation-class');
setTimeout(
_=> yourElement.classList.remove('animation-class'),
5000
)
});
#clickMe {
display: flex;
position: relative;
height: 70%;
}
.animation-class {
animation-name: test;
animation-duration: 5s;
}
#keyframes test {
0% { top: 0px; }
50% { top: 300px; }
100% { top: 0; }
}
<p id="clickMe">Element to click</p>
You need JavaScript for this.
If you add an event listener on the p element to listen for a click, this can then add the animation name to the selection div.
But you need to also listen for the end of the animation, otherwise subsequent clicks will have no effect. On animation end this snippet removes the animation name.
Note also that in order to be absolutely sure that the first (onload) animation end is trapped, the first animation name is not set until the event listeners have been set up.
function init() {
const clickMe = document.querySelector('#clickMe');
const selection = document.querySelector('#login-or-signup-selection');
clickMe.addEventListener('click', function() {
selection.style.animationName = 'test';
});
selection.addEventListener('animationend', function() {
selection.style.animationName = '';
});
selection.style.animationName = 'test';
}
window.onload = init;
#login-or-signup-selection {
display: flex;
animation-duration: 5s;
animation-iteration-count: 1;
position: relative;
height: 70%;
}
#keyframes test {
0% {
top: 0px;
}
50% {
top: 300px
}
100% {
top: 0;
}
}
<p id="clickMe">Element to click</p>
<div id="login-or-signup-selection">Login or signup selection</div>

Ken Burns Slideshow Modification

I found a slideshow on Codepen that looks like: https://codepen.io/wh1zk1d/pen/WRJjLd
I like this one, but I just wanted the image with the Ken Burns effect, so I simplified the code:
The beauty of this code, is it's very simple :-)
#slides {
background: #000;
height: 450px;
overflow: hidden;
width: 100%;
}
#slides div {
animation: ken-burns 3s ease-out;
animation-fill-mode: both;
background-position: center center;
background-repeat: no-repeat;
background-size: cover;
height: 100%;
width: 100%;
}
#keyframes ken-burns {
from {
transform: scale(1.2);
} to {
transform: scale(1);
}
}
<div id="slides">
<div style="background-image: url('https://images.unsplash.com/photo-1491609154219-ffd3ffafd992?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=2250&q=80')"></div>
</div>
I have this working on all of my inner pages for a website I am creating, but what I'd like to do on the homepage is use the same concept, with a few modifications, to create a multi-image (4) slideshow...
The way it works right now, is it loads one image and then when the animation completes, it stops. This works great of the inner pages, but on the homepage it'd be nice if this cycled in an infinite continuous loop.
I tried to add another div with a different background image, but the code still works the same way. Loads the image in the first div, then stops.
I'm pretty sure this is a simple tweak, but could someone help me adjust what I'm already using to get multiple images (4) to work, along with a infinite continuous loop of those images?
Thanks,
Josh
So, I found some JS that helped me get this working :-)
The CSS has some minor adjustments...
#slides {
background: #000;
height: 450px;
overflow: hidden;
width: 100%;
}
#slides div.current {
animation: ken-burns 3s forwards;
animation-fill-mode: both;
background-position: center center;
background-repeat: no-repeat;
background-size: cover;
height: 100%;
width: 100%;
}
#keyframes ken-burns {
0% {
opacity: 0;
transform: scale(1.2);
}
15% {
opacity: 1;
}
85% {
opacity: 1;
}
100% {
opacity: 0;
transform: scale(1);
}
}
The HTML looks a little different as well...
<div id="slides">
<div class="ini" data-imagenum="1" style="background-image: url('https://images.unsplash.com/photo-1497752531616-c3afd9760a11?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=2700&q=80'); z-index: -1"></div>
<div class="" data-imagenum="2" style="background-image: url('https://images.unsplash.com/photo-1437622368342-7a3d73a34c8f?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1920&q=80'); z-index: -2"></div>
<div class="" data-imagenum="3" style="background-image: url('https://images.unsplash.com/photo-1486365227551-f3f90034a57c?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=2700&q=80'); z-index: -3"></div>
<div class="" data-imagenum="4" style="background-image: url('https://images.unsplash.com/photo-1425082661705-1834bfd09dca?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=2710&q=80'); z-index: -4"></div>
</div>
Then I added some JS...
$(document).ready(function () {
if ($('#slides div').length){
$('.ini').addClass('current');
var numImages = $('#slides div').length;
var i = 1;
$('body').on('webkitAnimationEnd oanimationend msAnimationEnd animationend', '.current', function() {
i ++;
$('.current').removeClass('current');
if ( i <= numImages ) {
$('*[data-imagenum="' + i +'"]').addClass('current');
} else {
i = 1;
$('*[data-imagenum="' + i +'"]').addClass('current');
}
});
}
});
This was as close to my original code as I could get!
Here is the Codepen: https://codepen.io/joshrodgers/pen/ZEQjZNr

Remove/Hide div from DOM after animation completes using CSS?

I have an animation where a div slides out the view, however when the animation is completed, the div just returns to its origin position in the view. How do I totally remove the div or hide it after the animation ends using just CSS?
Here is the markup:
<div class="container">
<div class="slide-box" id="slide-box""></div>
</div>
and the css:
.slide-box {
position: relative;
width: 100px;
height: 100px;
background-image: url(../pics/red.png);
background-position: center;
background-size: cover;
background-repeat: no-repeat;
animation: slide 5s linear 1;
}
#keyframes slide {
0% {
left: 0;
}
20% {
left: 20%;
}
40% {
left: 40%;
}
60% {
left: 60%;
}
80% {
left: 80%;
}
100% {
left: 100%;
overflow: hidden;
visibility: hidden;
}
}
I don't want it to fade out over the duration of the animation, i just want it to disappear once it hits 100% in the keyframe. Thanks ahead of time!
Use the animation-fill-mode option. Set it to forwards and the animation ends at it's final state and stay like that.
Altered based upon comments Set opacity fade to just last 1% of animation... simplified keyframes. Added a jquery option to literally remove the div from the DOM. CSS alone won't alter the markup, where jQuery will.
Although you can't animate the display property. If you want the div totally gone, after the opacity fades to zero, you can then add the display property to remove the div. If you don't wait for opacity to end, the div will just vanish without any transition.
/*
This jquery is added to really remove
the div. But it'll essentially be
VISUALLY gone at the end of the
animation. You can not use, or
delete the jquery, and you really
won't see any difference unless
you inspect the DOM after the animation.
This function is bound to animation
and will fire when animation ends.
No need to "guess" at timeout settings.
This REMOVES the div opposed to merely
setting it's style to display: none;
*/
$('.slide-box').bind('animationend webkitAnimationEnd oAnimationEnd MSAnimationEnd', function(e) { $(this).remove(); });
.slide-box {
display: block;
position: relative;
left: 0%;
opacity: 1;
width: 100px;
height: 100px;
background: #a00;
animation: slide 1s 1 linear forwards;
/*
animation-name: slide;
animation-duration: 1s;
animation-iteration-count: 1;
animation-timing-function: linear;
animation-fill-mode: forwards;
*/
}
#keyframes slide {
0% {
left: 0%;
opacity: 1;
}
99% {
left: 99%;
opacity: 1;
}
100% {
left: 100%;
opacity: 0;
display: none;
}
}
#-webkit-keyframes slide {
0% {
left: 0%;
opacity: 1;
}
99% {
left: 99%;
opacity: 1;
}
100% {
left: 100%;
opacity: 0;
display: none;
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<div class="slide-box" id="slide-box"></div>
</div>
animation: slide 5s linear forwards;
at 100%
opacity: 0;
display: none;
Try this.
Working fiddle: https://jsfiddle.net/jbtfdjyy/1/
UPDATE: JS mani
var slideBox = document.getElementById('slide-box');
setTimeout(function(){
slideBox.style.display = 'none';
}, 5000);
Try this. https://jsfiddle.net/jbtfdjyy/2/
Add something at 99% or so to your keyframes, and set opacity to 1 in that. If you have opacity: 1 at the start, then it will stay that way until 99%. Only at 100% will it change.
It's not technically fired at 100%. If you want that, I'd recommend using some JavaScript here, but this will at least give the illusion you want.
#keyframes slide {
0% {
left: 0;
}
20% {
left: 20%;
}
40% {
left: 40%;
}
60% {
left: 60%;
}
80% {
left: 80%;
}
99% {
opacity: 1;
}
100% {
left: 100%;
overflow: hidden;
opacity: 0;
display: none;
visibility: hidden;
}
}
UPDATE:
As per your request, here is a JavaScript version. Keep in mind, there are endless ways to accomplish such a task. I am using vanilla JS (no jQuery, etc.), and using ES6 syntax.
What we do here is set a timeout, and at the end of that timeout I broadcast an event animation_end. That event listener will handle the end of the animation (in this case, it adds a class which will handle the fading out). This is much more granular than you need it to be, you could simply do the adding of the class within the setTimeout, but I think it is slightly better this way as you can abstract you can do other things with events such as animation start, etc.
Here is the fiddle: https://jsfiddle.net/vmyzyd6p/
HTML:
<div class="container">
<div class="slide-box" id="slide-box""></div>
</div>
CSS:
.slide-box {
position: relative;
width: 100px;
height: 100px;
background-color: blue;
animation: slide 3s linear 1;
-webkit-transition: opacity 2s ease-in-out;
-moz-transition: opacity 2s ease-in-out;
transition: opacity 2s ease-in-out;
}
.animationEnd {
opacity: 0;
}
#keyframes slide {
0% {
left: 0;
}
20% {
left: 20%;
}
40% {
left: 40%;
}
60% {
left: 60%;
}
80% {
left: 80%;
}
100% {
left: 100%;
}
}
JavaScript:
// Create a function that handles the `animation_end` event
const animationEnd = () => {
// Grab the slidebox element
let slideBox = document.getElementById('slide-box');
// Get the class of the slidebox element
let slideClass = slideBox.getAttribute('class');
// Add the animation end class appended to the previous class
slideBox.setAttribute('class', slideClass + ' animationEnd');
};
// Create the animation end event
let animationEndEvent = new Event('animation_end');
// Cross browser implementation of adding the event listener
if (document.addEventListener) {
document.addEventListener('animation_end', animationEnd, false);
} else {
document.attachEvent('animation_end', animationEnd);
}
// Set the timeout with the same duration as the animation.
setTimeout(() => {
// Broadcast the animation end event
document.dispatchEvent(animationEndEvent);
}, 3000);

CSS Animation won't apply for the second time

I am currently having a problem with CSS animations. A random background is called from an array, shows up and changes and so on. I applied two animation for the image caption id, a slide in and a delayed slide out. The slide in and out runs well for the first time, but when the second background shows up, the caption just appears to the screen without any animation.
This is my test page and below is my code.
HTML code:
<script type="text/javascript">
function loadRandomImage(imgs) {
var index = Math.floor(Math.random() * imgs.length);
console.log("loadRandomImages(): index = "+ index);
$.backstretch(imgs[index].url, {duration: 30000, fade: 1200});
$("#caption").html(imgs[index].caption);
}
var images = new Array(); //array of imgs objects
images[0] = {url: "https://s-media-cache-ak0.pinimg.com/736x/a5/47/45/a5474577f4a4ae93c85db719d0cbafd4.jpg", caption: "Caption0"};
images[1] = {url: "https://s-media-cache-ak0.pinimg.com/736x/e6/41/74/e64174e355f78a0f07e951bcec62ca96.jpg", caption: "Caption1"};
images[2] = {url: "https://media.giphy.com/media/3o7abHrsGbV10rCeze/giphy.gif", caption:"Caption2"};
images[3] = {url: "https://media.giphy.com/media/Bbt5FxRiArl3a/giphy.gif", caption:"Caption3"};
// Preload
setTimeout(loadRandomImage, 1000, images);
// Change images every 3 seconds
setInterval(loadRandomImage, 30000, images);
</script>
<div id="pattern"></div>
<div id="pattern2"></div>
<div id="caption"></div>
CSS code:
#caption {
position: relative;
font: 1.5em Trebuchet, sans-serif;
text-align: center;
margin-left: 75%;
z-index: 56;
color: #ffffff;
background: rgba(0, 0, 0, 0.7);
padding: 8px;
animation: slidein 3s, slideout 3s 27s;
}
#caption:empty
{
display: none;
}
#keyframes slidein {
0% {
margin-left: 100%;
width:100%;
visibility:hidden;
opacity: 0;
}
100% {
margin-left: 75%;
width:100%;
opacity: 1;
visibility:visible;
}
}
#keyframes slideout {
0% {
margin-left: 75%;
width:100%;
opacity: 1;
visibility:visible;
}
100% {
margin-left: 100%;
width:100%;
opacity:0;
visibility:hidden;
}
}
CSS animations have iteration count (animation-iteration-count) as only 1 when no value is given for that property. Here since you've not specified any value, the animation executes only once (that is on page load). There is no pure CSS way to re-trigger an animation once it has completed its cycle. It has to be removed from the element and then re-attached for it to start all over again.
So, for your case here is what you have to do - (a) Set the animations on #caption using JS on page load as it makes it easier to remove and re-add them (b) Upon completion of the slideout animation, remove both the animations from the element (that is, set animation-name: none) and also set html of #caption to none because :empty selector would only then hide it. (c) As soon as the next image is set on the element (using loadRandomImage function), set the animations back on the element. This would re-trigger the animation and so during each image switch, the caption would slide-in and out.
Note: I've changed some parts in the HTML and JS that are not relevant to this answer (like removing the two div and replacing them with 1, avoiding the $.backstretch and loading image using css() etc. But these are only auxiliary items and will not affect the crux of this answer (which is, to remove and add the animations).
function loadRandomImage(imgs) {
var index = Math.floor(Math.random() * imgs.length);
$('#img').css('background-image', 'url(' + images[index].url + ')');
$('#caption').css({
'animation-name': 'slidein, slideout',
'animation-duration': '3s, 3s',
'animation-delay': '0s, 7s'
});
$("#caption").html(imgs[index].caption);
}
var images = new Array(); //array of imgs objects
images[0] = {
url: "http://lorempixel.com/100/100/nature/1",
caption: "Caption0"
};
images[1] = {
url: "http://lorempixel.com/100/100/nature/2",
caption: "Caption1"
};
images[2] = {
url: "http://lorempixel.com/100/100/nature/3",
caption: "Caption2"
};
images[3] = {
url: "http://lorempixel.com/100/100/nature/4",
caption: "Caption3"
};
// Preload
setTimeout(loadRandomImage, 1000, images);
$('#caption').on('animationend', function(e) {
if (e.originalEvent.animationName == 'slideout') {
$('#caption').css('animation-name', 'none');
$('#caption').html('');
setTimeout(function() { /* dummy timeout to make sure browser sees animation as none before adding it again */
loadRandomImage(images);
}, 0);
}
});
#caption {
position: relative;
font: 1.5em Trebuchet, sans-serif;
text-align: center;
margin-left: 75%;
z-index: 56;
color: #ffffff;
background: rgba(0, 0, 0, 0.7);
padding: 8px;
}
#caption:empty {
display: none;
}
#keyframes slidein {
0% {
margin-left: 100%;
width: 100%;
visibility: hidden;
opacity: 0;
}
100% {
margin-left: 75%;
width: 100%;
opacity: 1;
visibility: visible;
}
}
#keyframes slideout {
0% {
margin-left: 75%;
width: 100%;
opacity: 1;
visibility: visible;
}
100% {
margin-left: 100%;
width: 100%;
opacity: 0;
visibility: hidden;
}
}
/* Just for demo */
#img {
height: 100px;
width: 100px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="img"></div>
<div id="caption"></div>
The animationend event still requires vendor prefixes in some browsers.
You need to use a callback, which is explained here:
How do create perpetual animation without freezing?
I think the animation direction needs to be altered.
These are the possibilities:
animation-direction: normal|reverse|alternate|alternate-reverse|initial|inherit;
I think you need to do one of these:
alternate
The animation will be played as normal every odd time (1,3,5,etc..) and in reverse direction every even time (2,4,6,etc...)
alternate-reverse
The animation will be played in reverse direction every odd time (1,3,5,etc..) and in a normal direction every even time (2,4,6,etc...)
At the moment it is set as
animation-direction: initial, initial;
Seen here: http://www.w3schools.com/cssref/css3_pr_animation-direction.asp
Rather than the Javascript suggestions already provided, you could do a straight CSS solution.
Just set animation-iteration-count to "infinite" (to continuously alternate the 2 elements, or an integer for a set number of repeats)
If you want staggered / alternating animations:
Use an animation-delay (matching the animation-duration) on the second element so it doesn't appear until the first element animation has completed
Build a delay onto the end of your animation (revert to original state # 50%) so that the first element stays hidden while the second animates.

How can I make animation sprites (with rows and cols) work in firefox?

Example (you can modify and test): http://codepen.io/g-liu/pen/XbrMzr?editors=110
I've modified the code to work in Firefox, but the second animation seems to be skipping frames.
frames: http://www.fabiobiondi.com/blog/wp-content/uploads/2012/08/runningGrant.png
html:
<div id="guy-1" class="guy"></div>
<div id="guy-2" class="guy"></div>
Original sprite
css:
.guy {
height: 294px;
width: 165px;
display: inline-block;
background-image: url(http://www.fabiobiondi.com/blog/wp-content/uploads/2012/08/runningGrant.png);
}
#guy-1 {
animation: run-x 0.4s infinite steps(12);
}
#guy-2 {
animation: run-x 0.4s infinite steps(12), run-y 2.4s infinite steps(6);
}
#keyframes run-x {
from {
background-position: 0 0;
}
to {
background-position: -1980px 0;
}
}
#keyframes run-y {
from {
background-position: 0 0;
}
to {
background-position: 0 -1764px;
}
}
I've solved my problem using LESS (http://lesscss.org/)
It maked the css of animation in a generic way that worked in all browsers (even in mobile).