Why does animating css translate cause flicker in webkit on a black background? - css

As you can see from the jsfiddle this animation flickers in webkit. It doesn't seem to matter if the animation is infinite or not. How can this be fixed? I have tried everything for hours. All the standard tricks don't seem to work on this example. Thanks for your time.
here is the code:
body {
background-color: #000;
}
#box {
width: 200px;
height: 200px;
top:20px;
left:20px;
position:absolute;
border: 1px solid red;
-webkit-animation: box 20s linear infinite normal;
}
#-webkit-keyframes box {
0% {-webkit-transform: translate(0,100px);}
50% {-webkit-transform: translate(100px,0);}
100% {-webkit-transform: translate(0,100px);}
}
EDIT: RCorrie was right, going into the color settings of my monitor and tweaking them solved the problem!

Thereason this happens is because the element is rendered at half pixel offset, to instead of having 1 pixel of 100% opacity, it'll be spread over 2 pixels both 50% opacity. It rapidly switches between 100% and 2x50% as it moves along, so that is what makes it flicker.
You could fix it by either making the line thicker, or speeding up your animation (the former being more effective at fixing it)

Related

Choppy transition: transform scalling animation on Safari

I have hard time making scaling animation that is not choppy in Safari (mobile). By choppy I mean you can clearly see that it's not 60FPS fluid animation. I need to say that element is absolutely positioned so it should not affect layout, should it?
First thing that I tried is animating element by creating CSS animation with 2 keyframes, going from transform: scale(0); to transform: scale(1);. For the effect I want to achieve I also used transform-origin: top right;. I also tried to optimize it by setting will-change: transform; but it was choppy.
I scrapped it and reworked it so it uses transition: transform. So by default element has transform: scale(0);, when certain class attaches to it, it gets transform: scale(1); which transition is animating, but it is still choppy.
After some research I found out that you want to avoid animating properties that require browsers to recalculate layout. I found out this site which says that WebKit (which Safari is using as far as I know) pretty much recalculates layout for every property change. Is that true, and if it is how do you make 60FPS fluid animations on mobile Safari (on other platforms using Safari it's not that noticeable because they have much more resources to recalculate everything and it appears a bit smoother than on mobile)?
There are 2 things that you can try:
avoid using scale(0). In some browsers this gives problems. scale(0.01) is almost the same, and will be better for the browser.
Try to make the animation handled by the GPU instead of the CPU. this can be done with the following code
from: {transform: scale(0.01) translateZ(1px);}
to: {transform: scale(1) translateZ(1px);}
In reference to this article section Animate Changes in CSS Properties, you can animate with keyframes, but need use a percentage like this:
More examples in w3s article.
PD: if you add an example, i'll try to help you.
function animateStart(){
document.getElementById('ball').classList.add('bounce');
}
function animationPause(){
document.getElementById('ball').style.webkitAnimationPlayState='paused';
}
function animationContinue(){
document.getElementById('ball').style.webkitAnimationPlayState='running';
}
#-webkit-keyframes bounce {
0% {top: 100px; left: 1px; -webkit-animate-timing-function: ease-in;}
25% {top: 150px; left: 76px; -webkit-animate-timing-function: ease-out;}
50% {top: 100px; left: 151px -webkit-animate-timing-function: ease-in;}
75% {top: 150px; left: 226px -webkit-animate-timing-function: ease-out;}
100% {top:100px; left: 301px;}
}
.bounce {
-webkit-animation-name: bounce;
-webkit-animation-duration: 2s;
-webkit-animation-timing-function: linear;
-webkit-animation-iteration-count: infinite;
-webkit-animation-direction: alternate;
}
.ball-style {
position:absolute; top: 100px; left: 10px;
height:100px; width:100px; border-radius:50px;
background:-webkit-radial-gradient(30% 30%, white, red 10%, black);;
}
.wall {
position:absolute; left: 400px; top: 100px;
height: 150px;
background: black;
}
<input type="button" value="Animate alternative"
onclick="document.getElementById('ball').classList.add('bounce');">
<input type="button" value="Animate" onclick="animateStart()">
<input type="button" value="Pause" onclick="animationPause()">
<input type="button" value="Continue" onclick="animationContinue()">
<div id="ball" class="ball-style"></div>
<div class="wall"> </div>
I don't know if this helps but are you using javascript to add a class and start the animation with the class change?
jQuery for example can cause long depth analysis in the dom when manipulating elements, this is likely to interfere with the performance you need for achieving the desired fps.

