I have a simplw div that expands and changes colors, from my understanding the backwards value for the animation-fill-mode should reset the div to the first frame of the animation after it ends, including delays, I have a delay of zero ms and instead of resetting back to the first frame, it simply disappears, why?
//css
#keyframes frames{
from{
background-color: blue;
width: 50px;
height: 50px;
}
to{
background-color: orange;
width: 200px;
height: 200px;
}
}
#d1{
width: 50px;
height: 50px;
animation: frames 1000ms ease-in-out 0ms 3 alternate backwards;
}
//html
<div id="d1"></div>
Alternate backwards doesn't exist. You should use alternate-reverse:
#d1 {
width: 50px;
height: 50px;
animation: frames 1000ms ease-in-out 0ms 3 alternate-reverse;
}
Related
I have these 3 rules:
.thingy{
display:inline-block;
position:relative;
width: 5em;
height: 5em;
background-color:#FF0000;
left:0em;
transition: left 4s linear, background-color 4s;
}
.thingy:active{
left:10em;
transition: left 0s linear;
}
.thingy:hover{
background-color:#00FF00;
transition: background-color 0s linear;
}
and this bit of basic HTML:
<div class="thingy"></div>
When the <div> is clicked, it will move to the right, as expected. However, whenever it is hovered over while it is returning to it's original position, it will snap back immediately.
I want it to, while returning to it's original position from being clicked, to be able to swap it's background-color (or any other property) then fade back to it's normal values without overriding any other transition currently going on.
For the purposes of the code, I can only use pure CSS, and I cannot utilize #key-frames or any property associated to it, such as animation-duration.
You can use CSS variable for this task
.thingy {
display: inline-block;
position: relative;
width: 5em;
height: 5em;
background-color: #FF0000;
left: 0em;
transition:
var(--t-left,left 4s linear),
var(--t-back,background-color 4s);
}
.thingy:active {
left: 10em;
--t-left: left 0s;
}
.thingy:hover {
background-color: #00FF00;
--t-back: background-color 0s
}
<div class="thingy"></div>
I am trying to get an object to lead in with one CSS animation key frame set and then have it loop another key frame set forever. Is this possible?
Depends on what you are willing to do for it :)
I don't think that there is a solution to trigger the second animation from within the last keyframe of the first animation.
A possible solution would be to delay the second animation until the first one has finished like this:
#test {
height: 50px;
width: 50px;
background: grey;
animation: 2s firstAnimation forwards, 1s secondAnimation 2s alternate infinite;
/* the "2s" after "secondAnimation" is for the delay */
}
#keyframes firstAnimation {
100% {
width: 100px;
background: red;
}
}
#keyframes secondAnimation {
0% {
height: 50px;
}
100% {
height: 100px;
}
}
<div id="test"></div>
Another possible approach is to verify with javascripts onanimationend and then add the second animation by adding a class for example:
let test = document.getElementById("test")
test.onanimationend = function(event) {
console.log(event) // contains a lot of interesting infos like the name of the animation that ended :)
test.classList.remove("startFirstAnimation")
test.classList.add("startSecondAnimation")
}
#test {
height: 50px;
width: 50px;
background: grey;
}
.startFirstAnimation {
animation: 2s firstAnimation forwards;
}
#keyframes firstAnimation {
100% {
width: 100px;
background: red;
}
}
.startSecondAnimation {
width: 100px !important; /* cheating a little bit here to keep the state of the end of the firstAnimation... */
background: red !important;
animation: 1s secondAnimation alternate infinite;
}
#keyframes secondAnimation {
0% {
height: 50px;
}
100% {
height: 100px;
}
}
<div id="test" class="startFirstAnimation"></div>
SOLUTION:
The solution I found is using two divs on top of each other(to make the function clearer I made one of the divs red), while it has to animate two divs for the effect, it should still be cleaner and faster than using javascript:
.outerDiv {
width: 100%;
height: 50px;
position: relative;
}
.hover1 {
height: 50px;
width: 50px;
background: black;
position: relative;
top: 0px;
transition: width 1s
}
.hover2 {
height: 50px;
width: 50px;
background: red;
position: relative;
top: -50px;
transition: width 1s 1s
}
.outerDiv:hover .hover2 {
width: 100%;
transition: width 0s 0.9s;
}
.outerDiv:hover .hover1 {
width: 100%;
transition: width 1s;
}
<div class="outerDiv">
<div class="hover1"></div>
<div class="hover2"></div>
</div>
This can be achieved by specifying different transition time for the normal state and hover state.
<style>
#hoverDiv {
height: 50px;
width: 50px;
background: black;
transition: width 5s; /*Specify required time.
This affects how long it takes to transition
back to the normal state*/
}
#hoverDiv:hover {
width: 100%;
transition: width 2s; /*This affects how long it takes to transition
into the hover state*/
}
</style>
<div id="hoverDiv"></div>
Also, if you want to add a delay before width decreases back to normal, try
#hoverDiv {
height: 50px;
width: 50px;
background: black;
transition: width 5s;
transition-delay: 5s; /*Waits for 5 seconds and then decreases
back to normal size in 5 seconds*/
}
I have a css transition that moves an element on hover and an animation that rotates the element on hover too. There's a delay on the animation equal to the transition duration so that after it's transitioned to it's correct position, the animation starts. And it works nice, however, when we mouse off, the animation stops but it doesn't transition back down.
Is it possible to get it to transition back after we mouse off and the animation ends?
You can see an example here: http://codepen.io/jhealey5/pen/zvXBxM
Simplified code here:
div {
width: 200px;
height: 200px;
margin: 40px auto;
background-color: #b00;
position: relative;
&:hover {
span {
transform: translateY(-60px);
animation-name: rotate;
animation-duration: 1s;
animation-delay: .5s;
animation-iteration-count: infinite;
animation-direction: alternate;
}
}
}
span {
position: absolute;
width: 20px;
height: 20px;
background-color: #fff;
bottom: 10px;
left: 0;
right: 0;
margin: auto;
transition: .5s;
}
#keyframes rotate {
from {
transform: translateY(-60px) rotate(0);
}
to {
transform: translateY(-60px) rotate(-90deg);
}
}
I have forked your project and adapted it so it works. You can find it here.
What I have changed is the following:
I give the white square a start position of top: 150px and let it, on hover of div, get a top: 0. The span gets a transition: top .5s and with that it goes to top: 0; on hover and back to top: 150px; when the mouse leaves.
I have removed the translateY(-60px); from the animation, because that would move it even more up when the animation would start.
Here's your new CSS:
div {
width: 200px;
height: 200px;
margin: 40px auto;
background-color: #b00;
position: relative;
&:hover {
span {
top: 0px;
animation: rotate 1s infinite .5s alternate;
animation-direction: alternate;
}
}
}
span {
position: absolute;
width: 20px;
height: 20px;
background-color: #fff;
bottom: 10px;
left: 0;
right: 0;
top: 150px;
margin: auto;
transition: top .5s;
}
#keyframes rotate {
from {
transform: rotate(0);
}
to {
transform: rotate(-90deg);
}
}
Edit: The problem is that an animation is time-based and not action-based, which means that as soon as you trigger an animation, a timer starts running and it will run through all the keyframes until the set time has passed. Hover-in and hover-out have no effect, except that the timer can be stopped prematurely, but the animation will not continue (or reversed, which you wanted) after that. transition is action-based, which means it gets triggered every time an action (for example :hover) is happening. On :hover, this means it takes .5s to go to top:0 and when the hover ends, it takes .5s to got to top:150px.
I hope the above addition makes sense :)
As you can see, I also cleaned up a bit in your animation-name: etc., since it can be combined into one line.
As Harry pointed out, the problem is that you are animating/transitioning the same property, in this case transform. It looks like the current versions of Chrome/FF will allow the animation to take control of the property, thereby breaking the transition. It seems like the only way to work around this is to transition/animation a different property. Since you need to continue rotating the element, you could translate/position the element by changing the bottom property instead. I know that doesn't produce the exact same results, but nonetheless, it does move the element (just not relative to the parent element).
Updated Example
div:hover span {
bottom: 80px;
}
As an alternative, you could also wrap the span element, and then translate that element instead.
In the example below, the .wrapper element is transitioned to translateY(-60px) on hover, and then the child span element is rotated and maintains the animation.
Example Here
div {
width: 200px;
height: 200px;
margin: 40px auto;
background-color: #b00;
position: relative;
}
div:hover .wrapper {
transform: translateY(-60px);
}
div:hover .wrapper span {
animation-name: rotate;
animation-duration: 1s;
animation-delay: .5s;
animation-iteration-count: infinite;
animation-direction: alternate;
}
.wrapper {
display: inline-block;
transition: .5s;
position: absolute;
bottom: 10px;
left: 0;
right: 0;
text-align: center;
}
.wrapper span {
display: inline-block;
width: 20px;
height: 20px;
background-color: #fff;
}
#keyframes rotate {
from {
transform: rotate(0);
}
to {
transform: rotate(-90deg);
}
}
<div>
<span class="wrapper">
<span></span>
</span>
</div>
I am trying a transition where a line becomes a long rectangle. I want to make it so that when the transition finishes, the final state remains in place even when the mouse is not hovered on it.
This is my current code:
#line {
width: 300px;
height: 1px;
background-color: darkblue;
transition: height 2s;
-webkit-transition: height 2s;
}
#line:hover {
width: 300px;
height: 200px;
background-color: darkblue;
}
<div id="line"></div>
I think the best solution is to add a small script that adds a class. The class remains after unhovering:
window.addEventListener('DOMContentLoaded', function() {
document.getElementById('line').addEventListener('mouseover', function(event) {
document.getElementById('line').classList.add('activated');
});
});
#line {
width: 300px;
height: 1px;
background-color: darkblue;
transition: height 2s;
-webkit-transition: height 2s;
}
#line.activated{
width: 300px;
height: 200px;
background-color: darkblue;
}
<body>
<div id="line"></div>
</body>
A tricky way to get this effect only with CSS: set the transition-delay on the element to a huge value. and set it to 0 on the hover state
When you hover, the element changes to the hover state, and this way the transition is immediate.
When you un-hover, there will a 9999s delay before it begins (well, not really for ever, but nobody will notice)
#line {
width: 300px;
height: 10px;
background-color: darkblue;
-webkit-transition: height 1s 9999s;
transition: height 1s 9999s;
}
#line:hover{
width: 300px;
height: 200px;
background-color: darkblue;
-webkit-transition-delay: 0s;
transition-delay: 0s;
}
<body>
<div id="line"></div>
</body>