尝试font-weight
使用 CSS 从“400”优雅地过渡到“600”,但它似乎在 Chrome 中不起作用。这是一个已知的错误还是我做错了什么?
8 回答
问题是字体权重,当以数字表示时,必须是 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>
提供不仅仅是普通和粗体的字体的数字字体粗细。如果给出的确切重量不可用,则 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 之间会有巨大的变化(较轻的重量遇到较深的重量)。
根据大量测试,目前 Chrome 和 IE-10 不支持字体粗细动画。这在未来可能会改变。
我来这里是为了自己找出如何转换字体粗细的答案,当我读到上面批准的答案说它不能完成(或者至少不是很好)时,我很失望。
由于字体粗细动画不可用,我决定尝试另一种效果,它实际上为您提供了字体粗细效果……我什至认为它不适用于这种类型的过渡。
以下是如何使体重增加:
.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;
}
完美流畅,正是我第一次到达此页面时所寻找的。希望它可以帮助某人。
字体不是简单的矢量图像集合(这就是 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 字体对于文本使用来说是废话。
通过同时进行快速颜色过渡(浅灰色到深蓝色),我似乎意外地获得了“字体粗细”过渡效果。
虽然没有直接的方法让字体粗细平滑过渡,但我找到了一种间接的方法(尽管有一些限制)。
本质上,您可以简单地使用其中一个伪元素来制作要转换为粗体字体的元素的镜像副本,其中伪元素上的字体粗细为粗体,不透明度为 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;
}
第二个限制来自该技术的性质,即因为您只是将伪元素覆盖在原始元素上,因此该元素需要具有纯色背景,否则这将不起作用,因为原始元素将在背景中保持可见。
您应该真正注意的一件事是伪元素和原始元素具有相同的尺寸,为此,在演示中,我已经删除了伪元素上的填充,因此您可能需要做类似的事情.
正如你所看到的,这种获得字体粗细转换的方法并非没有问题,而且远非理想,但这是我目前能想到的最好的方法,在有限的情况下,比如按钮,这不是很有用,如果即使在旧版浏览器中,正确完成也会看起来不错。
我已经调整了@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 发布的最初想法对我来说很重要。我接受这样一个事实,即正常和粗体之间的宽度应该不同,因为这是不同字体粗细的意图。所以,恕我直言,真正的挑战是弄清楚如何以一种流畅、不刺耳的方式在这两种外观之间穿梭。到目前为止,这似乎是我找到的最好的解决方案。
使用不限于 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>