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

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.

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.

Unknown CSS code in theme causing image to blur

The wordpress theme I have, NeoBeat is causing my logo at top to be blurry.
My site is earthcry.net
The CSS for the image above is
opacity: 1;
position: absolute;
top: 50%;
left: 0;
-webkit-transform: translateY(-50%);
-ms-transform: translateY(-50%);
transform: translateY(-50%);
It's actually being caused by this css here which is reducing the size and causing the blur:
#qodef-page-header .qodef-header-logo-link img {
display: block;
margin: auto 0;
width: auto; // Comment this out or delete
max-height: 100%; // Comment this out or delete
-webkit-transition: opacity .3s ease;
-o-transition: opacity .3s ease;
transition: opacity .3s ease;
}
If you get rid of those, it shows at it's intended size.
This is actually a relatively common issue with using the (relatively old hat) method of vertical centering with absolute positions. A quick search here, The Goog, The duck site, etc, will show many results for "blurry <element> with transforms`.
The easiest and most pragmatic way to deal with this is to not use the "absolute/50%/transform -50%" method to center elements, and upgrade to using flex, align-items: center and justify-content: center. There's all sorts of hacky ways to fix the blur, but you'll need to cycle through them and find which works for you (basically, it's being perfectly centered in a 69px tall element so it's got half a pixel on each side of center to deal with that it can't place, so it aliases it.)
However, with all of that said, it looks like you don't actually need a centering mechanism at all.
All you need to do is remove the actual position overrides and transforms. Here's your logo as it stands (it seems to be correct on mobile).
If you instead just used:
opacity: 1;
position: absolute;
It would look just fine:
Just remove the top, left and vendor-prefixed transform: translateY and you should be good to go.
(The previews in the answer may be blurry, click on them to open them up though, I promise the latter one is crisp, lol)

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.

Simple AngularJS with CSS animation

I have read a couple of tutorials online, but I can't seem to get a cross-browser working example together.
HTML:
<div ng-include="show ? 'views/registration/form_activation.html' : null" ng-animate class="drop-down"></div>
CSS:
/* ANIMATIONS */
.drop-down {
-webkit-transition: all linear 1s;
-moz-transition: all linear 1s;
-ms-transition: all linear 1s;
-o-transition: all linear 1s;
transition: all linear 1s;
line-height: 100%;
}
.drop-down.ng-enter,
.drop-down.ng-leave-active {
opacity: 0;
max-height: 0px;
}
.drop-down.ng-enter-active,
.drop-down.ng-leave {
opacity: 1;
max-height: 100%;
}
What I would like to accomplish is that when the template is loaded with ng-include, it fades in from 0 to 100 opacity, and that it simultaneously opens like a dropdown (starting from 0, to full height that it needs). And vice versa when the form gets hidden.
The opacity already works, but changing the height does not, the div instantly appears with full height. Can some help me build the CSS with a cross-browser solution?
you have to define max-height in px in .drop-down class to make it work.
you can put any high value to max-height in px as you are anyways not defining the height.
also define overflow: hidden in .drop-down so that content is hidden on transition of height.
worked for me.
example demo here :- http://plnkr.co/edit/rXQQHTogKzAG91xw3JUx?p=preview

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

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)

Resources