How to re-animate CSS3 animations on class change - css

So I've these CSS3 script
#place.us .level1 { background-position: -100px; background-color: #333; }
#place.gb .level1 { background-position: -100px; background-color: #CCC; }
#-webkit-keyframes place-pop-livel1 {
0% { bottom: -100px; }
100% { bottom: 30px; }
}
#place .level1 {
animation: place-pop-livel1 2s ease-out;
-moz-animation: place-pop-livel1 2s ease-out;
-webkit-animation: place-pop-livel1 2s ease-out;
}
When the page first loads, the div has #place.us and the animation works perfectly. Now I want to change the class of the div to 'gb' to make it #place.gb using jquery and as soon as the class is changed, I want the same animation to happen.
My jquery code is simple
$('.change-city').live('click', function(){
var city = $(this).data('city'); //gb or us
$('#place').removeClass().addClass(city);
});
The class changes and the .level1 property is affected as declared in the CSS but the animation doesn't happen. How do I make sure that the animation happens?

I'd recommend using CSS transitions as they have better browser coverage, they are simpler to manage and they fallback better (if the browser doesn't support transitions it does the same thing without the animation).
You problem can be solved like this:
// after load add the animation
$(".level1").addClass("pop");
// after the animation is done hide it again
$(".level1").bind("webkitTransitionEnd mozTransitionEnd oTransitionEnd msTransitionEnd transitionend", function(){
$(this).removeClass("pop");
});
$('.change-city').live('click', function(){
var city = $(this).data('city'); //gb or us
$('#place').removeClass().addClass(city).find(".level1").addClass("pop");
});
And the CSS
#place.us .level1 {background-color: #333; }
#place.gb .level1 {background-color: #CCC; }
#place .level1 {
position: absolute;
background-color: #000;
width: 100px;
height: 100px;
bottom: -100px;
-webkit-transition: bottom 2s ease;
-moz-transition: bottom 2s ease;
-o-transition: bottom 2s ease;
-ms-transition: bottom 2s ease;
transition: bottom 2s ease;
}
#place .pop {
bottom: 30px
}
You can check out the jsfiddle here: http://jsfiddle.net/EmsXF/

Related

Opacity transition without hover

