I am using animate.css and right now I have a CSS style for animated2500 which means it will take 2.5 seconds to animate. The style is:
.animated2500 {
-webkit-animation: 2500ms ease;
-moz-animation: 2500ms ease;
-ms-animation: 2500ms ease;
animation: 2500ms ease;
}
So in my HTML I would do:
<p class="animated2500 pulse">Takes 2.5 seconds to pulse</p>
There has to be an easier way to do this though, because I will want to specify how many seconds without creating a custom class for it each time.
Is there a way to use a custom data attribute like: <p data-delay="5000" class="fade">Fade in 5 econds</p> would that work?
How could I accomplish something like this?
Thanks!
I don't think you can use pure CSS for this, individual styles are the way to go.
If you really want to use a data-* attribute, since you've tagged your question jquery, I'll post a jQuery-specific answer although CSS animations and data attributes are not specific to jQuery (or even JavaScript):
jQuery(function($) {
$(".pulse[data-delay]").each(function() {
var value = parseInt(this.getAttribute("data-delay"), 10);
if (!isNaN(value)) {
value = value + "ms ease";
this.style["-webkit-animation"] = value;
this.style["-moz-animation"] = value;
this.style["-ms-animation"] = value;
this.style["animation"] = value;
}
});
});
That runs through the elements on DOM ready and applies the style directly. I don't like it for several reasons (not least that new elements added to the page post-load won't get handled), but if you really, really don't want to create specific classes...
maybe something like this will work? (untested)
$(document).ready(function() {
$("p[data-delay]").each(function(){
$(this).css('-webkit-animation',$(this).attr('data-delay')+'ms ease');
$(this).css('-moz-animation',$(this).attr('data-delay')+'ms ease');
$(this).css('-ms-animation',$(this).attr('data-delay')+'ms ease');
$(this).css('animation',$(this).attr('data-delay')+'ms ease');
}
);
});
$(document).ready(function() {
$("p[data-delay]").each(function(){
this.style.webkitAnimationDuration = $(this).attr('data-delay') + 's';
);
});
Related
I have a bar chart that animates with CSS3 and the animation currently activates as the page loads.
The problem I have is that the given bar chart is placed off screen due to lots of content before it so by the time a user scrolls down to it, the animation has already finished.
I was looking for ways either through CSS3 or jQuery to only activate the CSS3 animation on the bar chart when the viewer sees the chart.
<div>lots of content here, it fills the height of the screen and then some</div>
<div>animating bar chat here</div>
If you scroll down really fast right after page load, you can see it animating.
Here is a jsfiddle of my code. Also, I don't know if this matters, but I have several instances of this bar chart on the page.
I have come across a jQuery plug-in called waypoint but I had absolutely no luck getting it to work.
Capture scroll events
This requires using JavaScript or jQuery to capture scroll events, checking each time a scroll event fires to see if the element is in view.
Once the element is in view, start the animation. In the code below, this is done by adding a "start" class to the element, that triggers the animation.
Updated demo
HTML
<div class="bar">
<div class="level eighty">80%</div>
</div>
CSS
.eighty.start {
width: 0px;
background: #aae0aa;
-webkit-animation: eighty 2s ease-out forwards;
-moz-animation: eighty 2s ease-out forwards;
-ms-animation: eighty 2s ease-out forwards;
-o-animation: eighty 2s ease-out forwards;
animation: eighty 2s ease-out forwards;
}
jQuery
function isElementInViewport(elem) {
var $elem = $(elem);
// Get the scroll position of the page.
var scrollElem = ((navigator.userAgent.toLowerCase().indexOf('webkit') != -1) ? 'body' : 'html');
var viewportTop = $(scrollElem).scrollTop();
var viewportBottom = viewportTop + $(window).height();
// Get the position of the element on the page.
var elemTop = Math.round( $elem.offset().top );
var elemBottom = elemTop + $elem.height();
return ((elemTop < viewportBottom) && (elemBottom > viewportTop));
}
// Check if it's time to start the animation.
function checkAnimation() {
var $elem = $('.bar .level');
// If the animation has already been started
if ($elem.hasClass('start')) return;
if (isElementInViewport($elem)) {
// Start the animation
$elem.addClass('start');
}
}
// Capture scroll events
$(window).scroll(function(){
checkAnimation();
});
Sometimes you need the animation to always occur when the element is in the viewport.
If this is your case, I slightly modified Matt jsfiddle code to reflect this.
jQuery
// Check if it's time to start the animation.
function checkAnimation() {
var $elem = $('.bar .level');
if (isElementInViewport($elem)) {
// Start the animation
$elem.addClass('start');
} else {
$elem.removeClass('start');
}
}
You do not need to capture scroll events anymore
Since 2020, every browser is able to notify if an element is visible in your viewport.
With intersection observer.
I posted the code here:
https://stackoverflow.com/a/62536793/5390321
In order to activate a CSS animation, a class needs to be added to the element when this becomes visible. As other answers have indicated, JS is required for this and Waypoints is a JS script that can be used.
Waypoints is the easiest way to trigger a function when you scroll to
an element.
Up to Waypoints version 2, this used to be a relatively simple jquery plugin. In version 3 and above (this guide version 3.1.1) several features have been introduced. In order to accomplish the above with this, the 'inview shortcut' of the script can be used:
Download and add the script files from this link or from Github (version 3 is not yet available through CDNJS, although RawGit is always an option too).
Add the script to your HTML as usual.
<script src="/path/to/lib/jquery.waypoints.min.js"></script>
<script src="/path/to/shortcuts/inview.min.js"></script>
Add the following JS code, replacing #myelement with the appropriate HTML element jQuery selector:
$(window).load(function () {
var in_view = new Waypoint.Inview({
element: $('#myelement')[0],
enter: function() {
$('#myelement').addClass('start');
},
exit: function() { // optionally
$('#myelement').removeClass('start');
}
});
});
We use $(window).load() for reasons explained here.
Updated Matt's fiddle here.
In addition to these answers please consider these points :
1- Checking the element in view has many considerations :
How to tell if a DOM element is visible in the current viewport?
2- If someone wanted to have more control over the animation (e.g. set "the animation type" and "start delay") here is a good article about it :
http://blog.webbb.be/trigger-css-animation-scroll/
3- And also it seems that calling addClass without a delay (using setTimeout) is not effective.
CSS FOR TRIGGER :
<style>
.trigger{
width: 100px;
height: 2px;
position: fixed;
top: 20%;
left: 0;
background: red;
opacity: 0;
z-index: -1;
}
</style>
<script>
$('body').append('<div class="trigger js-trigger"></div>');
$(document).scroll(function () {
$('YOUR SECTIONS NAME').each(function () {
let $this = $(this);
if($this.offset().top <= $('.js-trigger').offset().top) {
if (!$this.hasClass('CLASS NAME FOR CHECK ACTIVE SECTION')) {
$this
.addClass('currSec')
.siblings()
.removeClass('currSec');
}
}
});
});
</script>
I have an image that when clicked should move a div up ~200px, I have it set through jquery to modify css without isssue but it doesn't look as 'clean' or smooth as i've seen on other websites.
Forgive me but i've been searching for a few hours and can't find the function/method to do this, I figured fadein/out would do this but i'm fairly sure it cannot.
Could anyone take a moment to point me in the right direction? Thank-you.
EDIT: After writing this I thought maybe I should quickly incrementally change the css via jquery to simulate a low-fps 'glide' .. hopefully there is an easier way
EDIT2: Currently use this, looking for a way to do it 'smoothly' if that even makes sense
$('#Table_Topbar').hide();
var pix = "px";
var fix = $('#Table_Middle1').css('top');
var fix2 = fix.replace('px','');
var fixsub = (fix2 - 200);
var fixstring = fixsub.toString();
var fixconca = fixstring.concat(pix);
$('#Table_Middle1').css('top',fixconca);
If you want to do this using only Javascript, you could also simply use an interval to update the css every xx number of milliseconds, for 60fps you'd use 16. (This is not the best way)
var i = parseInt($("#Table_Middle1").css("top"));
var animationLoop = setInterval(function() { i += 10; $("#Table_Middle1").css("top", i + "px"); }, 16);
A simpler way would be to use jQuery's animate api: http://api.jquery.com/animate/. (this is the most cross-browser friendly way)
$('#Table_Middle1").animate({top: "-=200px"}, 1000); // take 1 second to move up 200px
You could also use a CSS3 transition to accomplish the same thing, and reduce your JS to a simple class toggle (This is the most "modern" way)
jQuery:
$('#Table_Middle1").addClass("class-to-trigger-animation");
css:
#Table_Middle1 { top: 500px; transition: top 1s ease; }
#Table_Middle1.class-to-trigger-animation { top: 300px }
If you want more complex animations, you could consider a library like Greensock.
You could use a combination of js (jQuery) and CSS here, eg.
CSS:
.switch {position: absolute; top: 0; left: 0; transition: top 1s}
.switch.active {top: 160px}
jQuery:
$('.switch').click(function(){
$(this).toggleClass('active');
});
Check out the fiddle here: http://jsfiddle.net/pavkr/Lu7q2c1r/1/
You would need to adjust the parameters however, this is just a quick example.
I have a very strange issue. I'm loading articles from JSON in jQuery and as they load, I'd like to add a class of 'animate' to each dynamic element.
$.each(jsonArticles, function (i, article) {
var $articleHTML = $(
'<article class="article">' +
'<img src="' + jsonObject.imagePath + article.reviewImage + '" alt="">' +
'<h1>' + article.reviewTitle + '</h1>' +
'<p>' + article.reviewSummary + '</p>' +
'</article>');
$articles
.append($articleHTML)
.find("article")
.addClass("animate");
});
All of this works great and checking in Firebug reveals that the class is successfully added to each article tag.
However, when trying to use a CSS transition on the article for the class that's added, it does not animate, but instead skips straight to the final style (opacity: 1).
.article {
opacity: 0;
-webkit-transition: all 0.5s ease;
-moz-transition: all 0.5s ease;
-o-transition: all 0.5s ease;
transition: all 0.5s ease;
}
.article.animate {
opacity: 1;
}
The animation doesn't happen, but the class is added and the article is successfully set to opacity: 1. It shows up instantly.
Anyone have any ideas about this? I cannot figure this one out at all.
On another point, which is rather interesting...if I change the .animate class to have a :hover, then the articles won't show until I hover and the animation does work. Why it would work for hover and not when it's simply added immediately, seems strange to me.
.article.animate:hover {
opacity: 1;
}
I'd appreciate any input.
Thanks,
Mikey.
Live Demo: http://jsfiddle.net/Pz5CD/
Notice how the articles just pop in at 100% opacity. No animation is seen.
Update:
It turns out the OP wants to fade in each element sequentially, which is beyond the scope of the original question. I'll leave my answer here as an answer to the original question.
CSS animation won't trigger on addClass in jQuery
The issue is that your new html is added to the page and the animate class is added before the css for that html has been applied. The browser will skip ahead like that for the sake of efficiency. For example, if you added a class, then removed it, and repeated that process a hundred times, there wouldn't be a visual difference. It would have just skipped to the result. For this reason, you have to force a redraw on the element so that all previous styles have applied before adding the class. I wrote a function to handle this that should work in every circumstance on every browser, though there's no way to guarantee the behavior of a reDraw. It probably will always work and it's nice to have!
Live demo here (click). You can tell the reDraw is making the difference by commenting it out and just leaving the addClass().
$('body').append($articleHTML);
$a = $('body').find("article");
reDraw($a).then(function() {
$a.addClass("animate");
});
function reDraw($element) {
var deferred = new $.Deferred();
setTimeout(function() {
var h = $element[0].offsetHeight;
var s = $element[0].getComputedStyle;
deferred.resolve();
},0);
return deferred.promise();
}
The best way to force a redraw is to either access the offsetHeight or getComputedStyle of an element. However, there have been cases where those have failed for force a redraw on certain mobile devices. To add some extra encouragement for a redraw, I added a setTimeout as well. Even a time of 0 on the timeout will work, but it throws off the call stack, so I use a promise to ensure the next operation (adding your class) will happen after the redraw. That just means you'll use the syntax I demonstrated above to add the class - redraw($element).then(function() { //your code
For fun, I made a little demo of flipping classes with and without reDraw. http://jsbin.com/EjArIrik/1/edit
You need to add the class to the element after it is rendered to the dom, a set timout might work
setTimeout(function(){
$articleHTML.addClass("animate");
}, i * 500 );
http://jsfiddle.net/Pz5CD/1/
I'm not good with jQuery syntax as PHP is my thing.
I'm trying to produce a jQuery animation but with the correct vendor prefixes on multiple values, but my understanding of the usage of Modernizr.prefixed is letting me down.
What I'm trying to get is something like:
$('.rightbox3d').animate({
opacity: 1
,top:"60px"
,Modernizr.prefixed('transform'):"translateY(-200px)"
,Modernizr.prefixed('scale'):2
}, 4000);
ie. I want to include the vendor prefixes in the list of styles that are animated, but I get syntax error - unexpected token.
I have tried using
var transformProperty = Modernizr.prefixed ? Modernizr.prefixed('transform') : 'transform';
but it only allows listing that one style
ie: $(".rightbox3d").animate(transformProperty,"translateY(-200px)");
when what I want are multiple styles like transform, opacity, scale etc.
I notice that that line of code doesn't have brace brackets around the transformProperty part, whereas a list does
eg.
$('.rightbox3d').animate({
opacity: 1
,top:"-200px"
}, 4000, function() {
// Animation complete.
});
but I just can't get my head round it. Can anyone help?
So, you're going to have to make a big head leap. CSS Transitions are different than jQuery.animate.
Here's a good intro on the matter.
https://www.webkit.org/blog/138/
So, first let's recognize that we can't do the same things anymore
if (!Modernizr.csstransitions || Modernizr.csstransforms3d) {
// use some css
} else {
// use some jQuery
}
Now, let's fill in with your example
if (!Modernizr.csstransitions || !Modernizr.csstransforms3d) {
// Old jQuery version
$('.rightbox3d').animate({
opacity: 1,
top: "-200px",
width: 2 * $('.rightbox3d').width(),
height: 2 * $('.rightbox3d').height()
}, 4000);
} else {
// Modern cool version
// The transform is moving/rotating/stretching we want to do
// The transition is the animation we want
$('.rightbox3d').css({
opacity: 1,
transform: 'translateY(-200px) scale(2)',
transition: 'all 4000ms ease-in-out'
});
}
I think that should clear it up for you. :)
I am using jQuery and jQuery-ui and want to animate various attributes on various objects.
For the sake of explaining the issue here I've simplified it to one div that changes from blue to red when the user mouses over it.
I am able to get the behavior I want when using animate(), however when doing so the styles I am animating have to be in the animation code and so are separate from my style sheet. (see example 1)
An alternative is using addClass() and removeClass() but I have not been able to re-create the exact behavior that I can get with animate(). (see example 2)
Example 1
Let's take a look at the code I have with animate():
$('#someDiv')
.mouseover(function(){
$(this).stop().animate( {backgroundColor:'blue'}, {duration:500});
})
.mouseout(function(){
$(this).stop().animate( {backgroundColor:'red'}, {duration:500});
});
it displays all the behaviors I am looking for:
Animates smoothly between red and blue.
No animation 'overqueue-ing' when the user moves their mouse quickly in and out of the div.
If the user moves their mouse out/in while the animation is still playing it eases correctly between the current 'halfway' state and the new 'goal' state.
But since the style changes are defined in animate() I have to change the style values there, and can't just have it point to my stylesheet. This 'fragmenting' of where styles are defined is something that really bothers me.
Example 2
Here is my current best attempt using addClass() and removeClass (note that for the animation to work you need jQuery-ui):
//assume classes 'red' and 'blue' are defined
$('#someDiv')
.addClass('blue')
.mouseover(function(){
$(this).stop(true,false).removeAttr('style').addClass('red', {duration:500});
})
.mouseout(function(){
$(this).stop(true,false).removeAttr('style').removeClass('red', {duration:500});
});
This exhibits both property 1. and 2. of my original requirements, however 3 does not work.
I understand the reason for this:
When animating addClass() and removeClass() jQuery adds a temporary style to the element, and then increments the appropriate values until they reach the values of the provided class, and only then does it actually add/remove the class.
Because of this I have to remove the style attribute, otherwise if the animation is stopped halfway the style attribute would remain and would permanently overwrite any class values, since style attributes in a tag have higher importance than class styles.
However when the animation is halfway done it hasn't yet added the new class, and so with this solution the color jumps to the previous color when the user moves their mouse before the animation is completed.
What I want ideally is to be able to do something like this:
$('#someDiv')
.mouseover(function(){
$(this).stop().animate( getClassContent('blue'), {duration:500});
})
.mouseout(function(){
$(this).stop().animate( getClassContent('red'), {duration:500});
});
Where getClassContent would just return the contents of the provided class. The key point is that this way I don't have to keep my style definitions all over the place, but can keep them in classes in my stylesheet.
Since you are not worried about IE, why not just use css transitions to provide the animation and jQuery to change the classes. Live example: http://jsfiddle.net/tw16/JfK6N/
#someDiv{
-webkit-transition: all 0.5s ease;
-moz-transition: all 0.5s ease;
-o-transition: all 0.5s ease;
transition: all 0.5s ease;
}
Another solution (but it requires jQueryUI as pointed out by Richard Neil Ilagan in comments) :-
addClass, removeClass and toggleClass also accepts a second argument; the time duration to go from one state to the other.
$(this).addClass('abc',1000);
See jsfiddle:- http://jsfiddle.net/6hvZT/1/
You could use jquery ui's switchClass, Heres an example:
$( "selector" ).switchClass( "oldClass", "newClass", 1000, "easeInOutQuad" );
Or see this jsfiddle.
You just need the jQuery UI effects-core (13KB), to enable the duration of the adding (just like Omar Tariq it pointed out)
I was looking into this but wanted to have a different transition rate for in and out.
This is what I ended up doing:
//css
.addedClass {
background: #5eb4fc;
}
// js
function setParentTransition(id, prop, delay, style, callback) {
$(id).css({'-webkit-transition' : prop + ' ' + delay + ' ' + style});
$(id).css({'-moz-transition' : prop + ' ' + delay + ' ' + style});
$(id).css({'-o-transition' : prop + ' ' + delay + ' ' + style});
$(id).css({'transition' : prop + ' ' + delay + ' ' + style});
callback();
}
setParentTransition(id, 'background', '0s', 'ease', function() {
$('#elementID').addClass('addedClass');
});
setTimeout(function() {
setParentTransition(id, 'background', '2s', 'ease', function() {
$('#elementID').removeClass('addedClass');
});
});
This instantly turns the background color to #5eb4fc and then slowly fades back to normal over 2 seconds.
Here's a fiddle
Although, the question is fairly old, I'm adding info not present in other answers.
The OP is using stop() to stop the current animation as soon as the event completes. However, using the right mix of parameters with the function should help. eg. stop(true,true) or stop(true,false) as this affects the queued animations well.
The following link illustrates a demo that shows the different parameters available with stop() and how they differ from finish().
http://api.jquery.com/finish/
Although the OP had no issues using JqueryUI, this is for other users who may come across similar scenarios but cannot use JqueryUI/need to support IE7 and 8 too.