Smooth @keyframes animation goes discrete on Safari
The way I fixed it is instead of trying to manipulate width of an element (which causes redrawing each time the width changes), did the following:
@keyframes loading-wrapper-anim {
0% {
transform:scaleX(0);
}
100% {
transform:scaleX(1);
}
}
.preloader .loading_wrapper {
position:absolute;
width:100%;
height:1px;
background:#dbdbdb;
top:12rem;
animation: loading-wrapper-anim 1s;
animation-delay: 1s;
animation-fill-mode: forwards;
align-self:flex-start; /*this one is because of the parent element*/
transform:scaleX(0);
transform-origin:0% 0%;
}
.preloader .loading_wrapper .loading_bar {
height:100%;
width:100%;
height:100%;
background:#000;
animation: loading-wrapper-anim 3s;
animation-delay: 2s;
animation-fill-mode: forwards;
transform:scaleX(0);
transform-origin:0% 0%;
}
I used transform:scaleX()
in conjunction with transform-origin:0% 0%
(this one sets center of transformation to the top left corner) to emulate width change without actually changing it.
Conclusion: use transform
where/when possible. They are more efficient in terms of CSS animations and transitions.
How to prevent a CSS keyframe animation from running on page load?
Solution 1 - Add down animation on first hover
Probably the best option is to not put the down animation on until the user has hovered over the container
for the first time.
This involves listening to the mouseover
event then adding a class with the animation at that point, and removing the event listener. The main (potential) downside of this is it relies on Javascript.
;(function(){ var c = document.getElementById('container'); function addAnim() { c.classList.add('animated') // remove the listener, no longer needed c.removeEventListener('mouseover', addAnim); };
// listen to mouseover for the container c.addEventListener('mouseover', addAnim);})();
#container { position:relative; width:100px; height:100px; border-style:inset;}#content { position:absolute; top:100px; width:100%; height:100%; background-color:lightgreen; opacity:0;}
/* This gets added on first mouseover */#container.animated #content { -webkit-animation:animDown 1s ease;}
#container:hover #content { -webkit-animation:animUp 1s ease; animation-fill-mode:forwards; -webkit-animation-fill-mode:forwards;}
@-webkit-keyframes animUp { 0% { -webkit-transform:translateY(0); opacity:0; } 100% { -webkit-transform:translateY(-100%); opacity:1; }}@-webkit-keyframes animDown { 0% { -webkit-transform:translateY(-100%); opacity:1; } 100% { -webkit-transform:translateY(0); opacity:0; }}
<div id="container"> <div id="content"></div></div>
CSS Transform causes flicker in Safari, but only when the browser is = 2000px wide
Frustrating huh?
See EDIT4 for the answer to why 2000px is a magic number.
There is a couple of things you can try.
Add
-webkit-transform-style: preserve-3d;
to the elements that are
flickering.add
-webkit-backface-visibility: hidden;
to the elements that are
flickering.move the animating element outside of the parent the flickering
elements are within.
EDIT —
Wesley Hales, said here
"I encountered glitchy behaviour when applying hardware acceleration to parts of the page that were already accelerated"
Its hard to help you debug this without any code. But for starters I suggest you turn on debug mode in safari. Write 'defaults write com.apple.Safari IncludeInternalDebugMenu -bool true' in the terminal.
After this a Debug menu will show up. Choose Drawing/Compositing flags > Show Compositing borders.
This will help you see whats being rendered and by that choose what to put in hardware acceleration and what to leave out.
EDIT2 —
This is worth checking out as well: fast-animation-with-ios-webkit
Its regarding iOs, but I've experienced that - in some circumstances - solutions that work on iOs also works on osx.
EDIT3 —
If you are just asking what happens when its bigger than 2000px I can tell you for sure that on iPhones, WebKit creates textures that are no larger than 1024 by 1024, and if your element is larger than that, it has to create multiple textures.
Documentation on texture limitations
Now, when they do it on iPhone, it wouldn't surprise me if they do the same on OsX, but has a higher limit.
Don't know if this is your case tho. Impossible to tell without any code.
EDIT4 —
"The implementation in TextureMapperTiledBackingStore is pretty simple, and is used only to work around the 2000x2000 texture size limitation in OpenGL."
So, if your element is bigger than 2000x2000 it has to create multiple textures.
http://trac.webkit.org/wiki/CoordinatedGraphicsSystem
Related Topics
CSS- Target Text Links with Bottom Border on Hover, But Image Links with No Border
Styling Links Inside a Div with a Specific Class
Turn Off Animations in Capybara Tests
How Do Browsers Parse/Render CSS
CSS Selector to Check That Attribute Does Not Contain Both Values
CSSmin Not Correctly Handling @Import
Using CSS Mix-Blend-Mode with a Child of a Position Fixed Element
Unbalanced CSS Columns in Chrome
Twitter Bootstrap Accordion and Button Dropdown Overflow Issue
How to Set a Floating Div's Width to Take Up Remaining Space Without Pushing Other Divs Down
CSS Transform Square into Thinner Rhombus
How to Make Webgl Canvas Transparent
Did Chrome 72 Break 'Data:Image/Svg+Xml;Utf8' for CSS Background Svgs
Using @Import for Google Fonts Is Not Working on Internet Explorer