css animation only working in safari - css

I'm pretty new at web development, but I'm trying to animate my logo (represented in the codepen by the blue rectangle) for my portfolio website. There are actually two animations. 1. fadein: the logo fades in from the top 2. shrink: (after a 3 second delay) the logo moves from the middle of the page to the top left corner and shrinks a bit.
If you open the pen in safari you'll see it working, but if you open it in chrome or firefox (given that you change the -webkit-) it sort of blends the two animations into one.
Any ideas to why this might happen en how to fix it?
codepen
div
{
height: 150px;
width: 170px;
position: fixed;
background-color: blue;
-webkit-animation-duration: 2s, 2s;
-webkit-animation-name: fadein, shrink;
-webkit-animation-delay: 0, 3s;
-webkit-animation-fill-mode: forwards;
}
#-webkit-keyframes fadein
{
0% {opacity: 0; top: 30%; left: 50%; margin-top: -75px; margin-left: -85px;}
100% {opacity: 1; top: 50%; left: 50%; margin-top: -75px; margin-left: -85px;}
}
#-webkit-keyframes shrink
{
0% {top: 50%; left: 50%; margin-top: -75px; margin-left: -85px;}
100% {top: 50px; left: 20px; margin: 0; width: 84px; height: 74px;}
}
Thanks!

The problem is with your animation delay. I'm not sure if it's bugged or as specification, but it doesn't work if you don't pass a unit, not even for zero.
-webkit-animation-delay: 0s, 3s;
That is, using 0s instead of 0.

Related

Strange CSS3 animation issue in IE11 and Edge

I made a CSS3 animation, it works well in Firefox and Chrome, but it behaves differently in IE11 and Edge.
I couldn't fix the issue because it's hard to debug CSS3 Animation using IE Developer Tools. This issue also occurs on Edge (But i think my Edge version is outdated so please try to reproduce this issue only in IE11. The fix will probably work on both).
Here is how i want the animation to look (Works on Chrome/Firefox):
Here is how it animates differently on IE11:
Code:
HTML:
<div class="block"></div>
<span>click</span>
CSS:
span {
width: 50px;
height: 50px;
background: red;
font-size: 50px;
}
.block {
position: fixed;
height: 0%;
bottom: 0;
width: 100%;
top: auto;
display: block;
background-color: #0B0B0B;
z-index: 99999;
animation-fill-mode: both;
animation-duration: 2s;
animation-timing-function: ease-in-out;
}
.animate-up {
animation-name: overlayEffectUp;
}
#keyframes overlayEffectUp {
0% {
bottom: 0;
top: auto;
height: 0%;
}
35%,
65% {
height: 100%;
}
100% {
bottom: auto;
top: 0;
height: 0%;
}
}
JavaScript (With jQuery):
$('span').on('click', function() {
$('.block').addClass('animate-up')
})
Here is the Demo link: https://jsfiddle.net/zoq9h7xp/3/
Please, any help would be appreciated!
Edge seems to be buggy with position: fixed. Supposedly the switch between top: 0 and top: auto (and same story with the bottom property) causes this behaviour.
If you must maintain the fixed position, you can try to animate with the transform property. Change your rulesets as follow:
#keyframes overlayEffectUp {
0% {
transform: translateY(100%); // totally offscreen
}
35%,
65% {
transform: translateY(0%); // totally on screen from bottom
}
100% {
transform: translateY(-100%); // totally off screen again to top
}
}
.block {
position: fixed;
top:0;
bottom:0;
transform: translateY(100%);
width: 100%;
background-color: #0B0B0B;
z-index: 99999;
animation-fill-mode: both;
animation-duration: 2s;
animation-timing-function: ease-in-out;
}
Hope this helps.
Cheers, Jeroen

CSS animation (position) not smooth

