I've got a bit of a problem with a CSS3-animation that is not firing in IE10.
I basically have a static image that is mostly transparent but with a few details, behind it there is a background image that is supposed to move horizontally. It works well in Chrome, but not in IE10 (win7), and I don't know what I am doing wrong.
All kinds of tips and tricks would be much appreciated.
<div id="skyover">
<img src="hh_sky_transp2.png" alt="logo" width="1000" height="202" />
</div>
<div id="sky">
<img src="hh_sky.jpg" alt="logo" width="2016" height="202" />
</div>
#skyover {
position: absolute;
z-index: 10;
}
#sky {
width: 1000px;
height: 202px;
position: relative;
animation: skymove 10s infinite;
animation-direction: alternate;
-webkit-animation: skymove 10s infinite;
-webkit-animation-direction: alternate;
}
#keyframes skymove {
from { left: 0px; }
to { right: 1000px; }
}
#-webkit-keyframes skymove {
from { left: 0px; }
to { right: 1000px; }
}
The problem here is animating from a left-origin to a right-origin:
#keyframes skymove {
from { left: 0px }
to { right: 1000px }
}
If you change the to point-of-origin to left, the issue is resolved:
#keyframes skymove {
from { left:0px }
to { left: 1000px }
}
Fiddle: http://jsfiddle.net/HGe5D/2/show/
Related
I have a VueJs component and 2 classes with animations.
I have a v-bind:class on a div, but when the class changes, the animation doesn't run.
When the update_page computed property changes, the class changes as well.
What am I doing wrong?
The div:
<div
class="top-0 right-0 bottom-0
absolute h-full bg-primary"
:class="update_page ? 'detail-header-hide' : 'detail-header'"
></div>
The css class:
.detail-header {
width: 0;
animation: fadeIn 1500ms;
}
.detail-header-hide {
width: 100%;
animation: fadeIn 1500ms;
animation-direction: reverse;
}
#keyframes fadeIn {
0% {
width: 100%;
}
60% {
width: 100%;
}
100% {
width: 0;
}
}
I know snippet looks bad, but i mean problem will be at reusing one animation. Try to add one more to your project like me at snippet ('fadeOut')
let x = document.querySelector('div')
function toggle(){
x.classList.toggle('detail-header-hide')
x.classList.toggle('detail-header')
}
.detail-header {
width: 0;
animation: fadeIn 1500ms;
}
.detail-header-hide {
width: 100%;
animation: fadeOut 1500ms;
}
#keyframes fadeIn {
0% {
width: 100%;
}
60% {
width: 100%;
}
100% {
width: 0;
}
}
#keyframes fadeOut {
0% {
width: 0%;
}
60% {
width: 0%;
}
100% {
width: 100%;
}
}
<div
class="detail-header-hide"
>Some text Some text Some text Some text Some text</div>
<button onClick='toggle()'> btn </button>
The code below is a part of my code :
.myBox:hover::after {
animation-name: underline;
animation-duration: 350ms;
animation-fill-mode: forwards;
}
#keyframes underline {
from { width: 0; }
to { width: 100%; }
}
It works nicley, but I want to do it vice versa when animation completed, I mean when it finished then width should be 0 again, In fact for this part I want to do it when my element is not hovered. Which property can help me ?
You need to use alternate and run 2 iterations of the animation:
.box {
height:200px;
background:red;
animation: underline 500ms alternate 2 forwards;
}
#keyframes underline {
from { width: 0; }
to { width: 100%; }
}
<div class="box">
</div>
Or consider the use of transition if you want the effect on hover:
.box {
height: 200px;
background: red;
width: 0;
transition: 500ms;
}
body:hover .box {
width: 100%;
}
<div class="box">
</div>
You can specify multiple values for animations rather then from and to using percentage:
#keyframes underline {
0%, 100% { width: 0; }
50% { width: 100%; }
}
More detailed information can be found here.
.myBox:hover::after {
animation-name: underline infinite;
animation-duration: 350ms;
animation-fill-mode: forwards;
}
#keyframes underline {
from { width: 0; }
to { width: 100%; }
}
You infinite for this
I am trying to achieve a CSS only slider.
When hovering left and right arrows, the slider has to slide. Of course.
I tried something using animation-play-state, animation-fill-mode (to keep the positions) and animation-direction but I'm not able to fully make it work.
Starting with animation-play-state: paused, hovering the arrows changes it to running.
On hover of the right arrow, everything is fine. We can hover, leave, hover again.
But, as soon as I hover the left arrow (that changes the animation-direction to reverse), it's broken.
Simplified snippet:
.wrapper {
overflow: hidden;
position: relative;
width: 500px;
}
.arrows {
z-index: 2;
position: absolute;
top: 0;
height: 100%;
background: #ddd;
opacity: 0.66;
}
.arrows:hover {
opacity: 1;
}
.arrow-l {
left: 0;
}
.arrow-r {
right: 0;
}
.sliding {
height: 160px;
width: 2000px;
background: linear-gradient(to bottom right, transparent 49.9%, gray 50.1%);
animation: slide 2s linear;
animation-play-state: paused;
animation-fill-mode: both;
}
.arrows:hover~.sliding {
animation-play-state: running;
}
.arrow-l:hover~.sliding {
animation-direction: reverse;
}
#keyframes slide {
0% {
transform: translate(0px, 0);
}
100% {
transform: translate(-1500px, 0);
}
}
<div class="wrapper">
<div class="arrows arrow-l">[ ← ]</div>
<div class="arrows arrow-r">[ → ]</div>
<div class="sliding"></div>
</div>
Can someone help me understand what is happening, and correct this unwanted behaviour?
The main issue here is that changing the direction will keep the current state of the animation BUT it will consider the new direction. Let's take an easy example:
Suppose you have an animation from left:0 to left:100%. If you first run the animation untill left:80% and then you change the direction to reverse you will have left:20%!
Why?
Because with the default direction you reached the 80% (left:80%) of the animation and 80% of the same animation with reverse direction is simply left:20%.
Hover on reverse and you will see that the position of the box is jumping to switch to the new state considering the new direction. It's obvious when the animation ends and you will be switching between the first and last state:
.sliding {
width:100px;
height:100px;
background:red;
left:0%;
position:relative;
animation:slide 5s linear forwards;
animation-play-state:paused;
}
.arrows {
margin:20px;
}
.arrow-r:hover~.sliding {
animation-play-state: running;
}
.arrow-l:hover~.sliding {
animation-direction: reverse;
}
#keyframes slide {
0% {
left: 0%;
}
100% {
left: 100%;
}
}
<div class="wrapper">
<div class="arrows arrow-r">move normal</div>
<div class="arrows arrow-l">reverse !!</div>
<div class="sliding"></div>
</div>
There is no fix for this since it's the default behavior of animation, but instead you can rely on transition to obtain a similar effect. The trick is to play with the duration that you increase/decrease to create the needed effect.
Here is an idea:
.wrapper {
overflow: hidden;
position: relative;
width: 500px;
}
.arrows {
z-index: 2;
position: absolute;
top: 0;
height: 100%;
background: #ddd;
opacity: 0.66;
}
.arrows:hover {
opacity: 1;
}
.arrow-l {
left: 0;
}
.arrow-r {
right: 0;
}
.sliding {
height: 160px;
width: 2000px;
background: linear-gradient(to bottom right, transparent 49.9%, gray 50.1%);
transition:all 2000s linear; /*This will block the current state*/
}
.arrow-r:hover ~ .sliding {
transform: translate(-1500px, 0);
transition:all 2s;
}
.arrow-l:hover ~ .sliding {
transform: translate(0px, 0);
transition:all 2s;
}
<div class="wrapper">
<div class="arrows arrow-l">[ ← ]</div>
<div class="arrows arrow-r">[ → ]</div>
<div class="sliding"></div>
</div>
On my element, I have a CSS animation running as long as it has a certain class (wiggle), and a transition as soon as it has a different one (right):
<div class="outer">
<div class="inner wiggle"></div>
</div>
#keyframes wiggle {
from {
left: 10%;
}
50% {
left: 30%;
}
to {
left: 10%;
}
}
.inner {
left: 0;
&.wiggle {
animation: wiggle 2s infinite;
}
&.right {
left: 90%;
transition: left 2s;
}
}
Now, if remove the wiggle class and add right at the same time, the transition doesn't play out; left: 90% applies immediately. However, if there's a delay between removing the former and adding the latter, the transition will happen as expected.
Here's a JSFiddle illustrating the issue.
It looks like when coming from an animation, values (such as left in this case) don't have an explicit value to transition from, so they're just rendered to their final state.
Is this expected behavior, i.e. is it part of a specification? Or are browsers free how to handle that case?
I've tested on the lastest versions of Firefox and Chromium.
Clarification: I'm not mainly looking for workarounds, especially not complicated ones, but more for a reason why exactly browsers behave like they do.
I think this may be a bug in browser rendering or so, but If you want a solution I can give you one alternative method with transform
A working fiddle for you:
$('#toggle').click(() => {
$('.inner').removeClass('wiggle').addClass('right');
});
#keyframes wiggle {
from {
left: 10%;
}
50% {
left: 30%;
}
to {
left: 10%;
}
}
.outer {
height: 5em;
background-color: black;
position: relative;
}
.inner {
height: 100%;
width: 10%;
position: absolute;
transform: translate(0%);
background-color: green;
transition: transform 2s ease-in-out;
}
.inner.wiggle {
animation: wiggle 2s infinite;
}
.inner.right {
transform: translate(900%);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h2>
Animated
</h2>
<div class="outer">
<div class="inner wiggle"></div>
</div>
<h2>
Not animated
</h2>
<div class="outer">
<div class="inner"></div>
</div>
<hr>
<button id="toggle">
move right
</button>
I hope this was helpful for you.
Its look it is the expected behavior. I think when you are adding the right class with left:90%, its not able to pick the starting value for the left css property. As an alternate you can create another keyframe for the .right class
$('#toggle').click(() => {
$('.inner').removeClass('wiggle').addClass('right');
});
#keyframes wiggle {
0% {
left: 10%;
}
50% {
left: 30%;
}
100% {
left: 10%;
}
}
#keyframes right {
100% {
left: 90%;
}
}
.outer {
height: 5em;
background-color: black;
position: relative;
}
.inner {
height: 100%;
width: 10%;
position: absolute;
left: 0;
background-color: green;
transition: left 2s;
}
.wiggle {
animation: wiggle 2s infinite;
}
.right {
animation: right 2s forwards;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h2>
Animated
</h2>
<div class="outer">
<div class="inner wiggle"></div>
</div>
<h2>
Not animated
</h2>
<div class="outer">
<div class="inner"></div>
</div>
<hr>
<button id="toggle">
move right
</button>
This workaround might help you, the idea is to use the css variables, the idea is to set the animation with an alternate function, so in this way we will only need From and To... on the other hand we need to set up and event for every iteration, in that way we know when an iteration ends,
So when we click the button you can change the variable value and remove the class...
$('#toggle').click(() => {
$('.inner').addClass('right');
});
let flag = false;
$(".inner").on("animationiteration webkitAnimationIteration oAnimationIteration MSAnimationIteration", function(){
flag && $(".inner").removeClass('wiggle');
if($(".inner").hasClass('right')) flag = true;
});
:root {
--from: 10%;
--to: 30%;
}
#keyframes wiggle {
from {
left: var(--from);
}
to {
left: var(--to);
}
}
.outer {
height: 5em;
background-color: black;
position: relative;
}
.inner {
height: 100%;
width: 10%;
position: absolute;
transform: translate(0%);
background-color: green;
transition: transform 2s ease-in-out;
left:90%;
}
.inner.wiggle {
left:10%;
animation: wiggle 1s infinite;
animation-direction: alternate;
}
.inner.right {
--to:90%;
animation-direction: normal;
animation-duration:2s;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h2>
Animated
</h2>
<div class="outer">
<div class="inner wiggle"></div>
</div>
<hr>
<button id="toggle">
move right
</button>
Consider that this has a bug when the animation is moving back to the start point...
I would like each <div> to stay on screen for 8 sec before it fades out.
Also I would like them to fade into each other, opposed to fading to black and then the other fades in.
This works great thanks to #giovannipds except for a pop and not on screen for 8 sec. If you remove the z-index change it transitions clean.
.slider {
line-height: 1.5;
height: 200px;
margin: 20px auto;
position: relative;
width: 300px;
}
.slide {
padding: 20px;
position: absolute;
width: 100%;
height: 100%;
}
.slide,.slide a {
color: #fff;
}
.slide1 {
animation: fade 8s infinite;
background: red;
}
.slide2 {
animation: fade2 8s infinite;
background: blue;
}
#keyframes fade
{
0% { opacity: 1 ; z-index: 2; }
33.333% { opacity: 0; z-index: 1; }
66.666% { opacity: 0; z-index: 1; }
100% { opacity: 1; z-index: 2; }
}
#keyframes fade2
{
0% { opacity: 0; z-index: 1; }
33.333% { opacity: 1; z-index: 2; }
66.666% { opacity: 1; z-index: 2; }
100% { opacity: 0; z-index: 1; }
}
<div class="slider">
<div class="slide slide1">
<ul>
<li>Google</li>
<li>Globo.com</li>
</ul>
</div>
<div class="slide slide2">
<ul>
<li>Love Mondays</li>
<li>Hotmail</li>
</ul>
</div>
</div>
Old question but I was recently confronted with the same POP problem and I managed to solve it by separating the image and caption markup on each slide and by assigning separate cross-fade animations to each:
image animation (with opacity but without z-index) => just like fade and fade2 in the snippet above but without z-index; this actually solved the POP
caption animation (with both opacity and z-index) => just like fade and fade2 in the snippet above, this would address links or any other HTML you might want on top of image