Transition misbehavior - javascript

I have several problems with transition behavior, probably they are the same single problem.
First class of problems with a short transitions.
<style>
.someclass {
transition: all 1s linear;
}
</style>
<script>
function activationcode()
{
//$('.someclass').hide(); was in display none state.
$('.someclass').css('opacity', 0);
$('.someclass').show();
$('.someclass').css('opacity', 1);
}
</script>
Add in most of cases this code doesn't work as expected. The .someclass item appears in final state. The changing property doesn't matter, opacity is just for example. To make it working the two things helps: a) changing all for transition to the particular property, for this example to opacity; b) call $('.someclass').css('opacity', 1); with delay, for example, 100ms.
But this only reduce probability of problem to very low value, doesn't fix it.
Second class of problem is for a long animation. It works, but if you put it inside the tab (or anything like that), and will start to switch from animated tab to other one, the animation may be finished in a final state before the specified time. Single switch/switch-back usually doesn't break animation. But two or more switches does with very high probability.
I can reproduce this on Firefox (not very recent). Initially was reported for Chrome (reporter states that he uses the last one version).
I suspect that the problem does depend on amount of css/js activity on page (was unable to reproduce second problem with minimal jsfiddle).
So the question is how to fix such problems, does any solution exist?

Place the line...
$('.someclass').css('opacity', 1);
...in a setTimeout(fn, 0). This will defer its execution, ensuring that the browser won't optimise those steps into one paint (show the element at 100% opacity).

I suggest that you use classes instead and handle show/hide in CSS only
.hide {
display: none;
opacity: 0;
transition: opacity 1s linear 0s, display 0s linear 1s;
/* decrease opacity, then change display with a delay */
}
.show {
display: block;
opacity: 1;
transition: display 0s linear 0s, opacity 1s linear 0s;
/* change display instantly without delay, then increase opacity */
}
By delaying the hiding for 1s, you allow the opacity transition to complete before hiding it.
But we reset the delay on the showing because we need people to see the opacity increasing.

Related

Animating delay on bootstrap container classes

I am using bootstrap framework on my website, with the content wrapped in class="container"
This has certain break-points when the screen resizes, the cols, margins, etc change.
I wanted to put a delay on that break point but not sure how to go about it. So when the side margins change from one size to another, the content doesn't just jump to the new size, but animates into it.
Here you have an example of the CSS that you can use:
-webkit-transition:width 1000ms ease-in-out;
-moz-transition:width 1000ms ease-in-out;
-o-transition:width 1000ms ease-in-out;
transition:width 1000ms ease-in-out;
Basically what it does, is that when the property "width" changes specifies a transition effect with a slow start and end of 1 second.
JSFiddle with an example. You have to move your mouse hover the red DIV to see the effect.
More information about this CSS property.
Try adding something similar to the following CSS to your container element:
transition: all 0.5s ease-in-out;

Don't dim slide content when not active

I am using impress.js for the first time and wanted to make a tweak. The original demo SEEN HERE has the slides become dim/transparent when they are not active. I have seen another impress.js presentation SEEN HERE where the image/slides remain opaque throughout the presentation except on the first slide (after that everything become opaque). How can I make a particular slide or image stay opaque through out the presentation?
in your css adding
.future : { opacity: 1.0 !important;}
.past : { opacity: 1.0 !important;}
or editing impress-demo.css
.impress-enabled .step {
margin: 0;
opacity: 0.3; <--- CHANGE THIS
-webkit-transition: opacity 1s;
-moz-transition: opacity 1s;
-ms-transition: opacity 1s;
-o-transition: opacity 1s;
transition: opacity 1s;
}
will change the opacity for different steps
Anyway, you can find the elements ,and choose the one u want and make a .css with jquery, for example:
$("body").find(".future")[0].css("opacity","1.0"); <-- This will change just the first future step found
Anyway, please read about css rules and specificity:
https://developer.mozilla.org/en-US/docs/Web/CSS/Specificity
Hope it helps
EDIT
I though u may also want to use :firs-child or :after (CSS selectors) will can also help you: http://quirksmode.org/css/selectors/firstchild.html
http://www.w3schools.com/cssref/sel_after.asp

