w=Hi all, what I am trying to achieve is the animation of a progress bar namely .progress div from 0% width on document.ready to 100% width on document.load however I want this to be animated smoothly - I have a feeling this could be done via CSS but it is not cross browser and at the moment I the width of .progress div goes nearly directly to 100% width. Its containing div #overlay will also fade on document.ready... Any ideas?
Heres what I have at the moment;
CSS
.progress {
width: 100%;
height: 4px;
background: none;
position: absolute;
top: 0;
text-align: left;
}
.progress div {
background: #000;
}
JQuery
var progress = $('.progress div');
$(window).ready(function(){
progress.css('width','0'+'%');
});
$(window).load(function(){
//Set width to 100%
progress.css('width','100'+'%');
// PAGE IS FULLY LOADED
// FADE OUT YOUR OVERLAYING DIV
$('#overlay').fadeOut();
});
HTML
<div id="overlay">
<div class="progress">
<div class="bar"></div>
</div>
<div id="logo">
<img src="images/logo.png">
</div>
</div>
Thanks in advance for any help ;)
EDIT
I have tried using css transitions however the same scenario happens, their just goes straight to 100% instead of going over 4s as stated in the transition statement - this is show below
-webkit-transition: width 500ms ease-out 1s;
-moz-transition: width 500ms ease-out 1s;
-o-transition: width 500ms ease-out 1s;
transition: width 500ms ease-out 1s;
}
Use animate
jsfiddle Example
$(document).ready(function(){
var progress = $('.progress .bar');
//Set width to 100%
progress.animate({
width:'100%'
}, 2000);
setTimeout(function() {
$('#overlay').fadeOut();
}, 4000);
});
The reason it shoots right to 100% is because there is no intermediary between document-ready to window-loaded.
Your JS doesn't have an event to say "Im XYZ% done loading the objects". The browser does - but it's still doing a LOT of work to do that integration (getting the headers for all elements on the page, their file sizes, and the sum as it all comes in). But none of that is exposed to the javascript - that's internal browser engine code.
So you have just one step - from dom-ready to window-loaded - that's why it fires up. The other guy answering your question using a setTimeOut is just simulating a percentage loading - it's not a true representation of the actual percentage.
Unfortunately, you'll never get it. Unless you're doing a lot of REST calls, AJAX calls and loading your objects atomically -- you can sort of simulate it by "I'm loading 10 objects via REST/AJAX/OWIN [please don't] -- trigger a bump up each time one is done" sort of thing.
Related
UPDATED and CLARIFIED
I need to execute some jquery that does an immediate rotate (using css3 transform) on an icon. And then once the icon is rotated I want to animate and scale to 200% of the size. However, since scale and rotate are both one CSS3 property (transform) I am seeing that both of the transitions are occurring as an animation for 0.5s. (in the JQUERY code I also update the location (top, left), but since that is not in the transition: tag, it happens immediately as required).
What I want is the rotate to happen immediately, and the scale to happen over 2s. Any ideas?
CSS:
transition: transform 0.5s;
-webkit-transition: -webkit-transform 0.5s;
JQUERY:
self.pick = function (cmd) {
var pt = Tools.cmdToPoint(cmd);
$(self.bbox).css("position", "fixed");
$(self.bbox).css("top", pt.y - 32);
$(self.bbox).css("left", pt.x - 32);
$(self.bbox).css("opacity", "1");
var theta = self.angle(cmd);
$(self.bbox).css("transform", "rotate(" + theta + "deg) scale(2.0)");
$(self.bbox).css("-webkit-transform", "rotate(" + theta + "deg) scale(2.0)");
}
What happens is that since transition on the item, both the scale and the rotate occur in an animation over 0.5s.
You really have 2 options, but I think nested div's will most likely be your best option. You can use jQuery to control the timing of certain animations, but it will require a decent amount of coding to get it right.
Per Andrea Ligios comment, you should set a delay on the two class so that the transition starts after 0.5s
HTML
<div id="rotate" class="half rotate">
<div id="scale" class="two grow">Rotate</div>
</div>
CSS
.half {
transition: all 0.5s ease-in-out;
-webkit-transition: all 0.5s ease-in-out;
}
.two {
transition: all 2s ease-in-out 0.5s;
-webkit-transition: all 2s ease-in-out 0.5s;
}
#rotate, #scale {
height: 150px;
width: 100px;
text-align: center;
margin: 0 auto;
}
#scale {
border: 1px blue solid; /*for visualization*/
}
.rotate:hover {
transform: rotateZ(180deg);
-webkit-transform: rotateZ(180deg);
}
.grow:hover {
transform: scale(2.0);
-webkit-transform: scale(2.0);
}
Here is a CSS demo fiddle : http://jsfiddle.net/adjit/w4kgP/5/
Your jQuery option involves setting timeouts, the only thing is the reverse animation doesn't go exactly in the reverse order. It will shrink and un-rotate with an interval of .5s. You can ofcourse also set a timeout for mouseout
jQuery Option
$('#rotate-scale').hover(function(){
clearTimeout(timeout);
$this = $(this);
$this.addClass('rotate');
timeout = setTimeout(function(){
$this.css("-webkit-transition", "all 2s ease-in-out");
$this.addClass('grow');
}, 500);
}, function(){
clearTimeout(timeout);
$(this).css("-webkit-transition", "all 0.5s ease-in-out");
$(this).removeClass('rotate');
$(this).removeClass('grow');
});
Here is a jQuery demo fiddle : http://jsfiddle.net/adjit/tR7EY/1/
Short answer: Use GSAP.
Long answer: CSS3 transform properties cannot really be individually animated, unless you happen to be good with transformation matrixes and are ready to write a lot of supporting code for a better animation system. Not only would you have to deal with converting the transform properties into transforms matrices, but you'd also need some sort of system to dynamically mix different matrix states to be actually able to decouple timings. This requires a lot of advanced mathematics and development time, which would most likely be better spent elsewhere.
EDIT: Further reading: How to read individual transform values in js
EDIT2: Depending on what exactly you're trying to do, you might be able to separate the animations by splitting them across several nested divs. Eg. The outermost div handles the scale animation and within it is a div with a rotation animation. CSSdeck example
I'm attempting to use Bootstrap's Carousel to handle content that isn't the same height. The heights will differ based on the browsers width, and there is content below the carousel. I'd like to use CSS to animate the height change between slides. With some help from a friend I almost have this working in FireFox (the first slide jumps, the rest animate) but an obvious bug is happening with the sliding animation in Chrome.
Any input would be great, even if you think I should handle the height animation in a completely different way, please let me know!
Here is the JS and CSS that I think matter, but the whole thing is on JS Fiddle: http://jsfiddle.net/tkDCr/
JS
$('#myCarousel').carousel({
interval: false
});
$('#myCarousel').bind('slid', function(e) {
console.log('slid',e);
});
$('#myCarousel').bind('slide', function(e) {
console.log('slide',e);
var next_h = $(e.relatedTarget).outerHeight();
console.log(next_h);
$('.carousel').css('height', next_h);
});
By commenting out lines 12 and 13 of the JavaScript you can see that the bug is clearly being caused by assigning the variable next_h with the data from '$(e.relatedTarget).outerHeight();'. Even if the variable isn't used it still breaks the animation. Commenting out 11,12, and 13, will show you how the carousel functions normally.
CSS
.carousel {
width: 80%;
margin-left: auto;
margin-right: auto;
background: lightgoldenrodyellow;
-webkit-transition: height .5s ease;
-moz-transition: height .5s ease;
-ms-transition: height .5s ease;
-o-transition: height .5s ease;
transition: height .5s ease;
}
Thank you in advance.
// animate do the same - timeout is not needed
$('#myCarousel').carousel();
$('#myCarousel').bind('slide', function(e) {
$('#myCarousel').animate({height: $(e.relatedTarget).outerHeight()});
});
// After using animate, there is no need for transition in css (or height)
You can get around the problem by delaying the call to outerHeight() by a short timeout:
$('#myCarousel').bind('slide', function(e) {
setTimeout(function () {
var next_h = $(e.relatedTarget).outerHeight();
$('.carousel').css('height', next_h);
}, 10);
});
Also, you probably want to set the height of .carousel to something in the css, otherwise the first transition will begin at height 0, making it drop from the top.
I updated your fiddle here: http://jsfiddle.net/tkDCr/3/
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.
I tried inspecting the elements for this website, but I could not figure out how they got the CSS triangle to move to different nav elements when a different page anchor is clicked.
See website: www.simple.com
The arrow is a CSS sprite contained in http://simple.com/img/sprites.png. It's set up in the CSS with transitions as follows:
#main-nav #nav-arrow {
-webkit-transition: left opacity;
-moz-transition: left opacity;
-o-transition: left opacity;
transition: left opacity;
-webkit-transition-timing-function: ease-in-out;
-moz-transition-timing-function: ease-in-out;
-o-transition-timing-function: ease-in-out;
transition-timing-function: ease-in-out;
-webkit-transition-duration: 0.3s;
-moz-transition-duration: 0.3s;
-o-transition-duration: 0.3s;
transition-duration: 0.3s;
width: 22px;
height: 14px;
position: absolute;
top: 60px;
text-indent: -10000px;
background: url("/img/sprites.png") no-repeat -577px -52px
}
That does the animation when the left property of the CSS changes. The left property is altered by Javascript hooked from the main navigation library that drives the site, NavSimple, in the (customised and minified) https://www.simple.com/js/brawndo.min2175719530.js. The more general NavSimple code to do the navigation also triggers custom Javascript that moves the arrow's left position to halfway along the active navigation element (it's subtracting eleven pixels because the arrow is 22 pixels wide):
this.nav_arrow.setStyle("left",d.getPosition(this.nav_wrapper).x+(d.getWidth()/2-11))}
And that's basically how it works. Nice site, very well-engineered, I'd say. (The navigation arrow is actually a div containing a letter "V", so it'll still look like an arrow even if the background images don't load, which I thought was a nice touch.)
Having said all that, I think this question might be a bit too specific to survive...
It doesn't seem like the triangle moves until the page has scrolled to the specified content. You could use the window.scrollY value to evaluate to which button the triangle should move to.
I'd guess the animation for the triangle is done by a function which gets called at both the window.onscroll event. And by a callback to the scrolling animation function triggered by the buttons.
Yeah there is some very cool stuff going on on that site. Its all CSS transitions, I would expect the use of Adobe Edge or LESS with something like that.
The brawdndo.js seems to be apart of moo-growing-input
demo here http://www.ohloh.net/p/moo-growing-input
source here https://github.com/3n/moo-growing-input
I'd bet it's JavaScript just animating the triangle, you couldn't possibly do this in pure CSS.
I want my page to open with a picture and I want that picture to fade-out 10 seconds after. Which way is the best way I can do it ? Is there any way I can do it with Css3 ?
So long as you've given the element to fade out an id (or have some way to reference it from JavaScript):
window.setTimeout(
function(){
$('#pictureID').fadeOut('slow');
},10000);
JS Fiddle demo.
I'm assuming that you're using the image as a splash screen, of sorts? If so, then you can use position: absolute to position that image over the content of the page, and then fade out to reveal the contents below (JS Fiddle demo).
If, however, you also want the user to be able to hover over the image to hold it in place then the following could be used (the above, but with a couple of amendments):
var fadeAnim = window.setTimeout(
function(){
$('#i').fadeOut('slow');
},10000);
$('#i').hover(
function(){
window.clearTimeout(fadeAnim);
},
function(){
$(this).fadeOut(500);
});
JS Fiddle demo.
References:
JavaScript (from the Mozilla Developer Network's JavaScript resource):
window.setTimeout().
window.clearTimeout().
jQuery (from the jQuery API):
fadeOut().
setTimeout(function() {
$('.imgClass').fadeOut('slow')
}, 10000);
You will have to use Javascript to do that. You can cross Javascript (our jQuery) with CSS3 but for cross-browser issue you'd better do it in full jquery. To do so, you can use load(), delay() and fadeOut().
Try :
$('#yourImg').ready(function(){
$(this).delay(10000).fadeOut();
});
You can use setTimeout() to delay the start of the fade, and then you can fade it out using either jquery(or another javascript library such as mootools) or you can add a class to the element and have it transition using a css3 transition. Since the jQuery version has already been posted, i'll post the css3 version. http://jsfiddle.net/Tentonaxe/3Vnt7/
CSS:
#demo {
transition: opacity 2s ease-in;
-moz-transition:opacity 2s ease-in;
-o-transition: opacity 2s ease-in;
-webkit-transition: opacity 2s ease-in;
border: 4px solid green;
background-color: #ededed;
width: 75px;
height: 75px;
}
.hidden {
opacity: 0.0;
}
HTML:
<div id="demo"></div>
Javascript:
setTimeout(function(){
document.getElementById('demo').className = "hidden";
},10000);