Webkit-based blurry/distorted text post-animation via translate3d

烈酒焚心 提交于 2019-12-17 03:53:50

问题


This issue appears to affect all WebKit-based browsers, including the iPhone.

First some background. The site I'm working on uses a JavaScript-based 'slider' animation.

I'm using -webkit-transform: translate3d to 'power' the actual animation. When using this method, as opposed to a JavaScript-based method, the text becomes all blurry once the content has been animated. This is especially noticeable on the iPhone.

A few workarounds I saw were to remove an relative positioning, which I did, and to add a rule for -webkit-font-smoothing: antialiased, which I also did. Neither change made the slightest difference.

The only way I could make this work properly without blurry text was to use regular JavaScript for the animation and bypass the translate3d altogether. I'd prefer to use translate3d because it performs much faster on WebKit-enabled devices, but for the life of me I cannot figure out why it is affecting the text in such a poor way.

Any suggestions or solutions would be greatly appreciated.


回答1:


As @Robert mentioned above, sometimes adding background helps, but not always.

So, for the example Dmitry added that's not the only thing you must do: except from the background, you must tell browser to explicitly use the proper anti-aliasing, so, there is a fixed Dmitry's example: http://jsfiddle.net/PtDVF/1/

You need to add these styles around (or for the) blocks where you need to fix the anti-aliasing:

background: #FFF; /* Or the actual color of your background/applied image */
-webkit-font-smoothing: subpixel-antialiased;



回答2:


None of these seem to have worked for me but I've found a slightly dirty solution which seemed to do the trick:

top: 49.9%;
left: 49.9%;
-webkit-transform: translate(-50.1%, -50.1%);
transform: translate(-50.1%, -50.1%);



回答3:


I had the exact same problem described in Ken Avila's post: CSS: transform: translate(-50%, -50%) makes texts blurry

The problem was of course that I used transform: translate(-50%, -50%) which made my centered content become blurry, but only in safari on osx.

It is not only the text that becomes blurry, but the entire content, including images. I read on: http://keithclark.co.uk/articles/gpu-text-rendering-in-webkit/ that the "blurryness" is due to that the element is rendered on a non-integer boundary.

I also discovered that I could avoid using transform translate on the horizontal part of my centering from this post: https://coderwall.com/p/quutdq/how-to-really-center-an-html-element-via-css-position-absolute-fixed -The only minus was that I had to introduce a wrapper.

I discovered that using transform: translateY(-50%) didn't create any "bluryness", maybe because my element has a set height and thus does not end up rendering on a non-integer boundary.

My solution therefore ended up like this:

.wrapper {
  position: fixed;
  left: 50%;
  top: 50%;
}
.centered {
  position: relative;
  left: -50%;
  -webkit-transform: translateY(-50%);
  -ms-transform: translateY(-50%);
  transform: translateY(-50%);
}
<div class="wrapper">
  <div class="centered">
    Content
  </div>
</div>



回答4:


I fixed this problem by adding a translate3d style to the element before any animation occurs.

-webkit-transform: translate3d(0,0,0); 



回答5:


Elements you are translating must be divisible by two with even numbers.

I'ts important that whatever element you're trying to shift over by half is divisible by two for both it's width and height. Very similar to the responsive images, when things can be moved by 50% without splitting pixels.

A div with a width of: 503px and a height of 500px will cause blurring, no matter which way you move it or by how much when using translateX or Y. Using transform, it utilizes GPU graphics accelerator which should result is very crisp, smooth edges. It might also be a good idea to set box-sizing: border-box; to ensure calculated widths include padding and borders.

Be careful when using percentage widths. If it's relative to screen size, ever other screen pixel width will cause this blur.




回答6:


This is the best solution translateX(calc(-50% + 0.5px))




回答7:


Probably the easiest solution:

transform: translate(-50%, -50%) scale(2); 
zoom:.5;

Scale-and-zoom takes care of rounding the pixel values to full numbers




回答8:


None of these answers worked for me but using

display: inline-table;

did the trick




回答9:


Using zoom solved it for me.

I just added zoom: 1.04;




回答10:


I hope this is about centering the object into exact center of the screen. Blurring happens with the transform: translate(-50%,-50%);