I have the following class:
.dot{
width:40px;
height:40px;
position:absolute;
background: url(https://www.sporedev.ro/pleiade/images/Frunza.png);
background-size: 100% 100%;
z-index:999;
margin-top:-60%;
pointer-events:none;
}
I modified the class like this:
.dot{
width:40px;
height:40px;
position:absolute;
background: url(https://www.sporedev.ro/pleiade/images/Frunza.png);
background-size: 100% 100%;
z-index:999;
margin-top:-60%;
pointer-events:none;
-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;
}
What I tried to do was to apply a transition so that the div is not initially shown when the page is opened but it reaches opacity: 1; after 1s has passed.
I did some research and all I could find on SO and Google was related to hovering. I tried applying "opacity: 0;" to my class but then the transition wouldn't take place, the div would just stay hidden.
Is there any way to accomplish an opacity transition without a hover state using CSS?
You can accomplish this with CSS3 animation:
.dot{
width:40px;
height:40px;
position:absolute;
background:url(https://www.sporedev.ro/pleiade/images/Frunza.png);
background-size:100% 100%;
z-index:999;
pointer-events:none;
animation:fadeIn 1s ease-in;
}
#keyframes fadeIn {
from {
opacity:0;
}
to {
opacity:1;
}
}
<div class="dot"></div>
You can achieve this using css animations.
The animation is set using the #keyframes rule. To illustrate in the example, I removed the margin top; this is not a necessary change in your code.
.dot {
width: 40px;
height: 40px;
position: absolute;
background: url(https://www.sporedev.ro/pleiade/images/Frunza.png);
background-size: 100% 100%;
z-index: 999;
// margin-top:-60%;
pointer-events: none;
animation: fadein 1s ease-in;
}
#keyframes fadein {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
<div class="dot"></div>
Yes, use JavaScript to trigger the transition. That is the answer to your question. A transition only happens when there is something to transition to. Just sepcifying a transition on an element does not trigger the transition. Change does. When the element first loads there is nothing to transition to.

Transition not working on backdrop opacity to 0 when class is removed

I have a backdrop on my site that opens whenever it needs to. Modals, mobile nav etc.
I'd like to get the opacity of the backdrop to fade, however I can't get it to transition properly when the --open class is removed from the backdrop.
I've gone through a few iterations so any ideas on how to make it work AND be better css is appreciated.
Here's a demo demonstrating the ease effect occuring when --open is applied to the backdrop, but will not work when it is removed.
https://jsfiddle.net/p2yz0rvr/
For futures sake here's the code:
.backdrop {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: -9999999999;
opacity: 0;
text-align: center;
transition: opacity 0.3s ease-in;
}
.backdrop--open {
opacity: 0.75;
z-index: 2;
background: #000;
transition: opacity 0.4s ease-out;
}
The problem is that you don't have a background set on the initial .backdrop state, the background is set on the element .backdrop--open.
Since you are only transitioning the opacity property, the transition doesn't occur when you remove the .backdrop--open class. Therefore you would need to move background to the initial .backdrop state in order for the transition to take place when removing the class.
Updated Example
.backdrop {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: -1;
opacity: 0;
text-align: center;
background: #000;
transition: opacity 0.3s ease-in;
}
.backdrop--open {
opacity: 0.75;
z-index: 2;
transition: opacity 0.4s ease-out;
}
As an alternative, you could also keep your initial code and just transition the background property in addition to the opacity property (without having to change where the background is set).
Keep in mind that the z-index property can be transitioned, so depending on what you're trying to achieve you may only want to target those two properties rather than using all.
Updated Example
.backdrop {
/* ... */
transition: background 0.3s ease-in, opacity 0.3s ease-in;
}
.backdrop--open {
/* ... */
background: #000;
transition: background 0.4s ease-out, opacity 0.4s ease-out;
}

Keyframe CSS animation overwrites hover transition

I am afraid there are similar questions to this but I didn’t found a concrete solution, so I created a fiddle:
http://jsfiddle.net/Garavani/yrnjaf69/2/
<div class= "category_item">
<div class= "cat_button">
<span class="title_cat">TEXT</span>
</div>
</div>
CSS:
.category_item {
position: absolute;
background-color: #999;
top: 100px;
left: 50px;
width: 200px;
height: 200px;
/* seems to be overwriten by animation keyframes */
-webkit-transition: -webkit-transform 0.215s ease-in-out;
transition: transform 0.215s ease-in-out;
cursor: pointer;
}
.category_item:hover {
-webkit-animation-name: easeBack;
animation-name: easeBack;
-webkit-animation-duration: 1s;
animation-duration: 1s;
-webkit-animation-fill-mode: forwards;
animation-fill-mode: forwards;
}
#-webkit-keyframes easeBack {
0% {
-webkit-transform: translateY(0);
transform: translateY(0);
}
50% {
-webkit-transform: translateY(-50px);
transform: translateY(-50px);
}
100% {
-webkit-transform: translateY(-30px);
transform: translateY(-30px);
}
}
.cat_button {
position: absolute;
width: 200px;
height: 55px;
bottom: 0;
border: 2px solid #fff;
color: #fff;
-webkit-transition: background 0.215s ease-in-out, border 0.215s ease-in-out, color 0.215s ease-in-out;
transition: background 0.215s ease-in-out, border 0.215s ease-in-out, color 0.215s ease-in-out;
}
.category_item:hover .cat_button {
background: #fff;
border-color: #fff;
color: #511c5b;
}
In this (simplified) animation everything works fine except for when the mouse leaves the entire box. The animation starts from it original state, but abruptly.
The basic transition time (and ease) is ignored because it seems the keyframes have higher importance and overwrite it.
What I need is the keyframe animation triggering AND when the mouse leaves it should turn back to the original state smoothly.
Is there a solution for this
1) in pure CSS
2) maybe with some little javascript only?
Thanks in advance for help and ideas!
EDIT:
After implementing the solution offered kindly by Toni this is the correct fiddle:
http://jsfiddle.net/yrnjaf69/40/
Thanks again Toni!
EDIT 2:
Sadly, yet, there is one question left. The part with the keyframes is not executed on Firefox even though I added all the -moz- vendors, too, in this fiddle:
http://jsfiddle.net/dr6Ld0wL/1/
Why?
PS: As far as I tested for now it works even in Opera (Beta). Only browser resisting is Firefox
EDIT 3:
The correct (working) code is now in this fiddle:
http://jsfiddle.net/dr6Ld0wL/16/
The keyframes also need to be explicitly divided in vendor prefixes. Jesus Christ. Those prefixes…
Here is a jsfiddle that achieves this.
.demo-hover {
position: relative;
margin: 100px;
animation: complexProcessReversed 2s ease-in forwards;
width: 160px;
height: 160px;
background-color: #88d;
}
.demo-hover:hover {
animation: complexProcess 2s ease-in forwards;
width: 100px;
height: 100px;
background-color: #732;
}
#keyframes complexProcess {
/* keyframes */
}
#keyframes complexProcessReversed {
/* keyframes (opposite) */
}
The animation out is assigned in the css in the main class, then the hover state kicks in on hover and css re-applies the original class properties on unhover.
The animation does trigger backwards on page load, so you might like to think of tweaking your animation to take this into account, like this example, pinched from this answer. Alternatively, use javascript (or jquery), like this example where the animations are triggered by adding and removing classes to the target using jquery:
JavaScript
$('.demo-hover').hover(
function() {
// mouse in
$(this).removeClass('forwards--reversed').addClass('forwards');
},
function() {
// mouse out
$(this).removeClass('forwards').addClass('forwards--reversed');
}
);
CSS
.forwards {
animation: complexProcess 2s ease-in forwards;
width: 100px;
height: 100px;
background-color: #732;
}
.forwards--reversed {
animation: complexProcessReversed 2s ease-in forwards;
width: 160px;
height: 160px;
background-color: #88d;
}
Also, I'd use #keyframe or transition. Use transition if you just need a simple even change from n to m but when things are more complex, such as one thing changing evenly over 100% but another thing not starting until 50% off the animation has played, then use a #keyframe
Using both will cause confusion, especially if you're trying to animate the same properties.
Finally css vendor prefixes are required