Animation disappears after animation in MSIE11

I have this strange bug in MSIE11, where an animated element disappears right after the end of an animation.
See this example
.cta-43274891247129739-info {
position: absolute;
left: 0;
top: 50px;
margin: 10px 10px;
animation: cta-43274891247129739 4s 1s both ease-out;
text-align: center;
}
#keyframes cta-43274891247129739 {
0% {
transform: translateY(1em);
opacity: 0;
}
16.6667%, 83.3333% {
opacity: 1;
transform: translateY(0em);
}
100% {
transform: translateY(-40px);
}
}
<div class="cta-43274891247129739-info">This animation fades in from the bottom, makes a short stop and then translates up to its final halt. But not on MSIE11, where it will dissappear apruptely at the end of the animation </div>
MSIE11 has issues with animations, particularly with calculations involving different units.
In your particular example, the animation works perfectly, until the very last keyframe. After reaching 100%, it seems like the text has disappeared, but its actually still there, only moved up by 40em.
So the workflow looks something like this:
moves up by 1em => moves up by 0em => moves up by 40px => moves up by 40em
So by the last point, the text is already far above the viewport it seems like it has disappeared.
The solution to this is not to mix px's and em's.
If you change -40px to -4em on the last keyframe, the animation will work okay, maybe won't be the pixel perfect, but at least it will work.

I want to make a slideshow

This is the code of the slide show in html
<div id="slideshow">
<img src="images/slideshow/1.png"/>
<img src="images/slideshow/2.png"/>
<img src="images/slideshow/3.png"/>
<img src="images/slideshow/4.png"/>
<img src="images/slideshow/5.png"/>
<img src="images/slideshow/6.png"/>
</div>
And this is my css for it
#slideshow{
width:1100px;
height:432px;
position:relative;
border:3px solid #404A7F;
margin:auto;
margin-top:35px;
overflow:hidden;}
#slideshow img{
position:absolute;
opacity:0;
animation:move 30s infinite;}
#keyframes move{
0%{opacity:1;}
100%{opacity:1;}}
#slideshow img:nth-child(1){
animation-delay:0s;}
#slideshow img:nth-child(2){
animation-delay:5s;}
#slideshow img:nth-child(3){
animation-delay:10s;}
#slideshow img:nth-child(4){
animation-delay:15s;}
#slideshow img:nth-child(5){
animation-delay:20s;}
#slideshow img:nth-child(6){
animation-delay:25s;}
But when the last image shows the slideshow doesn't start again from the first image.
Can someone please tell me what's wrong?
The problem is that you fade from 1 opacity to 1 opacity. After you correct that, it's till not okay, since you fade in during the whole period of 30 seconds, so an image is not fully faded in when the next image starts. And lastly, it doesn't wrap well, since it starts without any visible image.
Here is a fixed version of what I think you tried to achieve. Note I used colors instead of image for the demo, but they are still actual image elements, and it should work fine in your situation.
Basically what it does:
Shows the last image always, but with a z-index of -1, so it is always visible behind the others. This makes that image the one that is immediately visible.
Fades in quickly (during only a part of the 5 seconds in which the image is visible)
Fades out at the same pace, so fading out the prio to last image actually shows the last one.
The trick is to fix the animation so the images fade in and out at the right times within the animation.
I've commented the various frame in the animation to explain why I chose those values.
Possibly even better: I think it should be possible to show the first one too, by changing making the opacity 1 for the first 17%, then fade to 0 from 17% to 22%, and then fade to 1 again from 95% to 100%. But unfortunately, I'm leaving for Christmas dinner, and I can't try it out now. ;)
#slideshow{
width:1100px;
height:432px;
position:relative;
border:3px solid #404A7F;
margin:auto;
margin-top:35px;
overflow:hidden;}
#slideshow img{
position:absolute;
opacity:0;
animation:move 30s infinite;
width: 300px; height: 200px; /* Demo only */
}
#keyframes move{
/* Relevant information. You have 6 images, taking up 16.66% (say 17%) of the animation
time. So fading in needs to take place within this time.
Also, to wrap properly, the last image is put in the back and is always visible, so to
show that, you basically hide the prior one. Because of this, fading out has to
commence at 17% and has to have the same duration as the fading in.
*/
/* Start transparent */
0%{opacity:0;}
/* Move in a relatively short time to full opacity for a fade in effect. This can be anything from 0 to 17% */
5%{opacity:1;}
/* Stay at that level until after the next image has faded in at 100 / 6 ~ 17%. */
17%{opacity:1;}
/* Fade out at the same pace. This is needed for the animation to wrap seemlessly,
so 17% + 5% = 22% until full fade out */
22%{opacity:0;}
/* Stay there until the next round */
100%{opacity: 0};
}
#slideshow img:nth-child(1){
animation-delay:0s;
background-color: red;
}
#slideshow img:nth-child(2){
animation-delay:5s;
background-color: orange;
}
#slideshow img:nth-child(3){
animation-delay:10s;
background-color: yellow;
}
#slideshow img:nth-child(4){
animation-delay:15s;
background-color: green;
}
#slideshow img:nth-child(5){
animation-delay:20s;
background-color: blue;
}
#slideshow img:nth-child(6){
animation-delay:25s;
background-color: purple;
opacity: 1;
z-index: -1;
}
<div id="slideshow">
<img src="images/slideshow/1.png"/>
<img src="images/slideshow/2.png"/>
<img src="images/slideshow/3.png"/>
<img src="images/slideshow/4.png"/>
<img src="images/slideshow/5.png"/>
<img src="images/slideshow/6.png"/>
</div>

