transform 文字模糊

字数 520阅读 102

自从发现transform里的translate后,自己定义弹窗提示类的都用此属性和position: fixed;。然而,今天突然发现,以往好好的效果,今天出现了文字模糊的情况。然后网上搜了资料,加上自己写demo验证,发现确实有这种情况,只是触发的条件,一般不会碰到而已。

问题:transform 文字模糊

此处只讨论position: fixed;+transform: translate3d(x,y,0);的场景,网上不少资料说,是因为transform的标签元素不是偶数导致的,经过我的验证,我觉得不准确,因为使用transform: translate(x,y,0);时,浏览器会根据该标签元素宽高加上transform属性计算出位置的x和y坐标位置,其实最终的计算结果有小数点都会导致文字模糊的情况。

原因:transform变换会在浏览器上单独创建一个绘画层并重新进行渲染,rotate渲染的时候,由于图层渲染的时候也处理了周围的文字,如果高度为奇数的文字可能会存在半个像素的计算量,浏览器对这半个像素会进行优化渲染,所以边缘会出现模糊的情况。

下面上效果图和源代码:
效果图:


transform-test0.png

代码:

 <!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta http-equiv="Access-Control-Allow-Origin" content="*">
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
    <meta name="format-detection" content="telephone=no">
    <title>transform 文字模糊问题</title>
    
<style type="text/css">
*{
  margin: 0;
  padding: 0;
}
.clear:after{
  content: '';
  display: block;
  width: 0;
  height: 0;
  clear: both;
}
body{
  line-height: 24px;
  font: 14px Helvetica Neue,Helvetica,PingFang SC,Tahoma,Arial,sans-serif;
}
h1,h2,h3{
  font-weight: 400;
}
.con{
  position: relative;
  width: 100%;
  height: 1000px;
  background: #eee;
}

.layerdiv {
    /*w:231,h: 72;*/
    background: #dedada;
    position: fixed;
    z-index: 1000;
    top: 50%;
    left: 50%;
    border-radius: 3px;
    transform: translate(-50%, -50%);
    width: 232px;
}
.layerdiv1 {
    background: #dedada;
    position: fixed;
    z-index: 1000;
    top: 50%;
    left: 50%;
    border-radius: 3px;
    transform: translate(-50%, 60%);
}
.layerdiv2 {
    background: #dedada;
    position: fixed;
    z-index: 1000;
    top: 50%;
    left: 50%;
    border-radius: 3px;
    transform: translate(-50%,-123.5px);
    width: 232px;
}
  </style>
</head>
<body>

<div class="layerdiv">
  <h2>测试文字模糊问题嘿嘿嘿</h2>
  <h3>0测试文字模糊问题嘿嘿嘿</h3>
  <h4>fixed+transform(整数)</h4>
</div>

<div class="layerdiv1">
  <h2>测试文字模糊问题嘿嘿嘿</h2>
  <h3>1测试文字模糊问题嘿嘿嘿</h3>
  <h4>fixed+transform(非整数)</h4>
</div>
<div class="layerdiv2">
  <h2>测试文字模糊问题嘿嘿嘿</h2>
  <h3>2测试文字模糊问题嘿嘿嘿</h3>
  <h4>fixed+transform(非整数)</h4>
</div>


<div class="con">
  带滚动条的内容页
</div>

</body>
</html>

解决方法

  • 宽高可固定:尽量把你的弹窗定义成偶数,这样transform: translate3d(-50%,-50%,0);计算的最终位置坐标就不会带小数(这时,其实不需要用transform属性也能解决,margin-left和margin-top就可以)。(适用场景:窄)
  • 宽高不固定:(需要多加一层div标签,最后会附上代码)
    • 利用flex布局解决(适用场景:非常广)
    • 利用inline-block解决(适用场景:非常广)
    • 利用table布局解决(适用场景:比较广)

解决方式的代码:

 <!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta http-equiv="Access-Control-Allow-Origin" content="*">
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
    <meta name="format-detection" content="telephone=no">
    <title>transform 文字模糊问题</title>

<style type="text/css">
*{
  margin: 0;
  padding: 0;
}
.clear:after{
  content: '';
  display: block;
  width: 0;
  height: 0;
  clear: both;
}
body{
  line-height: 24px;
  font: 14px Helvetica Neue,Helvetica,PingFang SC,Tahoma,Arial,sans-serif;
}
h1,h2,h3{
  font-weight: 400;
}
.con{
  position: relative;
  width: 100%;
  height: 1000px;
  background: #eee;
}
.layerdiv {
    background: #dedada;
    position: fixed;
    z-index: 1000;
    top: 50%;
    left: 50%;
    border-radius: 3px;
    transform: translate(-50%, -200%);
    width: 232px;
    height: 70px;
}
/*flex布局解决方式*/
.layerdiv-flex {
    display: flex;
    width: 100%;
    height: 100%;
    position: fixed;
    z-index: 9999;
    align-items: center;
    justify-content: center;
    /*background: rgba(0,0,0,0.5);*/
}
.layerdiv-flex .tips{
    position: relative;
    background: #dedada;
    box-shadow: 0 3px 6px #f00;
}
/*inline-block布局解决方式*/
.layerdiv-inline {
    position: fixed;
    z-index: 9999;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
    /*background: rgba(0,0,0,0.5);*/
    text-align: center;
}
.layerdiv-inline:after {
    content: "";
    display: inline-block;
    height: 100%;
    width: 0;
    vertical-align: middle;
}
.layerdiv-inline .tips{
    position: relative;
    background: #dedada;
    box-shadow: 0 3px 6px #f00;

    display: inline-block;
    vertical-align: middle;
}
/*table布局解决方式*/
.layerdiv-table {
    width: 100%;
    height: 100%;
    position: fixed;
    z-index: 9999;
    /*background: rgba(0,0,0,0.5);*/
    display: table;
    text-align: center;
}
.layerdiv-table:after {
    content: "";
    display: inline-block;
    height: 100%;
    width: 0;
    vertical-align: middle;
}
.layerdiv-table .tips{
    position: relative;
    background: #dedada;
    box-shadow: 0 3px 6px #f00;

    display: table-cell;
    vertical-align: middle;
}
  </style>
</head>
<body>

<div class="layerdiv-flex ">
  <div class="tips">
    <h2>测试文字模糊问题嘿嘿嘿</h2>
    <h3>测试文字模糊问题嘿嘿嘿</h3>
    <h4>fixed+transform(非整数)</h4>
  </div>
</div>

<!-- <div class="layerdiv-inline ">
  <div class="tips">
    <h2>测试文字模糊问题嘿嘿嘿</h2>
    <h3>测试文字模糊问题嘿嘿嘿</h3>
    <h4>fixed+transform(非整数)</h4>
  </div>
</div>

<div class="layerdiv-table ">
  <div class="tips">
    <h2>测试文字模糊问题嘿嘿嘿</h2>
    <h3>测试文字模糊问题嘿嘿嘿</h3>
    <h4>fixed+transform(非整数)</h4>
  </div>
</div> -->

<div class="layerdiv">
  <h2>测试文字模糊问题嘿嘿嘿</h2>
  <h3>测试文字模糊问题嘿嘿嘿</h3>
  <h4>fixed+transform(整数)</h4>
</div>

<div class="con">
  带滚动条的内容页
</div>

</body>
</html>

推荐阅读更多精彩内容