Chrome中的字体权重转换

时间:2013-05-18 22:48:42

标签: css css3 google-chrome fonts css-transitions

尝试让font-weight使用CSS优雅地从'400'过渡到'600',但它似乎无法在Chrome中运行。这是一个已知的错误还是我做错了什么?

Check the Fiddle here for an example

8 个答案:

答案 0 :(得分:47)

问题在于字体权重(以数字表示)必须是100的倍数。要在400到600之间设置动画,字体将从400变为500到600(如果您愿意,则为3'帧)并且不会看起来很顺利。动画不会每次增加1的重量(400,401,402 ......)它会使重量增加100(400,500,600)。如果你的动画持续2秒,1秒后重量突然变为500,2秒后重量突然变为600;没有中间变化。

你在这里尝试的另一个问题是你正在使用的字体(或者至少是JSFiddle的默认字体)对font-weight:500没有任何不同,这意味着它默认为400:

<p style="font-weight:400;">a - 400, normal</p>
<p style="font-weight:500;">a - 500 (no support, defaults to 400)</p>
<p style="font-weight:600;">a - 600 (bold)</p>
<p style="font-weight:650;">a - 650 (not valid, defaults to 400)</p>

http://jsfiddle.net/r4gDh/6/

  

提供超过普通和粗体的字体的数字字体粗细。如果给出的确切重量不可用,则600-900使用最接近的可用较暗的重量(或者,如果没有,则使用最接近的较轻重量),并且100-500使用最接近的较轻重量(或者,如果没有则) ,最接近可用的较暗的重量)。这意味着对于仅提供普通和粗体的字体,100-500是正常的,600-900是粗体。

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

这基本上意味着您无法顺利动画font-weight。即使您支持100到900之间的所有重量,这种变化也不会令人愉快,并且会在500到600之间发生巨大变化(其中较轻的重量满足较重的重量)。

答案 1 :(得分:13)

Chrome和IE-10目前不支持基于大量测试的字体权重动画。这可能在将来发生变化。

答案 2 :(得分:7)

字体不是简单的矢量图像集合(这就是为什么svg字体永远不会起飞)。 Opentype字体包括将字体钳位到像素网格的各种魔法,这使得期望字体系列包含每个可能的权重值是不现实的。

由于字体不是简单的矢量图像集合,因此它们也不会线性调整大小 - 将像素网格考虑在内。

此Google白皮书解释了为什么线性调整大小不适用于当前屏幕上的文本 https://docs.google.com/document/d/1wpzgGMqXgit6FBVaO76epnnFC_rQPdVKswrDQWyqO1M/edit

这就是没有浏览器会尝试它的原因,它们都依赖于预先计算的字体权重。

十年间视网膜显示器是最低的共同点,但目前的字体技术可以锁定目前的屏幕,这可能会有所改变。

此Microsoft白皮书记录了一些标准字体权重值 http://blogs.msdn.com/cfs-filesystemfile.ashx/__key/communityserver-components-postattachments/00-02-24-90-36/WPF-Font-Selection-Model.pdf

(但仅仅因为它们被记录并不意味着实际包含所有这些字体的字体数量不是很少)

你可以使用svg字体和一些javascript实现你想要的效果。 svg字体虽然是文本用的垃圾。

答案 3 :(得分:6)

我来到这里是为了找出自己如何过渡字体重量的答案,当我读到上面批准的答案说它无法完成(或者至少不是很好)时,我感到很失望。

由于字体权重动画不可用,我决定尝试另一种效果,实际上会给你一种字体权重效果......我甚至认为这种效果不适用于此类过渡。

以下是如何使体重增长:

.weightGrow:hover {
    text-shadow:
    -1px -1px 0 #2DD785,
    1px -1px 0 #2DD785,
    -1px 1px 0 #2DD785,
    1px 1px 0 #2DD785;
    -webkit-transition: all .5s;
    -moz-transition: all .5s;
    -o-transition: all .5s;
    transition: all .5s;
}