How to avoid the text jerk by using css transitions

I try to rotate the text by using, text-transform with transition. In firefox browser a slight jerk get happened. Check the below link, by mouse overing the text, end of the rotation you can see the slight jerk, how to avoid this?
.rot_pos{
margin:100px auto;
text-align:center;
}
.rotate{
font-size:30pt;
font-weight:bold;
display:inline-block;
transform:rotate(0deg);
-moz-transition:1s;
transition:1s;
}
.rotate:hover{
transform: rotate(-180deg);
-moz-transform: rotate(-180deg);
}
<div class="rot_pos">
<div class="rotate">Sample Text</div>
</div>
http://jsfiddle.net/es86wh1p/
Any other solution??
This happens only in firefox.
I had a small play with your code in js-fiddle, it almost appears to be a bug in firefox. A quick debugging tip for things like this is to enable borders and set different colors.
I was able to find a solution, but it is so incredibly hackey that this reminds me of the 90's and the fact that mozilla firefox rose from the ashes of the netscape codebase.
First I set a parent/child tag which "Should" have caused the text to rotate when the mouse entered the rot_pos div. This still caused the text to 'trap' when the mouse hit the box that was rotating ( when causing the mouse to leave quickly, you can test this by removing the padding from rot_pos )
Setting the Z-Order of rotate to -2 shows that the rotate:hover trigger is not being triggered when it is 'behind' another div. So the quick lazy fix would be to expand the size of rot_pos so it completely covers the rotating text.
Which leads me to:
http://jsfiddle.net/rwa1pq2v/
.rot_pos{
margin:100px auto;
text-align:center;
border: 1px solid black;
padding: 100px 20px 100px 20px;
}
.rot_pos > .rotate {
font-size:31pt;
font-weight:bold;
display:inline-block;
transform:rotate(0deg);
transition:1s;
border: 1px solid black;
background: green;
}
.rot_pos:hover > .rotate {
transform: rotate(-180deg);
-moz-transform: rotate(-180deg);
}
.rotate {
z-index: -2;
}
.rotate:hover {
background: pink;
}
The issue with this is that the rotation is being triggered when the mouse enters the outer-area. So with the knowledge that a div which is "above" according to the z-order will prevent the trigger of the div below I dropped a further 2 div's over the top which can be seen as red and blue with a opacity of 0.5 in the example below:
http://jsfiddle.net/non45qy2/
With some lazy hand fiddling of sizes to ensure that they completely cover the trigger area we have my final solution..
To improve on this we could also drop a further 2 div's to cover up the 2 leftover white area's (and fix up the padding on the covered up areas) so you don't have to offset by such a large amount.
if it wasn't 1:40am I would be raising this issue as a bug with mozilla and hoping it gets fixed in the next release.

