12

I noticed that there is a big quality difference when transforming text in this 2 ways:

.text1 {
  width: 200px;
  height: 22px;
  position: absolute;
  top: 40%;
  left: 0;
  transform-origin: 50% 50%;
  transform: scale(2); /* here */
  color: red;
  text-align: center;
  font-size: 22px;
}
.text2 {
  width: 200px;
  height: 22px;
  position: absolute;
  top: 60%;
  left: 0;
  transform-origin: 50% 50%;
  transform: translateZ(400px); /* here */
  text-align: center;
  font-size: 22px;
}
.perspective {
  width: 200px;
  height: 200px;
  perspective: 800px;
  transform-style: preserve-3d;
}
<div class="perspective">
  <div class="text1">Text</div>
  <div class="text2">Text</div>
</div>

Is there a way to force a better rendering when displacing text on the Z axis?

Vandervals
  • 5,774
  • 6
  • 48
  • 94
  • Might want to check this out: http://stackoverflow.com/questions/26176557/text-blurry-after-3d-transform. There doesn't seem to be a perfect solution but toggling the font-size and scale properties can help. – serraosays Sep 21 '15 at 15:17
  • @staypuftman, this kind of makes the "canvas" where drawing the font bigger, therefore you can display it bigger as well, but doesn't solve the problem for "any transform measure" – Vandervals Sep 21 '15 at 15:20

2 Answers2

13

the reason the text blurs when you're transforming with translateZ(400px) is that this is a 3D transformation ; the browser treats the element as textures instead of vectors in order to provide hardware 3d acceleration.
So basically the resolution will be lower when increasing size.

On the other hand transforming with scale is a 2D transformation, the browser treats the element as vector and blurring doesn't occur.


take a look at what happens to scale as soon as we kick in with 3d, without actually setting any translateZ value:

.text1 {
    width: 200px;
    height: 22px;
    position: absolute;
    top: 40%;
    left: 0;
    transform-origin: 50% 50%;
    transform: scale(2);
    /* here */
    color: red;
    text-align: center;
    font-size: 22px;
}
.text1a {
    width: 200px;
    height: 22px;
    position: absolute;
    top: 40%;
    left: 50%;
    transform-origin: 50% 50%;
    transform: translateZ(0) scale(2);
    /* here */
    color: blue;
    text-align: center;
    font-size: 22px;
}
.text2 {
    width: 200px;
    height: 22px;
    position: absolute;
    top: 60%;
    left: 0;
    transform-origin: 50% 50%;
    transform: translateZ(400px);
    /* here */
    text-align: center;
    font-size: 22px;
}
.perspective {
    width: 200px;
    height: 200px;
    perspective: 800px;
    transform-style: preserve-3d;
}
<div class="perspective">
    <div class="text1">Text</div>
    <div class="text1a">Text</div>
    <div class="text2">Text</div>
</div>

the only workaround I can think of at the moment is checking the stylesheet through JS and overriding translateZ with transform: scale

var styles = document.styleSheets;

//patterns
var perspPat = /perspective\s*?:\s*?(\d+)/;
var transZPat = /translateZ\(\s*?(\d+)/;

var perspective;
var translateZ = [];
[].slice.call(styles).forEach(function (x) {
    [].slice.call(x.rules).forEach(function (rule) {
        if (perspPat.test(rule.cssText)) {
            perspective = perspPat.exec(rule.cssText)[1]
        };
        if (transZPat.test(rule.cssText)) {
            translateZ.push([
            rule.selectorText,
            transZPat.exec(rule.cssText)[1]]);
        }


    });

})


translateZ.forEach(function (x) {
    document.querySelector(x[0]).style.transform = 'scale(' + perspective / x[1] + ')';

})

fiddle

As you can see, even if it does work, a lot of optimization is needed.. (I wouldn't consider it production ready in it's current state ).

maioman
  • 18,154
  • 4
  • 36
  • 42
-2

You can add font-smooth (for firefox), and antialiasing for webkit

 .text2 {
    -webkit-font-smoothing: antialiased;
    font-smooth: always;
 }

https://developer.mozilla.org/en-US/docs/Web/CSS/font-smooth

http://davidwalsh.name/font-smoothing

Marcos Pérez Gude
  • 21,869
  • 4
  • 38
  • 69