How can I add a time delay to my divs, so they appear one after the other like a powerpoint slide? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
So say I want div 1 to appear after 2 seconds, div 2 to appear after 7 seconds, and div 3 to appear after 15 seconds.
Is there a way for me to add an inline style element that will make the divs go from hidden but occupying space to fully visible.
I've been searching and most things I've found are hover/click triggered. I can't seem to find anything with a time trigger.
Thank you.
Edit: To make this more clear, I am looking for any kind of code that has a time delay to appear. When I search transition, I get a bunch of code based on actions, like a click or a hover. I am not looking for a user action to trigger this, just a time.
When I search for animation, I get a bunch of results about moving images, which I also do not need.
When I search for time delay, I get a bunch of results about time delay transitions, which is how long after the user action occurs does the transition occur which still requires user input, and I do not want user input.
I am more asking what I should be looking for, if there is a word for it or something you are familiar that does this. I didn't provide any code because I don't want you coding me something. I'm asking for lead, because it is frustrating that I cannot find the proper word to identify what I need.
you can either use a css transition to animate the visibility property after a set delay in your stylesheet, or you can change the visibility property using JS and setTimeout();
HTML
<div id="div1" style="visibility:hidden;"></div>
JS
setTimeout(function(){
document.getElementById('div1').style.visibility = "visible";
},1000);
This sets a callback to override the css property after 1000 ms, or 1 second.
For a pure css solution we can use this instead. We need to provide multiples of a few properties, for cross platform compatibility.
#-webkit-keyframes fadeIn { from { opacity:0; } to { opacity:1; } }
#-moz-keyframes fadeIn { from { opacity:0; } to { opacity:1; } }
#keyframes fadeIn { from { opacity:0; } to { opacity:1; } }
.fade-in {
opacity:0;
-webkit-animation:fadeIn ease-in 1;
-moz-animation:fadeIn ease-in 1;
animation:fadeIn ease-in 1;
-webkit-animation-fill-mode:forwards;
-moz-animation-fill-mode:forwards;
animation-fill-mode:forwards;
-webkit-animation-duration:1s;
-moz-animation-duration:1s;
animation-duration:1s;
}
So this class called fade-in adds a 1s animation to any element it's added to, it will start as soon as it's loaded as it is. It's opacity based so the object will take up space when it's invisible, if you don't want this you need to use a variation on display:none.
A delay can be added to an element using
-webkit-animation-delay: 2s;
-moz-animation-delay: 2s;
animation-delay: 2s;
Just set that with a different value for each 'slide' to get them to fade in at different times.
If you want the space taken up - meaning you don't want things collapsed up, I would create the div, and set it's display to none, and then the opacity to 0. This will hide the element, but it will still take up physical space on your page.
Then I would create a css class called "show" or something like that:
CSS:
.show {
opacity: 1;
transition: opacity 1s ease-in-out;
-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;
}
Then with jQuery (or javascript) you could use either setInterval, or setTimeOut. In your timeout function, you could dynamiclly assign the "show" class to each element. This would fade each element in after "x" seconds you specify.
Something like this:
jQuery:
$(function() {
setTimeout(function(){
showElement();
}, 3000);
function showElement() {
$('my-div').toggleClass('show');
}
});

AngularJS - Slide Divs Up And Down With Z-Index Changes Isn't Being Respected

