父元素transform小数导致子元素文字外边缘模糊解决方案,及css新特性介绍

8046次浏览

前言

今天将解决 transform导致文字 的模糊问题。 那么?什么时候会触发这种问题呢?在 Google 上,其实我们能搜到非常多类似的案例,总结而言:

一、当文本元素的某个祖先容器存在 transform: translate() 或者 transform: scale() 等 transform 操作时,容易出现这种问题

当然,这只是必要条件,不是充分条件。继续深入探究,会发现,必须还得同时满足一些其它条件:

二、元素作用了 transform: translate() 或者 transform: scale() 后的计算值产生了非整数

例如:

.container {
    position: absolute;
    width: 1104px; 
    height: 475px;
    top: 50%;
    transform: translateY(-50%);
    // ...
}

由于元素的高度为 475px,translateY(-50%) 等于 237.5px,非整数,才导致了内部的字体模糊。

但是,需要注意的是,并非所有产生的非整数都会导致了内部的字体模糊。

三、文本内容是否模糊还与屏幕有关,高清屏(dpr > 2)下不容易触发,更多发生在普通屏幕下(dpr = 1)

如何解决上面问题

使用css新特性 round() 函数解决模糊问题

我们可以通过 round() 函数,保证作用了 transform: translate() 或者 transform: scale() 后的计算值一定是正整数,从而避免模糊问题。

譬如,原本的 CSS 如下:

.container {
    width: 50vw;
    height: 50vh;
    transform: translate(-50%, -50%);
}

此时,transform: translate() 的实际最终计算值是会出现小数的。因此,我们可以使用 round() 函数进行取整:

.container {
    width: 50vw;
    height: 50vh;
    transform: translate(round(-50%, 1px), round(-50%, 1px));
}

round() 应用

round() 还有一个有趣用法。我们可以使用 round() 实现类似于 CSS Animation 中的 steps() 步骤动画的效果。

<div></div>

@property --angle {
  syntax: '<angle>';
  inherits: false;
  initial-value: 0deg;
}

div {
    width: 200px;
    height: 200px;
    border-radius: 50%;
    background: conic-gradient(#fc0, #fc0 15deg, transparent 15deg, transparent 30deg);
    transform: rotate(var(--angle));
    animation: propertyRotate 2s infinite linear;
}

@keyframes propertyRotate {
    100% {
        --angle: 360deg;
    }
}

其他css函数

在 CSS 中,存在许多数学函数,这些函数能够通过简单的计算操作来生成某些属性值,例如 :

calc():用于计算任意长度、百分比或数值型数据,并将其作为 CSS 属性值。

min() 和 max():用于比较一组数值中的最大值或最小值,也可以与任意长度、百分比或数值型数据一同使用。

clamp():用于将属性值限制在一个范围内,支持三个参数:最小值、推荐值和最大值。

最近各大浏览器也逐渐开始原生支持的三角函数:

sin()

cos()

tan()

CSS 三角函数语法介绍

.box {
  /* 设置元素的宽度为 sin(30deg) 的值 */
  width: calc(sin(30deg) * 100px);

  /* 设置元素的高度为 cos(45deg) 的值 */
  height: calc(cos(45deg) * 100%);

  /* 设置元素的透明度为 tan(60deg) 的值 */
  opacity: calc(tan(60deg));
}

我们可以通过 transfrom,借助 CSS @Property 属性,来构造一个三角函数的使用场景:

.g-single {
    width: 20px;
    height: 20px;
    background: #000;
    border-radius: 50%;
    animation: move 5s infinite ease-in-out;
    transform: translate(
        calc(var(--dis) - 40vw),
        calc(5 * sin(var(--angle)) * 1em)
    );
}

@keyframes move {
    0% {
        --dis: 0px;
        --angle: 0deg;
    }
    100% {
        --dis: 80vw;
        --angle: 1080deg;
    }
}

尝试使用三角函数实现波浪线

<div></div>
<div></div>
<div></div>

@function shadowSet($vx, $vy, $color) {
    $shadow: 0 0 0 0 $color;

    @for $i from 0 through 50 {
        $x: calc(2 * sin(#{$i * 15 * 1deg}) * #{$vy});
        $y: $i * $vy;

        $shadow: $shadow, #{$x} #{$y} 0 0 $color;
    }

    @return $shadow;
}

div {
    margin: auto;
    width: 10px;
    height: 10px;
    border-radius: 50%;
    background: #f00;
    box-shadow: shadowSet(3px, 3px, #f00);
}
div:nth-child(2) {
    width: 6px;
    height: 6px;
    background: #fc0;
    box-shadow: shadowSet(3px, 3px, #fc0);
}
div:nth-child(3) {
    width: 4px;
    height: 4px;
    background: #000;
    box-shadow: shadowSet(2px, 2px, #000);
}

今天暂时总结到这里。

相关文章: