css3 transition on background image doesn't work in Firefox - javascript

This is a follow up to my question here: jquery UI add class with animation does't work
See the new jsfiddle and try this in Firefox: http://jsfiddle.net/40mga4vy/3/
-webkit-transition: all 2.0s ease;
-moz-transition: all 2.0s ease;
-o-transition: all 2.0s ease;
transition: all 2.0s ease;
This code in combination with some jquery animates a background image change when selecting a new background image from a select-element. It works in all browsers except Firefox (tested in MacOS 35.0.1).
While animating a change in the background color and width/height properties works like a charme in FF: http://jsfiddle.net/tw16/JfK6N/ - animating a background image does not work.
Researching showed that a "left" property has to be set but it turned out to not have any impact. I also tried various notations but with no success, I cannot make it work.
There is a workaround shown in this fiddle:
http://jsfiddle.net/40mga4vy/1/
function changeBackground() {
$('#wallpaper').removeClass();
$("#wallpaper").addClass("wallpaper_" + $("#select_category").val()).css('opacity','0').animate({opacity:'1'});
};
This works in FF but its a bit ugly as the class is removed and then opacity raises afterwards (doesn't look as smooth as the css solution).
Any hints/tricks or is this simply not supported?

As far as I know, there is no suport in any browser to swap images smoothly in one single element in css.
After you do what you need, make sure you take a look into performance, your workaround is not as much as efficient as it could. In this code
$("#wallpaper").addClass("wallpaper_" + $("#select_category").val()).css('opacity','0').animate({opacity:'1'});,
the browser will take every single step until
.animate({opacity:'1'}).
For instance, the browser first has to find $("#wallpaper") then, it will call for .addClass("wallpaper_" + ...);
and concatenate the result from finding $("#select_category") then getting .val() and so on. everytime this function is called, it will iterate through every single of these objects, so it is not as efficient as probably could and with two more animations in the page, it may became a bit laggy, if possible, use animations through CSS.
Anyway, what I sugest you to do is (if i'm right about what you want), just do what's in here https://jsfiddle.net/bmjg5g9s/

Related

jQuery css() changing 'transition-delay' to 'transition' in safari

The following code produces the expected result in chrome, that is; adding transition-delay directly to all the elements.
$('.front-nav .sub-menu').each(function() {
var transitionDelay = 50;
$(this).find('li').each(function( index ) {
var thisDelay = transitionDelay * index;
thisDelay = thisDelay + 'ms';
$(this).css('transition-delay', thisDelay);
});
});
In Safari instead of transition-delay, a transition style is added to the element.
The style added by jQuery in safari:
style="transition: 50ms; -webkit-transition: 50ms;
The style added by jQuery in chrome:
style="transition-delay: 0ms; -webkit-transition-delay: 0ms;"
I stumbled upon this question because I had the same one. With a little experimentation, I found that it seems Safari is behaving properly, just in a misleading way. If you load jQuery into a blank page and try to set the transition-delay property on an element using your method, the inspector will only show transition: ___, but if you then query the element's transition property, you'll see it was actually set properly:
// in console
$(document.body).css('transition-delay', '0.3s') // sets `transition: 0.3s` on body
$(document.body).css('transition') // "all 0s ease 0.3s"
So we see that it's doing what we want. The issue I was having was when having multiple transitions with different values. For example:
$(document.body).css('transition-delay', '0.3s, 2s')
This appears to set transition: 0.3s, 2s on the element in inspector, suggesting 0.3s duration and 2s delay, but when you ask for the transition-delay property, you'll see it's still 0s. I think this is just a poor way on Safari's part of showing styles in the inspector.
Aside from the apparent styles applied, are you noticing truly different behavior in Safari?

Animation transitions behave differently for ng-hide-remove and ng-hide-add

I am trying to animate a <div> to slide-in/out from the left on a button click. I am using the angular framework and ng-showto control the <div> display/visibility, and adding transitions to the ng-hide set of styles.
I have successfully managed to have the div slide in from the left, however I can not get it to slide out (it simply dissappears after the specified delay). I have tried modifying several examples online to get the behavior I am after to no avail.
JSFiddle for anyone that wants to have a look
https://jsfiddle.net/mquinlan/0wcrcwxe/5/
You got that almost right except for removing the left:0 in the selectors for .animate-show.ng-hide-add.ng-hide-add-active, .animate-show.ng-hide-remove.ng-hide-remove-active.
.animate-show.ng-hide-add.ng-hide-add-active,
.animate-show.ng-hide-remove.ng-hide-remove-active {
-moz-transition: all ease 0.5s;
transition: all ease 0.5s;
}
Updated Fiddle: https://jsfiddle.net/vsj62g5r/

How to correctly wait until JavaScript applies inline Css

I have this jsFiddle. When the button is clicked, I want to put the red div behind the black one immediately, then start the animation.
var red = document.getElementById("red");
var button = document.getElementById("button");
button.addEventListener("click",function () {
red.style.zIndex = -1;
red.classList.remove("shifted");
});
However, as you can see, they seem to be occurring as two separate actions. I know I can use setTimeout to wait until the zIndex property is applied, but I do not know how long I am supposed to wait, and the duration perhaps differs from browsers to computers.
Should I create a loop that will check if zindex was applied? But this also sounds like an unintelligent solution. What is the correct way?
EDIT: I do not want to change the zIndex on the black div.
You can bind to the transitioned state of the element, something like this:
("#mySelector").bind("transitionend", function(){ 'yourcodehere' });
Also, here is some info on it:
https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Using_CSS_transitions
https://developer.mozilla.org/en-US/docs/Web/Reference/Events/transitionend
Without jQuery:
el.addEventListener("transitionend", updateTransition, true);
Edit:
There was some confusion as to the usage of:
-webkit-transition-duration: 1s;
This is applied like a styling as well. So anytime you make alterations to the element it is on, you are triggering this. You have TWO transition calls, one for setting the z-index, another for the movement.
Just put a
-webkit-transition-property: -webkit-transform;
into the #red and everything is fine. ;) This applies the transition only to specified property.
JSFIDDLE: http://jsfiddle.net/Qvh7G/.
The problem is with zIndex - the transform time delays the change in the zIndex.
You can simply force the duration for the transform property.
Replace:
-webkit-transition-duration: 1s;
With
-webkit-transition: -webkit-transform 1s; // ease-in;

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

How does Google achieve the fading effect on the home page?

If you go to google.com, you notice the menu on top slowly appears once you have mouse over the page. I was wondering what does Google use to control the fading effect?
[edit] since I don't use jQuery, I don't want to include it just to use this feature
There are two ways.
Javascript
Works in most browsers.
Gradually change the CSS opacity attribute of an element using Javascript. That's easiest with a good framework like jQuery, but is quite simple to do yourself.
function fadeIn() {
var element = document.getElementById("someID");
var newOpacity = element.style.opacity + 0.05;
element.style.opacity = newOpacity;
if (newOpacity < 1) {
window.setTimeout(fadeIn, 50);
}
}
Pure CSS
Only supported in Webkit at the moment.
#someID {
opacity:0;
-webkit-transition: opacity 1s linear;
}
#someID:hover {
opacity:1;
}
For an example have a look at the Surfin' Safari blog.
You could use jQuery and add an onmousemove callback on the tag that fades a hidden div with id "mymenu" in, something like:
$("html").one("mousemove", function() {
$("#mymenu").fadeIn("slow")
});
Warning: this was typed here, so I dunno if it compiles ootb.
I've never looked at it, but it's only logical to assume that there's a timer that gets started at load time for the page, and that adjusts either the alpha for the specified element or the opacity of another element that overlays it, in that element's CSS. Every timer tick, the numbers get turned up/down a little and the text becomes a bit more legible. When full visibility is reached, the timer is turned off.
JQuery is a finished, ready to use implementation of this in a cross-platform compatible package. You just add it, stir it up and it's done.
If you choose not to take the advice of the other answers, you'll have to research and implement the strategy from my top paragraph on your own. Good luck!
This is actually a rather complex thing to do because of the cross browser differences. The basics are something like the following:
Get the current opactity of the element as float.
Determine the ending opacity as float.
Determine your rate speed - i dont know what this should be in raw terms - somthing like .01/ms maybe?
Use a setInterval to fire a function that increases the opacity by your rate where: setInterval(function(){myElement.style.opacity = parseFloat(myElement.style.opacity)+0.01;}, 1); Somewhere in ther though you need to check if youve reached the endpoint of your animation and shutdown your interval.
I would think that they set the initial opacity of the elements other than the search box to zero. When the mouseover event is fired, the elements' opacity is gradually increased to 1.
Edit: In code it would look something like this:
var hiddenStuff = document.getElementByClassName("hiddenStuff");
var interval=document.setInterval(function() {
for (var i=0; i<hiddenStuff.length;i++){
hiddenStuff[i].style.opacity+=0.1
}
if (hiddenStuff[1].style.opacity===1){
window.clearInterval(interval);
}
}, 100);
You may need to tweak the parameters to get a smooth animation.
#Georg, that example works on Firefox 3.5 too. :-)
Demo: PURE CSS http://jsfiddle.net/6QS2a/1/
</div>
css:
.item {
height:150px;
width:150px;
border-radius:100%;
background:skyblue;
-webkit-transition: opacity 1s ease-in-out;
-moz-transition: opacity 1s ease-in-out;
-ms-transition: opacity 1s ease-in-out;
-o-transition: opacity 1s ease-in-out;
transition: opacity 1s ease-in-out;
opacity:0.2;
}
.item:hover {
opacity: 1;
}

Categories