Please see the JSFiddle here which shows my issue: http://jsfiddle.net/mlippy/zkH7S/
I'm attempting to shuffle divs up and down a list with those divs moving up hiding the divs moving down. If you look at the fiddle, there are 5 different colored boxes that you can click to tell them to move to the top. If you click various boxes in various positions, you'll start to see the z-index of the boxes moving up not be higher than that of the boxes moving down. If you click the 3rd positioned box repeatedly, that's been a quality reproducer for me.
The angular directive myWidget is applying the indexes through classes which are being added / removed in chained addClass and removeClass calls. See below and the opposite version in the fiddle.
element.removeClass('moveDown').addClass('moveUp').css('top', (newValue * 45) + 'px');
I had thought that this meant the browser was going to complete the first chained call before moving onto the second (and so on). However in this case it doesn't appear to be doing so.
Also in the directive / below, you'll find a working solution using $timeout to delay the change to the css top value which triggers the transition. It's been commented out, but there are comments showing how to toggle to the solution in the two spots code needs to be changed. This feels like cheating / not the correct way for it to be done however. Hence the question here.
element.removeClass('moveDown').addClass('moveUp');
$timeout(function() {
element.css('top', (newValue * 45) + 'px');
}, 350);
This is my first time using AngularJS, so feel free to let me know if I'm using things incorrectly or there's a better pattern which would fix my issue.
Thanks!
You're right, there is a better way to do it.
See, your code for transition affects all properties:
.widget.moveUp {
z-index: 100!important;
-webkit-transition: all 1s ease-in-out;
-moz-transition: all 1s ease-in-out;
transition: all 1s ease-in-out;
}
.widget.moveDown {
z-index: 1!important;
-webkit-transition: all 1s ease-in-out;
-moz-transition: all 1s ease-in-out;
transition: all 1s ease-in-out;
}
So my guess is that your transition to z-index is also taking 1 second to happen.
Guessing that, I've took the liberty to change these lines of code to target a transition only on the top property, which is the only one that should be affect in your case.
.widget {
width: 100%;
height: 40px;
position: absolute;
clear: both;
z-index: 1;
-webkit-transition: top 1s ease-in-out 0s;
-moz-transition: top 1s ease-in-out 0s;
transition: top 1s ease-in-out 0s;
}
.widget.moveUp {
z-index: 100!important;
}
.widget.moveDown {
z-index: 1!important;
}
Here, I updated your FIDDLE

Bypassing transition and changing a property instantly