How to completely center a Unicode math symbol within its parent element?

I am trying to implement a CSS-based animation involving a single Unicode character:
HTML
<div class="spinner">⊗</div>
CSS
.spinner {
display: inline-block;
font-size: 42pt;
margin: 50px;
animation: spin 0.5s infinite linear;
}
#keyframes spin {
to { transform: rotate(360deg); }
}
* I've omitted the vendor-specific prefixes in this example.
However, when I view the page in my browser (Firefox 20.0), the character is slightly off-center, resulting in a "wobbly" animation.
You can see it live here: http://jsfiddle.net/bBaVN/77/
How can I completely center the character?
Proof of Concept using SVG
Consider the following:
<div class="wrap">
<span class="spinner">
<svg {...many other attributes...} class="logo">
...path code...
</svg>
</span>
</wrap>
See the fiddle: http://jsfiddle.net/audetwebdesign/3G3U7/
I found a SVG version of the symbol at:
http://www.fileformat.info/info/unicode/char/2297/index.htm
I had to take the SVG, open it in Adobe Illustrator and then reset the view port (bounding box?) using object->artboards->fit to artwork bounds.
I then saved as SVG and then cut-paste the <svg> block into the demo, and finally, I added the class="logo" attribute to the <svg> tag.
For styling, I used the following CSS:
.spinner {
display: block;
width: 50px;
height: 50px;
position: relative;
top: 75px;
left: 75px;
animation: spin 1s infinite linear;
}
.logo {
display: block;
width: 50px;
height: 50px;
}
I set the display type to block for both .logo and .spinner, and both have the same height and width (use a square box for best results.
Seems to work. The hardest part was learning how to set up the SVG inline image. I found the following reference useful: http://css-tricks.com/using-svg/
You could set the line-height to 45px on .spinner, this will ensure that the containing span element is as high as it is wide. Here's a jsFiddle. Now there is a little less movement, but it still doesn't look like it is not moving around at all.
Another way to get it to rotate around the center of character instead of around the center of the containing span would be to play around with -vendorspecificprefix-transform-origin. You could set it to rotate around another point e.g. setting it to: 23px 34px would set the x and y coordinates for the point to rotate around.
I think the fact that it still looks like it moves around a little bit might be due to the character not being rendered as a perfect circle, you could try rendering it in a different font, changing point sizes of the font, or even turning text-rendering: optimizelegibility; on or off might make a difference there.
The default value for -vendorspecificprefix-transform-origin is 50% 50%, this suggests that if you make sure that the character inside the element is perfectly centered, and you set the animation on the containing element, it should rotate exactly around the the center, and then playing with -vendorspecificprefix-transform-origin would only make things worse.
Another thought I'm having, by setting the point size of the text to 42pt, the width of the containing span becomes 45px, now 50% of that would be 22.5px, maybe it would work if you made the point size of the text a bit bigger, or just set the width and the height of the containing span to 46px, then 50% would be 23px, which might make the difference with the current movement.
Update:
I was able to get it to be centered perfectly in Chrome (and in FireFox) by using a mono-space font Courier, manually setting the line-height, height and width of the span to center the character, and then forcing the character to look more like a circle by moving it over by 0.5px using -webkit-transform: translate().
.spinner {
display: inline-block;
font-size: 42pt;
line-height: 50px;
height: 46px;
width: 46px;
margin: 50px;
-webkit-animation: spin 1s infinite linear;
-moz-animation: spin 1s infinite linear;
-ms-animation: spin 1s infinite linear;
-o-animation: spin 1s infinite linear;
animation: spin 1s infinite linear;
font-family: courier;
}
#-webkit-keyframes spin {
from { -webkit-transform: rotate(0deg) translate(0.5px, 0px)}
to { -webkit-transform: rotate(360deg) translate(0.5px, 0px)}
}
I think the fact that I need 2 jsFiddle's to demonstrate for different browsers kind of answers the question about if you should be doing it this way, I think the differences in font-rendering between browsers will ensure that you can't do this reliably without browser detection.

Resources