Multiple CSS Transforms on class change using the CSS animation property - html

How do I activate the CSS animation when the .move class is added to the .box using only CSS? The animation should translate first and when the translate has finished the rotate should begin where the translate ended. Also, how do I make the end state of the animation to be persistent at 100% and reset to 0% when the .move class is removed?
$(".test").click(function(){
$(".box").toggleClass("move")
});
body{
padding: 45px;
}
.test{
margin-top: 15px;
}
.box{
height: 45px;
width: 45px;
background: black;
}
.move{
background: blue;
}
.box{
animation: slide 0.5s, rotate 0.5s;
animation-delay: 0s, 0.5s;
}
#keyframes slide{
100%{
transform: translateX(450px);
}
}
#keyframes rotate{
100%{
transform: rotate(45deg);
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="box">
</div>
<button class="test">Toggle</button>

You can add multiple transforms by placing them together:
transform:translateX(450px) rotate(45deg);
To do this with a key-frame animation, you want to do all stages as a single animation. You will want to apply the animation to the .move class and set animation-fill-mode: forwards to persist the last frame until the class is removed.
$(".test").click(function(){
$(".box").toggleClass("move")
});
body{
padding: 45px;
}
.test{
margin-top: 15px;
}
.box{
height: 45px;
width: 45px;
background: black;
}
.move{
background: blue;
animation: slide 1s;
animation-fill-mode: forwards;
}
#keyframes slide{
50%{
transform: translateX(450px);
}
100%{
transform:translateX(450px) rotate(45deg);
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="box">
</div>
<button class="test">Toggle</button>

That is possible by setting multiple transitions on the element, combined with the transition-delay property.
One note: since each transition has a one to one correspondence to a property, and since you are using the transform property for both the "move" and "rotate" operations, it won't work the way you've written it.
For the "move" operation, I am using margin-left rather than the transform property. You can use any method, as long as it is animatable and doesn't overload a property that you are using for one of the other transitions.
$(".test").click(function(){
$(".box").toggleClass("move")
});
body {
padding: 45px;
}
.test {
margin-top: 15px;
}
.box {
height: 45px;
width: 45px;
background: black;
transition:
margin-left 0.5s,
transform 0.5s;
/* delays for when the .move class was just removed */
transition-delay: 0.5s, 0s;
}
.box.move {
background: blue;
margin-left: 450px;
transform: rotate(45deg);
/* delays for when the .move class was just added */
transition-delay: 0s, 0.5s;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="box">
</div>
<button class="test">Toggle</button>
You can also specify the delay directly in the transition shorthand property, like this.
/* transitions for when the .move class was just removed */
transition:
margin-left 0.5s 0.5s,
transform 0.5s 0s;

It seems what you're looking for is a solution based on transition, not animation (unless I misunderstand what you're looking for, in which case please comment):
$(".test").click(function(){
$(".box").toggleClass("move")
});
.test, .box {
margin-top: 15px;
}
.box {
height: 45px;
width: 45px;
background: black;
position: relative;
left: 0;
transition: left 5s, transform 5s linear 5s;
}
.box.move {
background: blue;
left: 450px;
transform: rotate(45deg);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="box">
</div>
<button class="test">Toggle</button>

This may kinda invalidate what you're trying to do, but you're setting transform twice - if you need to target multiple transform properties on one element, you need to do it in one tranform declaration, like this:
.box{
animation: boxStuff 0.5s
}
#keyframes boxStuff{
100%{
transform: translateX(450px) rotate(45deg);;
}
}
Otherwise whichever is further down is just overriding the other. Maybe you can use a margin or something instead of translateX to work around this?
For the other half of your question, you should be able to add this to the .move class to stop on the last animation frame until the move class is removed.
animation-fill-mode: forwards;

If I understood you correctly, this is the result you want.
<a class="test">Toggle</a>
<div class="box"></div>
.box {
width: 200px;
height: 200px;
margin-left: 0;
background: gold;
transform: rotate(0deg);
transition: transform .3s 0s, margin .3s .3s;
}
.move {
margin-left: 50px;
transform: rotate(45deg);
transition: margin .3s 0s, transform .3s .3s;
}
and here's a fiddle https://jsfiddle.net/VilleKoo/owsm0f7h/1/

Related

How to make 2 chained transforms, the first with transition and the following with no transotions?

I need to add 2 chained transforms, one animated and the second with no animations. Something like:
transition: transform 500ms;
transform: translateX(100%);
and then, after 500ms:
transform: translateX(200%); // this time without any transition or, in other words, with transition time == 0ms.
So the object will translate the first 100% width on the X axis with an animation, and than directly go further to 200% without animating, just plain set.
How to?
You can use animation like below:
.box {
width: 100px;
height: 100px;
background: red;
animation: change 1s forwards;
}
#keyframes change {
50% {
transform: translateX(100%);
}
50.1%, 100% { /*change right after 50%*/
transform: translateX(200%);
}
}
<div class="box"></div>
With transition you can consider 2 divs:
.container {
display:inline-block;
transition:0s 0.5s transform;
}
.box {
width: 100px;
height: 100px;
background: red;
transition:0.5s transform;
}
body:hover .container,
body:hover .box{
transform: translateX(100%);
}
<div class="container">
<div class="box"></div>
</div>

Why can´t i animate the scali when i make another animation with keyframes?

I want a picture to slide (with keyframes), and wen :hover that its scale grows, and when :active, decrease its scale. When i do so, it only slides, :hover and :active don´t work... Please help
#slide-right {
margin-left: 25px;
margin-right: 25px;
margin-bottom: 25px;
height: 250px;
box-shadow: 0px 1px 5px grey;
border-radius: 10px;
transition: .5s;
animation: slide-right 1s ease-out both;
}
#slide-right:hover {
transition: .5s;
transform: scale(1.04);
}
#slide-right:active {
transition: .2s;
transform: scale(0.95);
}
#keyframes slide-right {
0% {
transform: translateX(0);
}
100% {
transform: translateX(+200px);
}
}
<img src="https://www.w3schools.com/w3css/img_lights.jpg" id="slide-right">
#slide-right {
position: relative;
margin-left: 25px;
margin-right: 25px;
margin-bottom: 25px;
height: 250px;
box-shadow: 0px 1px 5px grey;
border-radius: 10px;
transition: .5s;
animation: slide-right 1s ease-out forwards;
}
#keyframes slide-right{
0% {
left: 0px;
}
100% {
left: 200px;
}
}
#slide-right:hover {
transition: .5s;
transform: scale(1.04);
}
#slide-right:active {
transition: .2s;
transform: scale(0.95);
}
<img src="https://www.w3schools.com/w3css/img_lights.jpg" id="slide-right">
It is happening because your key-frames animation is using css transform property and css for hover also uses transform to scale the image. So, only one of it will work at a time.
As a workaround for this problem, you can animate the entry of image using position.
Add position:relative to #slide-right and update your key-frames to 0%{left:0} and 100%{left:200px}.
For working example, please refer : this