Is it possible in CSS to transition through a third color when using a hover transition?

I have an element that is red in resting state, and green when the user hovers their cursor over it. I have it set to ease the transition for 0.4s.
Instead of having the colour transition straight from red to green, I'd like it to pass through yellow at the midway point. So when the user mouses over it, it goes from red to yellow to green in one smooth transition. Is this possible?
This is my current code.
.element {
background-color: red;
-webkit-transition: all 0.4s ease;
transition: all 0.4s ease;
}
.element:hover {
background-color: green;
}
You can use the CSS #keyframes animation syntax.
#keyframes animate-color {
0% { color: red; }
50% { color: yellow; }
100% { color: green; }
}
element:hover {
animation: animate-color 0.4s forwards;
}
Change the 0.4s value to control how fast the animation runs.
Here's an example for Chrome using -webkit-animation and #-webkit-keyframes:
https://jsfiddle.net/ahm2u8z2/1/
Make sure you cover all browser possibilities as the syntax is different for Chrome, Firefox, Internet Explorer and Opera.
https://css-tricks.com/snippets/css/keyframe-animation-syntax/
Here's more information for configuring your animations in CSS3, you can control things such as animation-delay, animation-direction, and many more.
https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Using_CSS_animations
Alteratively, if you're not up to using #keyframes (although I don't see why not), you can use pseudo elements to act as the middle color. All you need to do is control the delay of the transitions using transition-delay:
.element {
width: 100px;
height: 100px;
background-color: red;
-webkit-transition: all 0.4s ease;
transition: all 0.4s ease;
position: relative;
-webkit-transition-delay: 0.4s;
transition-delay: 0.4s;
}
.element:before {
position: absolute;
width: 100%;
height: 100%;
content: "";
background: green;
-webkit-transition: all 0.4s ease;
transition: all 0.4s ease;
opacity: 0;
-webkit-transition-delay: 0s;
transition-delay: 0s;
}
.element:hover:before {
opacity: 1;
-webkit-transition-delay: 0.4s;
transition-delay: 0.4s;
}
.element:hover {
background-color: yellow;
-webkit-transition-delay: 0s;
transition-delay: 0s;
}
<div class="element"></div>
you could use keyframes for this:
.element {
background-color: red;
height: 300px;
width: 300px;
}
.element:hover {
-webkit-animation: changeColor 0.4s forwards;
animation: changeColor 0.4s forwards;
}
#-webkit-keyframes changeColor{
0%{background: red;}
50%{background:yellow}
100%{background:green}
}
#keyframes changeColor{
0%{background: red;}
50%{background:yellow}
100%{background:green}
}
<div class="element"></div>
This works by adding the keyframe sequence when the element is hovered, and not during the actual element's creation (so the keyframes only work during the hovered stage).
The forwards declaration is used so that the animation will 'pause' on the '100%' keyframe, rather than looping back and 'finishing where it started'. I.e. the first keyframe.
Please note: Other prefixes will need to be included see here for more info.