so instead doing

position: absolute;
margin:0;
top: 50%;
left: 50%;
transform: translate(-50%,-50%);

I tried injecting style in to element using javascript. (React.js)

const node = ReactDOM.findDOMNode(this);
var width = node.offsetWidth;
var height = node.offsetHeight;
var windowWidth = window.innerWidth;
var windowHeight = window.innerHeight;

style={
    left : (windowWidth/2) - (this.state.width/2) + 'px',
    right:  (windowWidth/2) - (this.state.width/2) + 'px',
    top: (windowHeight/2) - (this.state.height/2) + 'px',
    bottom: (windowHeight/2) - (this.state.height/2) + 'px'
}

inject style into element by javascript style

Eg.

export default class Dialog extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            width: '0px',
            height: '0px'
        };
    }

    setWidthhandHeight(node){
        if (this.state.width !== node.offsetWidth) {
            this.setState({
                width: node.offsetWidth,
                height: node.offsetHeight
            });
        }
    }

    componentDidMount() {
        this.setWidthhandHeight(node);
    }

    render() {
        const windowWidth = window.innerWidth;
        const windowHeight = window.innerHeight;
        return (
            <dialog className={this.props.className + " dialog"}
                    style={{
                        left : (windowWidth/2) - (this.state.width/2) + 'px',
                        right:  (windowWidth/2) - (this.state.width/2) + 'px',
                        top: (windowHeight/2) - (this.state.height/2) + 'px',
                        bottom: (windowHeight/2) - (this.state.height/2) + 'px'
                    }}>
                {this.props.title ? (
                    <header><span>{this.props.title}</span></header>
                    )
                    : null
                }
                {this.props.children}
            </dialog>
        );
    }
}



回答11:


Reduce the vertical margin(margin-top or margin-bottom) or height of any element in the container on which transform translate property is being applied by just 1 pixel.




回答12:


Neil Taylor's solution was the best, but it can still be improved:

transform: translateX(-50%) translateX(.5px)

This way it has 2 advantages:

  • It works in crappy browsers like IE11 (which doesn't support calc inside translate)
  • It only calculates at parse time, not every time the browser evaluates.



回答13:


Resetting Chrome's zoom to 100% worked for me.




回答14:


@kizu These answers and suggestions do not help. For your jsfiddle you need to add

-webkit-perspective-origin: 50% 50%; -webkit-perspective: 1400px;

to the parent element of the element you want to use translate3d on, otherwise translating the z-axis doesn't actually do anything. In this case you are applying it to the button you click, I think you meant to apply it to the content.

But anyway, adding those to activate z-axis change causes the blur to the button in your example.

I would love to find a solution to this as well, I fear there isn't one.




回答15:


For an alternative solution try:

-webkit-text-stroke: 0.35px



回答16:


I use will-change on these types of issues, it usually solves scaling issues or rounding errors, such as seeing a 1px white line separating elements for example.

will-change: transform;

Read more here: https://developer.mozilla.org/en-US/docs/Web/CSS/will-change




回答17:


Solution found in my case was setting a height value of the first child element




回答18:


.row{
        height: 100vh;
        background-color:black;
      }
      .align-center{
        left:50%;
        top:50%;
        background-color:green;
      }
      
      .translate3d{
        transform: translate3d(-50%,-50%,0);
      }
      .translateXY{
        transform: translateX(-50%) translateY(-50%);
      }
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" rel="stylesheet"/>
<div class="row">
      <div class="col">
        <h1 class="text-center position-absolute align-center text-white translate3d font-weight-bold">BLURRED</h1>
      </div>
      <div class="col">
        <h1 class=" text-center position-absolute align-center text-white font-weight-bold translateXY  ">CLEAR</h1>
      </div>

I also had same issue when i used translateZ, it got resolved when i used translateX and translateY together and not translateZ , like this

transform: translateX(-50%) translateY(-50%);

works with transparent background as well, not sure why but worked for me atleast




回答19:


Using the HTML5 doctype solved the issue for me.

<!doctype html>
<html>
<head>
<meta charset="UTF-8">


来源:https://stackoverflow.com/questions/6411361/webkit-based-blurry-distorted-text-post-animation-via-translate3d

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!