CSS hover animations playing on page load

I've been playing around with animations on hover with pure CSS, applying the animation to element:hover and then the same animation to the regular element in reverse so that when the mouse is moved away the element returns to it's original state, this works fine however any animation that is fired when a user moves their mouse away from an element also runs on page load. I understand why this happens, but I would like to know if there's a way to stop it at all? Preferably not using JS but I don't see how that would be possible really
Current code being used, simple animations on hover:
.image{
animation: hoverout 1s ease-in-out forwards;
}
.image:hover{
animation: hover 1s ease-in-out forwards;
}
#keyframes hover{
0%{
opacity: 0;
}
100%{
opacity: 0.5;
}
}
#keyframes hoverout{
0%{
opacity: 0.5;
}
100%{
opacity: 0;
}
}
You do not need to use animation and keyframes on such a simple hover. Use transition instead. A transition simply transitions between 2 points, in this case between the hover state and the non-hover state.
It would look something like this:
.image {
opacity: 0;
transition: opacity 300ms;
}
.image:hover {
opacity: 1;
}
In this case I set the opacity to transition on hover. You can add more values to this with commas such as transition: opacity 300ms, color 300ms or simplify it by transitioning everything transition: all 300ms, although that will take more performance.
Well, this is a problem.
1) you can use visibility to solve it. Try this:
setTimeout(function(){
$('.image')[0].style.visibility = 'visible';
}, 1000)
element {
visibility: hidden;
}
element:hover {
visibility: visible;
}
$(document).ready(function ($) {
setTimeout(function(){
$('.image')[0].style.visibility = 'visible';
}, 1000)
});
.image-parent {
border: 1px solid;
width: 100px;
height: 100px;
}
.image-parent .image {
width: 100%;
height: 100%;
background: red;
visibility: hidden;
opacity:0;
animation: hoverout 1s ease-in-out;
}
.image-parent:hover .image {
visibility: visible;
animation: hover 1s ease-in-out forwards;
}
#keyframes hover {
0% {
opacity: 0;
}
100% {
opacity: 0.5;
}
}
#keyframes hoverout {
0% {
opacity: 0.5;
}
100% {
opacity: 0;
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div class="image-parent">
<div class="image"></div>
</div>
Here may help u.
2) If you are using animation and keyframe, u can replace them by transition and opacity. Eg:
element {
opacity:0;
transition:opacity 1s, transform 0.5s;
}
element:hover {
opacity:1;
transform : rotateX(90deg);
}
Here may help u.
.image-parent {
border: 1px solid;
width: 100px;
height: 100px;
}
.image{
width: 100%;
height: 100%;
border: 1px solid;
background: red;
opacity: 0;
transition: opacity 1s;
}
.image:hover{
opacity: 0.5;
}
<div class="image-parent">
<div class="image"></div>
</div>