I made a subtle background movement, but the effect isn't that pleasing. While moving it kinda jerks, you can see the image move pixel by pixel.
How can I change this so it becomes a nice smooth animation.
The Code (https://jsfiddle.net/38tf0j21/):
body {
padding:50px;
margin 0;
height:100vh;
}
.landing_img_container {
position: absolute;
right: 0;
width: calc(100% - 100px);
height: 100%;
animation-name: start_animation;
animation-delay: 1s;
animation-direction: normal;
animation-duration: 5s;
animation-iteration-count: infinite;
animation-timing-function: ease;
}
.landing_img {
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
background-color:red;
}
#keyframes start_animation {
0% {
left: 100px;
}
100% {
left: 50px;
}
}
<div class="landing_img_container">
<div class="landing_img"></div>
</div>
This should work like you expect it to: https://jsfiddle.net/38tf0j21/2/
This is using the transform property instead of left
For smooth CSS position animations you need use transform: translate3d property.
See this example

Improve CSS3 background-position animation's performance

I'm trying to improve a CSS3 animation as it seems the current code is causing some excessive CPU load and the browser seems to be laggy.
What can I do? I've got all the vendor prefixes etc. I'm not sure I can improve the code or refactor it to use it as best code practices.
Fiddle Demo
.wrapper {
width: 960px;
height: 140px;
margin-top: 80px;
position: relative;
}
.content:before {
position: absolute;
z-index: 1;
top: 0;
left: 0;
width: 100%;
height: 100%;
content: "";
-webkit-transform: translateZ(0);
transform: translateZ(0);
-webkit-transform-origin: 50% 50% 0;
-ms-transform-origin: 50% 50% 0;
transform-origin: 50% 50% 0;
v -webkit-animation-name: sideupscroll;
animation-name: sideupscroll;
/*animation-duration*/
-webkit-animation-duration: 80s;
animation-duration: 80s;
/*animation-timing-function*/
-webkit-animation-timing-function: linear;
animation-timing-function: linear;
/*animation-iteration-count*/
-webkit-animation-iteration-count: infinite;
animation-iteration-count: infinite;
background: url("http://i.imgur.com/wNna7D3.png") repeat fixed 0 0 indigo;
-webkit-animation-fill-mode: both;
animation-fill-mode: both;
}
/* Safari and Chrome */
#-webkit-keyframes sideupscroll {
0% {
background-position: 0 0;
}
50% {
background-position: -50% -100%;
}
100% {
background-position: -100% -200%;
}
}
#keyframes sideupscroll {
0% {
background-position: 0 0;
}
50% {
background-position: -50% -100%;
}
100% {
background-position: -100% -200%;
}
}
<div class="wrapper">
<div class="content"></div>
</div>
Reason
Animating the background-position of an element is always going to be resource intensive and it has a high probability of causing laggy animations in almost all browsers. This is because, a change to the background-position results in a repaint + a composition in all browsers (+ it also results in re-layout in Webkit). Because of the need to perform so many costly operations, the result is always laggy.
Snippet with problem:
The below snippet is the same as your fiddle (without vendor prefixes). Run this snippet and inspect it using Chrome Dev tools after enabling "Show Paint Rects" option. You would see a red or green color box on top of the element (this is the paint rect) and the box will either keep blinking constantly or stay colored for the entire duration of the animation. It indicates that a repaint is happening often and thus it impacts performance.
In Firefox, the paint rects can be seen by enabling nglayout.debug.paint_flashing in about:config page (set it to true).
.wrapper {
width: 960px;
height: 140px;
margin-top: 80px;
position: relative;
}
.content:before {
position: absolute;
z-index: 1;
top: 0;
left: 0;
width: 100%;
height: 100%;
content: "";
transform: translateZ(0);
transform-origin: 50% 50% 0;
animation-name: sideupscroll;
animation-duration: 80s;
animation-timing-function: linear;
animation-iteration-count: infinite;
background: url("http://i.imgur.com/wNna7D3.png") repeat fixed 0 0 indigo;
animation-fill-mode: both;
}
#keyframes sideupscroll {
0% {
background-position: 0 0;
}
50% {
background-position: -50% -100%;
}
100% {
background-position: -100% -200%;
}
}
<div class="wrapper">
<div class="content"></div>
</div>
Solution
It is always better to avoid animating the background-* properties (all of which are visual properties) and use properties like transform. Using transform produces better performance atleast in Blink (Chrome) and EdgeHTML as Blink only does a re-composition while EdgeHTML triggers a re-layout only for the first time (1st update within animation).
Snippet without problem: (or atleast much lesser impact on performance in Blink and EdgeHTML)
The below snippet uses transform property (translateX and translateY) to achieve what is very similar to your expected output (but not the same). If you inspect this snippet with dev tools, you'd see that the green box (paint rect) appears only once at the start of the animation. Post that, the browsers only perform compositing and hence the performance is much better.
.wrapper {
width: 960px;
height: 140px;
margin-top: 80px;
position: relative;
overflow: hidden;
}
.content:before {
position: absolute;
z-index: 1;
top: 0;
left: 0;
width: 200%;
height: 400%;
content: "";
background: url("http://i.imgur.com/wNna7D3.png") 0 0 indigo;
background-repeat: repeat;
}
.content {
position: relative;
height: 100%;
width: 100%;
animation-name: sideupscroll;
animation-duration: 80s;
animation-timing-function: linear;
animation-iteration-count: infinite;
animation-fill-mode: both;
}
#keyframes sideupscroll {
0% {
transform: translateX(0%) translateY(0%);
}
50% {
transform: translateX(-50%) translateY(-100%);
}
100% {
transform: translateX(-100%) translateY(-200%);
}
}
<div class="wrapper">
<div class="content"></div>
</div>
What about Gecko and Webkit?
Unfortunately there doesn't to be a solution for browsers using these rendering engines as at the time of writing. The only option seems to be to reduce the animation-duration. A reduction in animation's duration means that the no. of re-paint + re-layout + re-composition cycles required is lesser and thus the animation's performance is better.
The below snippet looks less laggy in Firefox as the duration is only 20s.
.wrapper {
width: 960px;
height: 140px;
margin-top: 80px;
position: relative;
overflow: hidden;
}
.content:before {
position: absolute;
z-index: 1;
top: 0;
left: 0;
width: 200%;
height: 400%;
content: "";
background: url("http://i.imgur.com/wNna7D3.png") 0 0 indigo;
background-repeat: repeat;
}
.content {
position: relative;
height: 100%;
width: 100%;
animation-name: sideupscroll;
animation-duration: 20s;
animation-timing-function: linear;
animation-iteration-count: infinite;
animation-fill-mode: both;
}
#keyframes sideupscroll {
0% {
transform: translateX(0%) translateY(0%);
}
50% {
transform: translateX(-50%) translateY(-100%);
}
100% {
transform: translateX(-100%) translateY(-200%);
}
}
<div class="wrapper">
<div class="content"></div>
</div>
Useful Links:
CSS Triggers - Lists out which properties result in which operations being triggered.
HTML5 Rocks - Accelerated Rendering in Chrome - Explains how accelerated rendering works in Chrome (and how to enable "Show Paint Rects" option)
Note: As I had already stated above, the animation is not 100% the same as what you had in question but in my opinion this is about the closest you could get.

