FadeIn animation using CSS3 in Javascript - javascript

As jQuery.fadeIn is not very smooth on mobile devices I try to use CSS but it doesn't work as expected. How to create a smooth CSS animation using Javascript?
In general this is what I'm trying:
$('div')
.css('opacity', 0) // at first, set it transparent
.css('display', 'block') // make it appear
.css('transition', 'opacity 1000ms linear') // set a transition
.css('opacity', 1); // let it fade in
https://jsfiddle.net/8xa89y04/
EDIT1:
I'm not searching a solution using static CSS classes. The point is: I need to set this dynamically in Javascript code - a replacement for jQuerys fadeIn() for example.

Your logic isn't quite right. Firstly you cannot animate display, so to achieve what you require the element has to always be rendered in the DOM (ie. anything but display: none). Secondly, the transition property should be placed within the CSS styling itself. Finally you can make this much more simple by setting all the rules in CSS classes and just turning the class on/off. Try this:
div {
position: absolute;
width: 100px;
height: 100px;
background-color: black;
opacity: 0;
transition: opacity 1000ms linear;
}
.foo {
opacity: 1;
}
$('div').addClass('foo');
Working example

Use this code.
CSS
div {
width: 100px;
height: 100px;
background-color: black;
transition:opacity 2s;
}
JavaScript
$('div').hover(function(){
$(this).css('opacity','0');
})

Without using CSS properly, you are going the long way about it. You'll need to emulate what you would normally do in CSS, using JavaScript, so you'll be setting all your CSS properties, transitions etc, then applying them with js.
I can't personally see any benefit in doing this. Using actual CSS would be cleaner, more efficient, more maintainable, and simply a plain better solution to what you need.

I think this is what you are looking for.
$('div').css({"display":"block", "opacity":"0"}) //Make div visible and opacity as "0"
$('div').animate({opacity :1}, 1000); //Animate div to opacity "1"
Take a look at this Demo

Found the cause here: CSS transitions do not work when assigned trough JavaScript
To give this attention I need to give the browser some time - or better: a working slot to activate the transition as the time seems not to be a problem.
The following code cuts the process in two by using setTimeout()... and it works!
var div = $('div');
// first process
div
.css('opacity', 0) // initial opacity
.css('display', 'block') // make it appear (but still transparent)
.css('transition', 'opacity 1s linear'); // set up a transition for opacity
// break - start the transition in a new "thread" by using setTimeout()
window.setTimeout(function(){
div.css('opacity', 1); // start fade in
}, 1); // on my desktop browser only 1ms is enough but this
// may depend on the device performance
// maybe we need a bigger timeout on mobile devices

Related

Wait for class to be added before modifying styles

I'm trying to do something like this:
element.classList.add('animate-in')
element.style.transform = 'translateY(100px)';
Where the animate-in class has a transition: transform 1s property for animation. But when I run this it the element is translated 100px down but without the transition, seems like the transform property is modified before the class name can be added and take affect. I don't want to use setTimeout since it can be unreliable in animations. Is there any way to wait for the class to be added before modifying any styles?
I don't think we get any events for the 'application of styles' through JavaScript, which is pretty frustrating in this case...
I found this thread that's pretty helpful.
One thing to note: the animation will work even if you use setTimeout with 0 ms. What was the reason in particular that it messed with animations?
setTimeout(function(){
element.style.transform = 'translateY(100px)'
}, 0)
Also, if you set it up with an event, you can change the style directly and see the animation applied.
Here's the bin I was playing around with: https://jsbin.com/lofotutumu/edit?html,css,js,output
You don't really want to wait, but want the properties embedded with this new class to be applied.
And this can be done, synchronously, by triggering a reflow.
Some properties/functions need the DOM boxes to be recalculated in order to return their values. To do so, the browser has to trigger a reflow on the page, and hence will apply your new properties.
But note that this has a performance impact, particularly on complex pages, so use it with care.
element.classList.add('animate-in');
element.offsetTop; // trigger a reflow
element.style.transform = 'translateY(100px)';
.animate-in {
transition: transform 2s linear;
}
<div id="element">Hello</div>
Would creating a keyframe and adding that into your class suit your needs? E.g.
// This is your keyframe to animate your element
#keyframes translateDown {
0%{
transform:translateY(0);
}
100%{
transform:translateY(100px);
}
}
.animate-in{
animation: 2s linear translateDown both;
}

how to show hover effect on a image where i hover my mouse