I want to bypass CSS transition and change a property instantly.
I tried to set transition-duration to 0s before the change and then set transition-duration back to its original value:
$('div').css('width', '200px').delay(1000).queue(function() {
$(this).css({
transitionDuration: '0s',
msTransitionDuration: '0s',
mozTransitionDuration: '0s',
webkitTransitionDuration: '0s',
oTransitionDuration:'0s'
}).css('width', '10px').css({
transitionDuration: '2s',
msTransitionDuration: '2s',
mozTransitionDuration: '2s',
webkitTransitionDuration: '2s',
oTransitionDuration:'2s'
})
})​
Fiddle
This obviously doesn't work.
I understand that the spec does not define that behavior for this:
Since this specification does not define when computed values change,
and thus what changes to computed values are considered simultaneous,
authors should be aware that changing any of the transition properties
a small amount of time after making a change that might transition can
result in behavior that varies between implementations, since the
changes might be considered simultaneous in some implementations but
not others.
Is there an easy way to do this?
Note: The property I am changing is transform so .animate() would not be an option.
Since nobody else is posting a valid answer, here goes:
$('div').css('width', '200px').delay(1000).queue(function() {
$(this).css({transition: '0s', width: '10px'}).delay(1).queue(function() {
$(this).css({transition:'2s'});
});
},1000)​;
FIDDLE
Or if it's the other way:
$('div').css({
transition: '0s'
}).css('width', '200px').delay(1000).queue(function() {
$(this).css({width: '10px', transition: '2s'});
});
FIDDLE
jQuery should normalize vendor prefixes these days, so you don't have to type them all yourself.
The issue here is that jQuery attaches all the styles at once, only keeping the last styles, overwriting the previous styles of the same CSS property without ever doing a repaint of the DOM, and testing with native javascript seems to be doing the same thing, so it's probably the browser trying to avoid uneccessary reflows by adding a style just to have it changed in the next line of code, so doing:
$('div').css({
transition: '0s',
width: 200
}).css({
transition: '3s',
width: 10
});
won't work as only the last style is added.
This is where delay() comes into play, the OP's question was already using delay() so there was no reason not to use it, but removing delay() will of course cause the above issue, where the browser doesn't paint the first style, but only the last etc.
As delay() is really just a fancy timeout, it effectively defers the execution of the second setting of the styles, causing two browser repaints.
As this is most likely a browser issue, and not something we can change, deferring the setting of the second style is the only way to make this work, and using a delay will still work even if it's set to just 1 milliseconds, or one could defer the execution with a regular timeout, which is the usual way to defer execution of a script:
$('div').css({
transition: '0s',
width: 200
});
setTimeout(function() {
$('div').css({
transition: '3s',
width: 10
});
});
FIDDLE
The above will work just fine, as the timeout causes the first setting of the style to be painted by the browser, and defers the setting of the style inside the timeout to a later time, but as no time is set, it's executed as soon as the browser can (but still deferred until after the current script has completed), which for the human eye would seem like immediately, and that solves the issue.
Set up an override class that would disable css transitions on an element applied to, !important is perfect for this:
.notransition {
-webkit-transition: none !important;
-moz-transition: none !important;
-o-transition: none !important;
-ms-transition: none !important;
transition: none !important;
}
You can now toggleClass to switch the desired behaviour (smooth transition vs instant change):
$('div').
toggleClass('notransition', true). //or false!
css('width', '200px');
Fiddled. IMO one of the advantages of this approach is that you have clear separation between default element styling and the disable all smooth animations flag. This is also a very "wrappable" reusable approach, i.e. you can easily add an optional boolean property to your existing methods that would indicate whether or not it should be executed with transitions.
NB: sometimes you may want to disable transitions on the page altogether for whatever performance/UX reasons. In that case, you can change the selector to .notransition * and disable transition on all descendant elements.
If you have control of the CSS
The easiest thing to do is tie the animation to some class, and then at what point you want the animation to no longer be bypassed, you add the class, otherwise no animation is ever set. If the reverse, you generally want the animation, but occasionally want to bypass it, then add the class by default and remove it at time of bypassing.
Example CSS
div{
height: 100px;
width: 200px;
background: red;
}
div.doTransition {
width: 10px;
transition: width 2s linear;
-ms-transition: width 2s linear;
-moz-transition: width 2s linear;
-webkit-transition: width 2s linear;
-o-transition: width 2s linear;
}
See fiddle which creates a click event to start animation when it is desired, but this could be some other programmatic trigger to add the class at the time that one no longer wants to bypass it. This fiddle does the opposite, it assumes the animation is present, but on page load immediately bypasses it by removing the class.
The issue is that, since there is no reason for the browser to slow down and execute each operation seperately, it combines them and does both at the same time. Querying offsetHeight is one way to force it to do each operation seperately, as it has to recalculate the height. http://jsfiddle.net/markasoftware/6cTeY/15/ works perfectly
This is the only way I could make it work. jQuery seems to be a bit stubborn.
http://fiddle.jshell.net/8qTpe/1/
P.S. There are some errors in your approach:
You are re-sizing to 200px before the delay, thus using the default CSS settings.
You are re-sizing to 10px before the change of the transition back to 2s.
Now jQuery seems to apply all CSS settings in a row so that's why the whole thing does not seem to work.
I'd go for a rather clean CSS solution
HTML
<div id="foo"></div>
<button class="out">out</button>
<button class="in">in</button>
JS
$('button.out').click(function(){console.log($('#foo').addClass);$('#foo').addClass('out')})
$('button.in').click(function(){$('#foo').removeClass('out')})
CSS
div{
height: 100px;
width: 10px;
background: red;
transition: width 0s linear;
-ms-transition: width 0s linear;
-moz-transition: width 0s linear;
-webkit-transition: width 0s linear;
-o-transition: width 0s linear;
}
div.out {
width: 200px;
transition: width 2s linear;
-ms-transition: width 2s linear;
-moz-transition: width 2s linear;
-webkit-transition: width 2s linear;
-o-transition: width 2s linear;
}
http://jsfiddle.net/6cTeY/19/
I usually do it in this vanilla JS fashion.
FIDDLE
HTML
Suppose you have an element
<div id="element"></div>
CSS
Suppose your element has CSS Transitions already active and background: green
#element {
background: green;
width: 200px;
height: 200px;
-webkit-transition: 'all 0.5s ease-out';
-moz-transition: 'all 0.5s ease-out';
-ms-transition: 'all 0.5s ease-out';
-o-transition: 'all 0.5s ease-out';
}
JS
The element has CSS transitions but we want to change the element's background to BLUE, instantly.
Right after that, we want the element's normal behaviour to return so we can animate it's background to RED.
We need to shut off transitions for a moment and restore them right after.
// grab the element
var element = document.getElementById('element');
// removeTransitions
element.style.webkitTransition = 'none';
element.style.mozTransition = 'none';
element.style.msTransition = 'none';
element.style.oTransition = 'none';
// apply desired 'instant' property
element.style.background = 'blue'; // is applied instantly
// this 10ms timeout is necessary for the transitions to be active again
setTimeout(function() {
element.style.webkitTransition = 'all 5s ease-out';
element.style.mozTransition = 'all 5s ease-out';
element.style.msTransition = 'all 5s ease-out';
element.style.oTransition = 'all 5s ease-out';
// apply desired 'animated' property
element.style.background = 'red'; // is applied smoothly
}, 10);
var ball = document.querySelector('.ball'),
ballSpeed = 2,
button = document.querySelector('button');
// Chane to random speed "instantly" (on button "click")
button.addEventListener('click', ()=>{
ballSpeed = Math.random()*8 + 1;
ball.style.transitionDuration = ballSpeed + 's';
ball.classList.remove('move');
ball.clientHeight; // <--- triggers repaint
ball.classList.add('move');
// set button text
button.textContent = ballSpeed.toFixed(2) + 's';
})
function animate( speed ){
ball.style.transitionDuration = '0s';
ball.classList.remove('move');
ball.clientHeight; // <--- triggers repaint. has to be after "move" class was removed
ball.style.transitionDuration = ballSpeed + 's';
ball.classList.add('move');
ball.removeEventListener('transitionend', animate)
ball.addEventListener('transitionend', animate); // keep rollin..
}
animate();
html, body{ height:100%; overflow:hidden; }
.ball{
position: absolute;
width: 3em;
height: 3em;
left:0; right:0; top:0; bottom:0;
margin: auto;
transition-duration: 2s; /* <-- start speed */
transition-timing-function: linear;
}
.ball::after{
content: '';
display: block;
width: 100%;
height: 100%;
transform: translateX(100%);
border-radius:50%;
background: gold;
}
.ball.move{
transform: rotate(360deg);
}
<button>2s</button>
<div class="ball"></div>
I don't know how this works in JQuery, but you could do this in CSS (at least at the time of writing):
div {
animation: trans 2s;
}
#keyframes trans {
0% {
width: 200px;
}
99.9% {
width: 200px;
}
100% {
width: 10px;
}
}
pure JS solution that should work with JQuery (have not tested).
The problem with the accepted answer is placing a value for the delay, but a better solution is to have a delay of 0. We are gonna use a little trick with the event loop to achieve this:
const button = document.querySelector('button');
function reposition() {
button.style.transition = 'none';
button.style.transform = 'translate(-50%)';
setTimeout(() => {
button.style.transition = '1s';
button.style.transform = 'translate(0)';
}, 0);
}
button.addEventListener('click', reposition);
<button>
Click Me
</button>
This is called a zero delay. It still uses a delay, but you don't have to feel icky about it because this will instantly run when the stack is clear.
If you want to understand why this is, I recommend watching this video
But here's a (messy) short explanation:
Basically what's happening is that setTimeout() will hold the value until a certain amount of time, our time here is 0, but it won't execute yet until the stack is clear, (why? this is, watch the video) because the browser still has to repaint the changes, the re-render will still be in the stack and as it finishes, the function passed to setTimeout() will be executed causing another re-render.
Do I know if this works 100% of the time? In theory, it should, but I'm no expert.

Categories

Resources