jquery live() click function: class not being removed

I'm using jQuery to show a success message after a form is submitted. The form is created using the wordpress plugin Contact Form 7. The class wpcf7-mail-sent-ok is added dynamically by the plugin ajax submission script. I'm trying to make it so that when the user clicks on the message, it fades out and then dissappears. For some reason though the removeClass method isn't working.
Can anyone see any reason why it shouldn't be working? The timeout function is definitely working as I tested it with an "alert()" call. Thanks for your help.
PS... i'm using LESS css so that explains the .opacity() syntax in the css posted here.
HTML:
<div class="wpcf7-response-output wpcf7-mail-sent-ok"><div class="image"></div></div>
Jquery + CSS
var $sent = $('.wpcf7-mail-sent-ok ');
function remove() {$sent.hide().removeClass('wpcf7-mail-sent-ok hide').removeAttr('style')}
$sent.live("click", function(){
$(this).addClass('hide');
setTimeout(remove,400)
});
.wpcf7-response-output {
width: 100%;
height: 100%;
position: fixed;
top: 0;
left: 0;
z-index: -1;
background: transparent;
opacity: 0;
-moz-opacity: 0;
.transition(opacity,.4s);
}
.wpcf7-response-output.wpcf7-mail-sent-ok .image {
width: 400px;
height: 138px;
display: block;
position: absolute;
z-index: 2000;
top: 50%;
left: 50%;
margin: 0;
background: url(assets/images/loading.png) no-repeat;
background-size: 0 0;
-webkit-transition: margin .4s ease-in-out;
-moz-transition: margin .4s ease-in-out;
-o-transition: margin .4s ease-in-out;
-ms-transition: margin .4s ease-in-out;
transition: margin .4s ease-in-out;
-webkit-animation: pulse 400ms ease-out infinite alternate;
-moz-animation: pulse 400ms ease-out infinite alternate;
-o-animation: pulse 400ms ease-out infinite alternate;
animation: pulse 400ms ease-out infinite alternate
}
.wpcf7-response-output.wpcf7-mail-sent-ok {z-index: 1000; background-color: rgba(255,255,255,.7); .opacity(1)}
.wpcf7-response-output.wpcf7-mail-sent-ok .image {
height: 132px;
position: absolute;
margin: -66px 0 0 -200px;
background-size: 100% 100%;
background: url(assets/images/img-sent.png) no-repeat center center;
}
.wpcf7-mail-sent-ok.hide {.opacity(0); z-index: -1}
It doesn't work because at the point where you define the function remove, the value of $sent has already be determined to be a jQuery object that matches no elements. This is because the matching happens as soon as you write
var $sent = $('.wpcf7-mail-sent-ok ');
At this time there is no "mail sent" element present yet.
The easiest way to fix this is to re-evaluate the selector within remove:
function remove() {
$('.wpcf7-mail-sent-ok').hide()
.removeClass('wpcf7-mail-sent-ok hide')
.removeAttr('style');
}
Another solution would be to just use this inside the click handler and pass it as a parameter to remove:
function remove(el) {
$(el).hide()
.removeClass('wpcf7-mail-sent-ok hide')
.removeAttr('style');
}
$sent.live("click", function(){
$(this).addClass('hide');
setTimeout(function() { remove(this); },400)
});
Of course it's even better to just use jQuery's built-in delay and get rid of remove altogether:
$sent.live("click", function(){
$(this).addClass('hide')
.delay(400)
.hide(0) // need to pass 0 as a parameter
.removeClass('wpcf7-mail-sent-ok hide')
.removeAttr('style');
});
I don't see any code to fade out the element. The reason its not working is same as mentioned by #Jon. You can try to use anonymous funciton and indside this function this will point to the element on which click is trigger. Try this.
$('.wpcf7-mail-sent-ok ').live("click", function(){
var $this = $(this).addClass('hide');
setTimeout(function(){
$this
.hide()
.removeClass('wpcf7-mail-sent-ok hide')
.removeAttr('style')
},400)
});

Resources