Creating a box flap open effect using only CSS

I tried to create this effect using transitions. It should look like you are opening a box.
There are 2 problems:
The order in which the box closes is same as in which it opens. Is there anyway to close the box in reverse order of its opening so that the box goes back in the same state it was when closed?
The ends of the green and yellow flaps are hidden during transition because of the red and blue flaps, so it doesn't look 3D. Is there a way I can show all flaps in 3D way?
I would prefer if the solution was in pure CSS , no JavaScript please.
#box {
position: relative;
top: 170px;
left: 170px;
width: 300px;
height: 300px;
border: 1px solid black;
perspective: 800px;
}
#flap1, #flap2, #flap3, #flap4 {
position: absolute;
}
#flap1 {
background-color: red;
width: 150px;
height: 300px;
z-index: 1;
transform-origin: 0 0;
transition: transform 1s;
}
#flap2 {
left: 150px;
background-color: blue;
width: 150px;
height: 300px;
z-index: 1;
transform-origin: 100% 0;
transition: transform 1s ease 0.3s;
}
#flap3 {
background-color: green;
width: 300px;
height: 150px;
transform-origin: 0 0;
transition: transform 1s ease 0.6s;
}
#flap4 {
background-color: yellow;
top: 150px;
width: 300px;
height: 150px;
transform-origin: 0 100%;
transition: transform 1s ease 0.9s;
}
#box:hover #flap1{
transform: rotateY(-170deg);
}
#box:hover #flap2{
transform: rotateY(170deg);
}
#box:hover #flap3{
transform: rotateX(170deg);
}
#box:hover #flap4{
transform: rotateX(-170deg);
}
<html>
<head>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div id="box">
<div id="flap1"></div>
<div id="flap2"></div>
<div id="flap3"></div>
<div id="flap4"></div>
</div>
</body>
</html>
For Question 1:
If you give the delay in forward order for the :hover selectors and in the reverse order within default selectors, it will achieve the exact reverse animation.
For Question 2:
The fix and the explanation are as follows:
For part of the transition duration, the green and yellow boxes don't look like they have 3D effect because there are a couple of elements with higher z-index which is being placed above. This prevents the stretched area (due to perspective rotate) from showing up and thus it looks like it's only 2D (while it actually is not). To overcome this, we need to instruct the browsers to preserve the 3D aspect of the transform. This is done using transform-style: preserve-3d.
When we do the above, the flaps will all open with a 3D effect but near the start of the animation and its end, we will see a flicker on the blue flap when the transition actually starts and ends for the blue flap. It seems like this is because the z-index loses effect when 3D transform is used and there is a small amount of time between the losing of the z-index effect and starting of the preserve-3D effect during which the blue flap temporarily goes behind. To address this, the 3D equivalent of z-index: 1 (which is, translateZ(1px)) is added. The translate in Z-axis brings the element closer by 1px to your eye and keeps it above the yellow and green flaps.
Finally, despite all the above, there is a small glitch at the end of hover out animation, where the green flap shows through the blue flap. To overcome this, I had changed the delay timings a bit.
(Contrary to what I originally mentioned, the translateZ(0px) is not required and can be removed.)
#box {
position: relative;
top: 170px;
left: 170px;
width: 300px;
height: 300px;
border: 1px solid black;
perspective: 800px;
transform-style: preserve-3d;
}
#flap1, #flap2, #flap3, #flap4 {
position: absolute;
}
#flap1 {
background-color: red;
width: 150px;
height: 300px;
z-index: 1;
transform: translateZ(1px);
transform-origin: 0 0;
transition: transform 1s 1.5s;
}
#flap2 {
left: 150px;
background-color: blue;
width: 150px;
height: 300px;
z-index: 1;
transform: translateZ(1px);
transform-origin: 100% 0;
transition: transform 1s ease 1s;
}
#flap3 {
background-color: green;
width: 300px;
height: 150px;
transform-origin: 0 0;
transition: transform 1s ease 0.5s;
}
#flap4 {
background-color: yellow;
top: 150px;
width: 300px;
height: 150px;
transform-origin: 0 100%;
transition: transform 1s ease;
}
#box:hover #flap1 {
transform: rotateY(-170deg) translateZ(1px);
transition: transform 1s ease;
}
#box:hover #flap2 {
transform: rotateY(170deg) translateZ(1px);
transition: transform 1s ease 0.5s;
}
#box:hover #flap3 {
transform: rotateX(170deg);
transition: transform 1s ease 1s;
}
#box:hover #flap4 {
transform: rotateX(-170deg);
transition: transform 1s ease 1.5s;
}
<div id="box">
<div id="flap1"></div>
<div id="flap2"></div>
<div id="flap3"></div>
<div id="flap4"></div>
</div>