当我第一次到达这个页面时,非常流畅,正是我所寻找的。希望它可以帮到某人。

答案 4 :(得分:4)

我似乎意外地通过快速颜色过渡(浅灰色到深蓝色)同时获得了“字体 - 重量”过渡效果。

答案 5 :(得分:2)

虽然没有直接的方法让字体权重平滑过渡,但我已经找到了一种间接做到这一点的方法(虽然有一些限制)。

本质上,您可以简单地使用其中一个伪元素,以便为要转换为粗体的字体生成元素的镜像副本,其中伪元素上的font-weight为粗体,不透明度为0。并且在悬停时只需转换伪元素的不透明度,即可实现非常平滑的过渡。

你可以在这里看到一个演示:
http://jsfiddle.net/r4gDh/45/

HTML:

<div class="element" data-text="text will turn to bold on hover">
  text will turn to bold on hover
</div>

在HTML中你已经可以看到其中一个限制,因为我们使用伪元素,我们也需要将元素的内容作为属性传递,因此内容是重复的。

CSS:

.element,
.element::before {
    background: red;
    font-weight:normal;
    font-size:40px;

    text-align:center;

    display: inline-block;

    padding: 0px 30px 0px 30px;

    position: relative;
    top: 0;
    left: 0;
}
.element::before {
    position: absolute;
    top: 0;
    left: 0;

    width: 100%;
    height: 100%;

    padding: 0;

    content: attr(data-text);
    opacity: 0;

    font-weight: bold;

    transition: all 1s linear;
}
.element:hover::before {
    opacity: 1;
}

第二个限制来自于技术的本质,即因为你只是将伪元素覆盖在原始元素上,然后元素需要具有实体背景,否则这将无法工作,因为原始元素将保持可见背景。

你应该关注的一件事是,伪元素和原始元素具有相同的尺寸,为此,在演示中,我已经删除了伪元素上的填充,所以你可以需要做类似的事情。

正如你所看到的,这种获得字体 - 重量转换的方式并非没有它的问题而且远非理想,但这是我目前能想到的最好的,在有限的情况下,如按钮和什么这不是很有用,如果正确完成,即使在旧版浏览器中看起来也不错。

答案 6 :(得分:0)

我已经调整了@Idra的提琴,使法线到粗体的过渡更加平滑。这是小提琴:http://jsfiddle.net/y7rLwx95/

更改...由于加粗时文本宽度会变宽,因此我通过增加字母间距添加了初始的“拉伸”过渡:

.element:hover {
   letter-spacing: 0.9px;
   transition: all .3s linear;
}

然后延迟了粗体:: before元素的淡入:

.element:hover::before {
   opacity: 1;
   transition-delay: .2s
}

这里还有一些其他调整:

.element::before {
   transition: all .3s linear;  /* replace */
   letter-spacing: 0;           /* additional */
}

过渡时间正是我觉得合适的时间。 @Idra发布的最初想法对我很重要。我接受这样的事实,即正常字体和粗体字体的宽度不同,因为这是不同字体粗细的目的。因此,恕我直言,真正的挑战是要找到一种如何以平滑,无刺激的方式在两种外观之间过渡的方法。到目前为止,这似乎是最好的解决方案。

答案 7 :(得分:0)

使用不限于以 100 为增量的可变字体可以实现平滑的字体粗细过渡和动画。有关可变字体的更多信息,请访问:https://web.dev/variable-fonts/

试试这个片段,例如。 https://fonts.google.com/specimen/Raleway

@font-face {
  font-family: 'Raleway Flex';
  src: url('Raleway-VariableFont_wght.ttf');
  font-weight: 100 900;
}

h1 {
  font-family: 'Raleway Flex', sans-serif;
  animation: example 1s linear 0s infinite alternate both;
}

@keyframes example {
  from {
    font-weight: 100;
  }
  to {
    font-weight: 900;
  }
}
<h1>HELLO</h1>
<p>I look way smoother if you use a variable font.</p>