此问题似乎会影响所有基于 WebKit 的浏览器,包括 iPhone。
首先是一些背景知识。我正在开发的网站使用基于 JavaScript 的“滑块”动画。
我正在使用 -webkit-transform:translate3d
来“增强”实际动画。与基于 JavaScript 的方法相反,使用此方法时,一旦内容被动画化,文本就会变得完全模糊。这在 iPhone 上尤其明显。
我看到的一些解决方法是删除相对定位(我这样做了),并添加了 -webkit-font-smoothing: antialiased
规则(我也这样做了)。这两项改变都没有产生丝毫影响。
我能够在没有模糊文本的情况下正常工作的唯一方法是使用常规 JavaScript 进行动画并完全绕过 translate3d
。我更喜欢使用 translate3d
因为它在支持 WebKit 的设备上执行速度快得多,但我一生都无法弄清楚为什么它会影响这样的文本一个糟糕的方法。
任何建议或解决方案将不胜感激。
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.
发布评论
评论(20)
这些似乎都不适合我,但我找到了一个稍微肮脏的解决方案,它似乎可以解决问题:
None of these seem to have worked for me but I've found a slightly dirty solution which seemed to do the trick:
我在 Ken Avila 的帖子中描述了完全相同的问题:CSS:转换:翻译(-50%,-50%)使文本模糊
问题当然是我使用了transform:translate(-50%,-50%)这使得我的居中内容变得模糊,但仅在 osx 上的 safari 中。
不仅文本变得模糊,整个内容(包括图像)也变得模糊。
我继续阅读: http://keithclark.co.uk/articles/ gpu-text-rendering-in-webkit/
“模糊”是由于元素在非整数边界上渲染造成的。
我还发现,我可以避免在这篇文章的居中水平部分上使用变换平移: https://coderwall.com/p/quutdq/how-to-really-center-an-html-element-via-css-position-absolute-fixed - 唯一的缺点是我必须引入一个包装器。
我发现使用transform:translateY(-50%)不会产生任何“模糊”,可能是因为我的元素有一个设定的高度,因此不会最终在非整数边界上渲染。
因此我的解决方案最终是这样的:
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:
正如@Robert 上面提到的,有时添加背景会有所帮助,但并非总是如此。
因此,对于 Dmitry 添加的示例,这不是您必须做的唯一事情:除了后台之外,您必须告诉浏览器显式使用正确的抗锯齿功能,因此,有一个固定的 Dmitry 示例: http://jsfiddle.net/PtDVF/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:
您要翻译的元素必须能被偶数整除。
重要的是,无论您尝试移动一半的元素,其宽度和高度都可以被二整除。与响应式图像非常相似,物体可以移动 50% 而无需分割像素。
宽度为 503px、高度为 500px 的 div 会导致模糊,无论您以何种方式移动它,或者使用 TranslateX 或 Y 时移动多少。使用 Transform,它利用 GPU 图形加速器,结果应该非常清晰、平滑边缘。设置 box-sizing: border-box; 也可能是个好主意。确保计算的宽度包括填充和边框。
使用百分比宽度时要小心。如果它与屏幕尺寸相关,则任何其他屏幕像素宽度都会导致这种模糊。
Elements you are translating must be divisible by two with even numbers.
It's 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.
我通过在任何动画发生之前向元素添加
translate3d
样式来解决此问题。I fixed this problem by adding a
translate3d
style to the element before any animation occurs.这是最好的解决方案
translateX(calc(-50% + 0.5px))
This is the best solution
translateX(calc(-50% + 0.5px))
可能是最简单的解决方案:
缩放负责将像素值四舍五入为整数
Probably the easiest solution:
Scale-and-zoom takes care of rounding the pixel values to full numbers
使用CSS“round”函数解决老问题的新解决方案。
为了确保翻译后的块在整数坐标上渲染(假定父级已经在整数坐标上),我们可以使用“圆”功能。
居中示例:
ref: https://developer.mozilla.org/en -US/docs/Web/CSS/round
A new solution to an old problem using the CSS "round" function.
To ensure that the translated block is rendered on integer coordinates (given that the parent is already on integer coordinates), we can use the "round" function.
centering example:
ref: https://developer.mozilla.org/en-US/docs/Web/CSS/round
这些答案都不适合我,但使用却
成功了
None of these answers worked for me but using
did the trick
Neil Taylor 的解决方案是最好的,但它仍然可以改进:
transform:translateX(-50%)translateX(.5px)
这样它有 2 个优点:
Neil Taylor's solution was the best, but it can still be improved:
transform: translateX(-50%) translateX(.5px)
This way it has 2 advantages:
我希望这是将对象居中到屏幕的正中心。
变换时会发生模糊:translate(-50%,-50%);
因此,
我尝试使用 javascript 将样式注入到元素中。 (React.js)
通过 javascript 样式将样式注入到元素中,
例如。
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
I tried injecting style in to element using javascript. (React.js)
inject style into element by javascript style
Eg.
将容器中应用变换平移属性的任何元素的垂直边距(顶部边距或底部边距)或高度减少 1 个像素。
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.
将 Chrome 的缩放重置为 100% 对我来说很有效。
Resetting Chrome's zoom to 100% worked for me.
如果百分比用于动画,如果我们还考虑它的性能,那么它仍然可以接受,但是当您不使用
translate
进行动画时,它会有所不同,因为文本总是模糊的。使用百分比时,可能会出现小数,例如
0.5px
和文本模糊的原因。在我的实验中,使用translate(0.5px, 0.5px)
会使文本非常模糊,因此您应该避免使用0.3px <=> 之间的小数。 0.7px
而0.2px 和 0.8px
仍然可以接受。我的建议是使用 JavaScript 并将百分比转换为圆角像素以对元素进行动画处理,如果使用
translate
来定位元素,则使用像素而不是百分比。另一种选择是使用
left
和top
设置带有百分比的初始位置,然后使用transform:使用目标位置的像素翻译()
,并仅使用transition-property:transform;
对变换
进行动画处理If the percentage is used for animation it still acceptable if we also consider it's performance, but when you're not using
translate
for animation it would different because the text will always blurry.When using percentage it's possible of having fractional number like
0.5px
and that the reason why the text was blurry. On my experiment usingtranslate(0.5px, 0.5px)
would make the text very blurry, so you should avoid fractional number between0.3px <=> 0.7px
while0.2px and 0.8px
still acceptable.My suggestion is using JavaScript and turn the percentage into rounded pixel for animating the element, and using pixel instead of percentage if
translate
is being used for positioning the element.The other alternative is using
left
andtop
to set the initial position with percentage then usetransform: translate()
with pixel for the target position and animate thetransform
only withtransition-property: transform;
对于替代解决方案,请尝试:
For an alternative solution try:
使用
zoom
为我解决了这个问题。我刚刚添加了
zoom: 1.04;
Using
zoom
solved it for me.I just added
zoom: 1.04;
在我的案例中找到的解决方案是设置第一个子元素的高度值
Solution found in my case was setting a
height
value of the first child element@kizu
这些答案和建议没有帮助。对于您的 jsfiddle,您需要添加
-webkit-perspective-origin: 50% 50%;
-webkit 透视:1400px;
到要使用translate3d 的元素的父元素,否则平移z 轴实际上不会执行任何操作。在这种情况下,您将其应用到您单击的按钮,我认为您的意思是将其应用到内容。
但无论如何,添加这些来激活 z 轴更改会导致示例中的按钮模糊。
我也很想找到解决这个问题的办法,恐怕没有。
@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.
我在这些类型的问题上使用
will-change
,它通常可以解决缩放问题或舍入错误,例如看到分隔元素的 1px 白线。will-change:transform;
在此处阅读更多内容:
https://developer.mozilla.org/en-US/文档/Web/CSS/will-change
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
使用 HTML5 文档类型为我解决了这个问题。
Using the HTML5 doctype solved the issue for me.