How to scale div smoothly in css using keyframes

I want to smoothly scale the div from ratio 0.06 to 1 using css on mouseover.but i m not able to get that effect.
Here is what i have tried
<!DOCTYPE html>
<html>
<head>
<style>
div {
width: 100px;
height: 100px;
background: red;
-webkit-transition: transform 2s; /* For Safari 3.1 to 6.0 */
transition: width 2s, height 4s;
}
div:hover {
transform:scaleX(0.06);
animation-name: example;
animation-duration: 1s;
}
#keyframes example {
25% {transform:scaleX(0.200);}
50% {transform:scaleX(0.500);}
75% {transform:scaleX(0.700);}
100% {transform:scaleX(1);}
}
</style>
</head>
<body>
<p><b>Note:</b> This example does not work in Internet Explorer 9 and earlier versions.</p>
<div>jhk</div>
<p>Hover over the div element above, to see the transition effect.</p>
</body>
</html>
How can i do this?
You didn't really specify how you want to transition everything so here is a basic example:
div {
width: 100px;
height: 100px;
background: red;
transition: all ease-in 2s;
transform:scale(0.06);
}
div:hover {
transform:scale(1);
}
You don't need keyframes for smooth animations. Something simple like that can be accomplished with simple CSS transforms.
Working fiddle: http://jsfiddle.net/mh90y3xv/
try this. You don't need transition when using key frames
<!DOCTYPE html>
<html>
<head>
<style>
div {
width: 100px;
height: 100px;
background: red;
-webkit-transform:scaleX(0.06);
transform:scaleX(0.06);
}
div:hover {
animation-name: example;
animation-duration: 1s;
animation-fill-mode: forwards;
}
#-webkit-keyframes example {
0% {-webkit-transform:scaleX(0.06);}
100% {-webkit-transform:scaleX(1);}
}
#keyframes example {
0% {transform:scaleX(0.06);}
100% {transform:scaleX(1);}
}
</style>
</head>
<body>
<p><b>Note:</b> This example does not work in Internet Explorer 9 and earlier versions.</p>
<div>jhk</div>
<p>Hover over the div element above, to see the transition effect.</p>
</body>
</html>
No need to use #keyframes just use transition.
Here's the JsFiddle link.
HTML
<div>
<div class="animate">
jhk
</div>
</div>
Note: You must add a div with a class animate to maintain the transition.
CSS
div,
.animate {
width: 100px;
height: 100px;
}
.animate {
background: red;
-webkit-transition: all 1s linear;
-moz-transition: all 1s linear;
-o-transition: all 1s linear;
transition: all 1s linear;
}
div:hover > .animate {
-webkit-transform:scaleX(0.06);
-moz-transform:scaleX(0.06);
-o-transform:scaleX(0.06);
transform:scaleX(0.06);
}
In this case, using transition is a lot smoother than animation and #keyframes.
Hope it helps.
I hope you want something like this.
CSS
div {
width: 100px;
height: 100px;
background: red;
-webkit-transition: all .06s ease-in-out;
-o-transition: all .06s ease-in-out;
transition: all .06s ease-in-out;
}
div:hover {
-webkit-transform: scale(0.6);
-ms-transform: scale(0.6);
-o-transform: scale(0.6);
transform: scale(0.6);
}
#keyframes example {
25% {transform:scaleX(0.200);}
50% {transform:scaleX(0.500);}
75% {transform:scaleX(0.700);}
100% {transform:scaleX(1);}
}
Fiddle