i have multiple images, on hover on particular image i want to apply on that image only, it should not effect on other image.
More Explanation:
In this example(http://codepen.io/anon/pen/AnsqI), suppose i have multiple images & want to apply the certain effect on only on that image where i hove my mouse.
I am using class attribute...
<script>
$(function() {
//For grid view hover effect
$('.grid_content').hide()
$('.grid_container').hover(
// Over
function() {
$('.grid_content').fadeIn();
}
,
// Out
function() {
$('.grid_content').fadeOut();
}
);
//--js for grid view hover effect ends here
});
</script>
Something i have to apply like $this , i tried like($this.$('.grid_content').fadeOut();)but it did not work.
Somebody please help me.
Use this:
$('.container').hover(function(){
$('.content',this).fadeToggle();
});
Check this Demo http://codepen.io/anon/pen/BxbID
You could consider using CSS and the opacity attribute (or display). You could progressively enhance the hover effect with CSS3's transition property as well. There isn't necessarily a need for JS here, and I only added five lines of CSS (unprefixed) to achieve the same effect.
.content {
width: 100%;
height: 100%;
background: rgb(255,255,255,0.9);
padding: 5px 15px 10px 15px;
box-sizing: border-box;
opacity: 0;
transition: opacity .2s linear; /* CSS3 progressive enhancement */
}
.content:hover {
opacity: 1;
}
Depending on how you organize your HTML, you may need to make modifications, but the concept is the same.
Check out the demo: http://jsfiddle.net/NeEuP/1/
There are 2 ways to do this. You can either reference it using the this javascript keyword and surrounding it in a jQuery function:
$('.grid_container').hover(function(){
$(this).fadeIn();
, function(){
$(this).fadeOut();
});
Or you can:
$('.grid_container').hover(function(e){
$(e.currentTarget).fadeIn();
, function(e){
$(e.currentTarget)$(this).fadeOut();
});
... basically you're getting element through the event object. I personally prefer this method, because it's more flexible it doesn't depend on the actual scope (this depends on scope).

jquery-ui switchClass() not working as expected

I'm having trouble getting the switchClass function to fade nicely like it does in the example on the jquery site. Basically the timing doesn't seem to have any effect, I've tried from 40000-4 but makes no difference.
I've posted a fiddle below (which explains better) but here's the code I'm using. There's two divs which are meant to switch class so the background image is different. I'm using different methods for each div but they both give exactly the same result even though one uses switchClass the other uses addClass.
$(document).ready(function() {
$('.iamatrainer').hover(function(){
$(this).switchClass('iamatrainer', 'iamatrainerhover', 400, 'easeInOutQuad');
}, function(){
$(this).switchClass('iamatrainerhover', 'iamatrainer', 400, 'easeInOutQuad');
});
$('.iusetrainer').hover(function(){
$(this).addClass('iusetrainerhover', 400);
}, function(){
$(this).removeClass('iusetrainerhover', 400);
});
});
http://jsfiddle.net/KJbA8/
Can anyone help me out?
Are you sure you have jQueryUI loaded? The switchClass method isn't a part of jQuery. Your fiddle is throwing JS Console errors about it.
You don't really need JS for this. Just setting the :hover on the .iamatrainer and .iusetrainer elements works fine. http://jsfiddle.net/y3ALr/3/
Also, if you must use a background image...
Make sure you're using some reasonably accessible image replacement technique
Consider using sprites and :hover offsets so you don't get that nasty delay.
You can use :hover pseudo-selector and css transitions
CSS:
.iamatrainer{
background:url(http://renegadeox.com/iamatrainer.png);
height:70px;
width:512px;
transition: background 0.3s linear;
}
.iamatrainer:hover{
background:url(http://renegadeox.com/iamatrainerhover.png);
height:70px;
width:512px;
transition: background 0.3s linear;
}
Here is your updated Demo.
Also, you'd better merge images in one and use background-position for :hover state

Does jQuery animate between two different CSS classes?

I am trying to understand how jQuery animations work.
For instance, if I have an a element with CSS that makes it look like a clickable image and a given with and height in CSS, how would I safely animate the width and height of this element?
Do I need to animate the values in the CSS class? Or do I need to set a new CSS class with the target values for width and height, and let jQuery animate from oldClass to newClass?
Or can I simply use the .width() and .height() methods of jQuery, regardless of what values are specified in CSS?
What confuses me is: If I tweak the width of an element with jQuery, does this also modify my CSS, or does jQuery / JavaScript simply override the specified values in CSS with something else? I mean: After use jQuery to edit the width, does this width become the new value in the CSS file as well? Can I apply this class to other elements and they will have the new width?
It will overide inline style.
I will now show a version with top, left being animated but you can apply it on almost all CSS properties.
HTML
<span id="test">blablabla</span>
CSS
span{
position:absolute;
display:block;
height:50px;
width:50px;
}
jquery
$('#test').animate({top:'100px',left:'50px'}, 500);
fiddle
I know it's been a long time, but it may help someone looking for the answer anyway. Relying on CSS3 transition property can lead to trouble when wanting to support older browsers.
The requested behaviour of animating between two states (CSS Classes) can fully be accomplished by using jQuery UI, which supports this by extending the switchClass() method. It also supports all the perks of the animate() method, such as duration, easing, callback, etc.
As the official documentation states: '
Similar to native CSS transitions, jQuery UI's class animations
provide a smooth transition from one state to another while allowing
you to keep all the details about which styles to change in CSS and
out of your JavaScript.
You can read all about it here.
jQuery UI can also be compiled to include only the things you need, so you can reduce the size of the library by excluding the features you won't use. Check the available options here.
Hope it helped someone!
jQuery animate only animates numeric css values. It will not animate between classes (see example below for how to do that). The .animate() function adds the css you give it as a paramater and adds it as inline css. It will always override your stylesheet css. This is fine but a little messy and can get out of control very easily.
However, if you want to animate between classes, it is better for performance and cleaner to use css3 transition property. See example:
HTML
<div class="myTestAnimation">Something to test</div>
JQuery (could use vanilla javascript for this as well). Just toggling between classes. This way you don't have any styling info in your css at all.
jQuery(document).ready(function($) {
$(".myTestAnimation").click(function() {
$(this).toggleClass("animate");
});
});
CSS (this animates the width and height and background color) .animate() will not animate background color so that is an added bonus.
.myTestAnimation {
width: 50px;
height: 50px;
background-color: red;
-webkit-transition: background-color 300ms linear, width 300ms linear, height 300ms linear;
transition: background-color 300ms linear, width 300ms linear, height 300ms linear;
position: relative;
}
.myTestAnimation.animate {
background-color: blue;
width: 200px;
height: 200px;
}

What is the cleanest way to disable CSS transition effects temporarily?

I have a DOM element with this effect applied:
#elem {
transition: height 0.4s ease;
}
I am writing a jQuery plugin that is resizing this element, I need to disable these effects temporarily so I can resize it smoothly.
What is the most elegant way of disabling these effects temporarily (and then re-enabling them), given they may be applied from parents or may not be applied at all.
Short Answer
Use this CSS:
.notransition {
-webkit-transition: none !important;
-moz-transition: none !important;
-o-transition: none !important;
transition: none !important;
}
Plus either this JS (without jQuery)...
someElement.classList.add('notransition'); // Disable transitions
doWhateverCssChangesYouWant(someElement);
someElement.offsetHeight; // Trigger a reflow, flushing the CSS changes
someElement.classList.remove('notransition'); // Re-enable transitions
Or this JS with jQuery...
$someElement.addClass('notransition'); // Disable transitions
doWhateverCssChangesYouWant($someElement);
$someElement[0].offsetHeight; // Trigger a reflow, flushing the CSS changes
$someElement.removeClass('notransition'); // Re-enable transitions
... or equivalent code using whatever other library or framework you're working with.
Explanation
This is actually a fairly subtle problem.
First up, you probably want to create a 'notransition' class that you can apply to elements to set their *-transition CSS attributes to none. For instance:
.notransition {
-webkit-transition: none !important;
-moz-transition: none !important;
-o-transition: none !important;
transition: none !important;
}
Some minor remarks on the CSS before moving on:
These days you may not want to bother with the vendor-prefixed properties like -webkit-transition, or may have a CSS preprocessor that will add them for you. Specifying them manually was the right thing to do for most webapps when I first posted this answer in 2013, but as of 2023, per https://caniuse.com/mdn-css_properties_transition, only about 0.4% of users in the world are still using a browser that supports only a vendor-prefixed version of transition.
There's no such thing as -ms-transition. The first version of Internet Explorer to support transitions at all was IE 10, which supported them unprefixed.
This answer assumes that !important is enough to let this rule override your existing styles. But if you're already using !important on some of your transition rules, that might not work. In that case, you might need to instead do someElement.style.setProperty("transition", "none", "important") to disable the transitions (and figure out yourself how to revert that change).
Anyway, when you come to try and use this class, you'll run into a trap. The trap is that code like this won't work the way you might naively expect:
// Don't do things this way! It doesn't work!
someElement.classList.add('notransition')
someElement.style.height = '50px' // just an example; could be any CSS change
someElement.classList.remove('notransition')
Naively, you might think that the change in height won't be animated, because it happens while the 'notransition' class is applied. In reality, though, it will be animated, at least in all modern browsers I've tried. The problem is that the browser is buffering the styling changes that it needs to make until the JavaScript has finished executing, and then making all the changes in a single "reflow". As a result, it does a reflow where there is no net change to whether or not transitions are enabled, but there is a net change to the height. Consequently, it animates the height change.
You might think a reasonable and clean way to get around this would be to wrap the removal of the 'notransition' class in a 1ms timeout, like this:
// Don't do things this way! It STILL doesn't work!
someElement.classList.add('notransition')
someElement.style.height = '50px' // just an example; could be any CSS change
setTimeout(function () {someElement.classList.remove('notransition')}, 1);
but this doesn't reliably work either. I wasn't able to make the above code break in WebKit browsers, but on Firefox (on both slow and fast machines) you'll sometimes (seemingly at random) get the same behaviour as using the naive approach. I guess the reason for this is that it's possible for the JavaScript execution to be slow enough that the timeout function is waiting to execute by the time the browser is idle and would otherwise be thinking about doing an opportunistic reflow, and if that scenario happens, Firefox executes the queued function before the reflow.
The only solution I've found to the problem is to force a reflow of the element, flushing the CSS changes made to it, before removing the 'notransition' class. There are various ways to do this - see here for some. The closest thing there is to a 'standard' way of doing this is to read the offsetHeight property of the element.
One solution that actually works, then, is
someElement.classList.add('notransition'); // Disable transitions
doWhateverCssChangesYouWant(someElement);
someElement.offsetHeight; // Trigger a reflow, flushing the CSS changes
someElement.classList.remove('notransition'); // Re-enable transitions
Here's a JS fiddle that illustrates the three possible approaches I've described here (both the one successful approach and the two unsuccessful ones):
http://jsfiddle.net/2uVAA/131/
Add an additional CSS class that blocks the transition, and then remove it to return to the previous state. This make both CSS and JQuery code short, simple and well understandable.
CSS:
.notransition {
transition: none !important;
}
Note: !important was added to be sure that this rule will have higher preference, because using an ID is more specific than class.
JQuery:
$('#elem').addClass('notransition'); // to remove transition
$('#elem').removeClass('notransition'); // to return to previouse transition
I would advocate disabling animation as suggested by DaneSoul, but making the switch global:
/*kill the transitions on any descendant elements of .notransition*/
.notransition * {
transition: none !important;
}
.notransition can be then applied to the body element, effectively overriding any transition animation on the page:
$('body').toggleClass('notransition');
For a pure JS solution (no CSS classes), just set the transition to 'none'. To restore the transition as specified in the CSS, set the transition to an empty string.
// Remove the transition
elem.style.transition = 'none';
// Restore the transition
elem.style.transition = '';
If you're using vendor prefixes, you'll need to set those too.
elem.style.webkitTransition = 'none'
You can disable animation, transition, transforms for all of element in page with this CSS code:
var style = document.createElement('style');
style.type = 'text/css';
style.innerHTML = '* {' +
' transition-property: none !important;' +
' transform: none !important;' +
' animation: none !important;}';
document.getElementsByTagName('head')[0].appendChild(style);
I think you could create a separate CSS class that you can use in these cases:
.disable-transition {
transition: none;
}
Then in jQuery you would toggle the class like so:
$('#<your-element>').addClass('disable-transition');
If you want a simple no-jquery solution to prevent all transitions:
Add this CSS:
body.no-transition * {
transition: none !important;
}
And then in your js:
document.body.classList.add("no-transition");
// do your work, and then either immediately remove the class:
document.body.classList.remove("no-transition");
// or, if browser rendering takes longer and you need to wait until a paint or two:
setTimeout(() => document.body.classList.remove("no-transition"), 1);
// (try changing 1 to a larger value if the transition is still applying)
This is the workaround that worked easily for me. It isn't direct answer to the question but still may help someone.
Rather than creating notransition class which was supposed to cancel the transition
.notransition {
-webkit-transition: none !important;
-moz-transition: none !important;
-o-transition: none !important;
transition: none !important;
}
I created moveTransition class
.moveTransition {
-webkit-transition: left 3s, top 3s;
-moz-transition: left 3s, top 3s;
-o-transition: left 3s, top 3s;
transition: left 3s, top 3s;
}
Then I added this class to element with js
element.classList.add("moveTransition")
And later in setTimeout, I removed it
element.classList.remove("moveTransition")
I wasn't able to test it in different browsers but in chrome it works perfectly
If you want to remove CSS transitions, transformations and animations from the current webpage you can just execute this little script I wrote (inside your browsers console):
let filePath = "https://dl.dropboxusercontent.com/s/ep1nzckmvgjq7jr/remove_transitions_from_page.css";
let html = `<link rel="stylesheet" type="text/css" href="${filePath}">`;
document.querySelector("html > head").insertAdjacentHTML("beforeend", html);
It uses vanillaJS to load this css-file. Heres also a github repo in case you want to use this in the context of a scraper (Ruby-Selenium): remove-CSS-animations-repo
does
$('#elem').css('-webkit-transition','none !important');
in your js kill it?
obviously repeat for each.
I'd have a class in your CSS like this:
.no-transition {
-webkit-transition: none;
-moz-transition: none;
-o-transition: none;
-ms-transition: none;
transition: none;
}
and then in your jQuery:
$('#elem').addClass('no-transition'); //will disable it
$('#elem').removeClass('no-transition'); //will enable it

Categories