CSS Transition after animation ends

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>

CSS3 animation: inactive, active and additional 'end' state?

I have a button with an animated background on hover. It fills with a coloured background from left to right, however currently on mouse out it reverses the animation; the colour shrinks back toward the left and disappears. On mouse out I would like the fill to continue moving from left to right, so that it disappears out the right of the button. Any ideas? An example of this can be seen on the 'VISIT WEBSITE' button here:
http://www.notashop.com.au/new/project/lifewithbird/
Ideally would like to do this using CSS3 animation, however im feeling the active/inactive state of css3 animation may be the limiting factor here. If it cant be done using CSS3 any ideas using jQuery? A jsfiddle would be much appreciated!
Thanks for your help!
Ready for something cool... You will need to make this multi browser friendly but thats easy.
THis is ready in ff
here is the fiddle
.button {
background: blue;
width: 200px;
height: 45px;
position: relative;
}
.button:before {
background: none repeat scroll 0 0 #FFFFFF;
content: "";
height: 45px;
left: 100%;
position: absolute;
width: 200px;
z-index: 1;
transition: all 0.5s ease;
}
.button:hover:before{
-webkit-animation: left 1s;
-moz-animation: left 1s;
-o-animation: left 1s;
animation: left 1s;
animation-fill-mode:forwards;
}
.button p{
position: absolute;
left: 50%;
top: 5px;
z-index: 2
}
#keyframes left {
0% {left: -100%;}
50% {animation-play-state: paused; }
100%{left: 0%; animation-play-state: paused;}
}
Your gonna have allot of questions...

Resources