直接进入代码,这里有一个可行的实现
html {
font-size: 16px;
}
@media screen and (min-width: 320px) {
html {
font-size: calc(16px + 6 * ((100vw - 320px) / 680));
}
}
@media screen and (min-width: 1000px) {
html {
font-size: 22px;
}
}
值得一看我们最近发布的博文 简化流体排版,它提供了实用的、受限的、基于视窗的字体大小调整方案。
它会将 font-size
从最小 16px(在 320px 视窗下)调整到最大 22px(在 1000px 视窗下)。这是一个演示,但它采用 Sass @mixin(稍后会介绍)。
查看 使用 Sass 的流体字体的基本示例,由 Chris Coyier (@chriscoyier) 在 CodePen 上创建。
Sass 的使用只是为了使输出更容易生成,并且其中涉及一些数学运算。让我们来看看。
使用视窗单位和 calc()
,我们可以根据屏幕大小调整字体大小(以及其他属性)。因此,字体大小不是始终保持一致,也不是在媒体查询中从一个大小跳转到另一个大小,而是可以实现流畅变化。
这是数学运算,感谢 Mike Riethmuller
body {
font-size: calc([minimum size] + ([maximum size] - [minimum size]) * ((100vw - [minimum viewport width]) / ([maximum viewport width] - [minimum viewport width])));
}
数学运算之所以有点复杂,是因为我们试图避免字体大小小于最小值或大于最大值,而使用视窗单位很容易出现这种情况。
例如,如果我们希望字体大小在 14px
(最小视窗宽度为 300px
)到 26px
(最大视窗宽度为 1600px
)之间,则公式如下
body {
font-size: calc(14px + (26 - 14) * ((100vw - 300px) / (1600 - 300)));
}

查看 JEVevK,由 CSS-Tricks (@css-tricks) 在 CodePen 上创建。
要锁定最小和最大大小,可以使用媒体查询中的这种数学运算。以下是一些有帮助的 Sass 代码...
在 Sass 中
你可以创建一个(非常强大的)mixin,如下所示
@function strip-unit($value) {
@return $value / ($value * 0 + 1);
}
@mixin fluid-type($min-vw, $max-vw, $min-font-size, $max-font-size) {
$u1: unit($min-vw);
$u2: unit($max-vw);
$u3: unit($min-font-size);
$u4: unit($max-font-size);
@if $u1 == $u2 and $u1 == $u3 and $u1 == $u4 {
& {
font-size: $min-font-size;
@media screen and (min-width: $min-vw) {
font-size: calc(#{$min-font-size} + #{strip-unit($max-font-size - $min-font-size)} * ((100vw - #{$min-vw}) / #{strip-unit($max-vw - $min-vw)}));
}
@media screen and (min-width: $max-vw) {
font-size: $max-font-size;
}
}
}
}
使用方法如下
$min_width: 320px;
$max_width: 1200px;
$min_font: 16px;
$max_font: 24px;
html {
@include fluid-type($min_width, $max_width, $min_font, $max_font);
}
这是 Mike 的另一个示例,可以轻松地实现流畅的节奏

将理念扩展到标题和模块化尺度
模块化尺度意味着可用空间越多,大小差异越明显。也许在最大的视窗下,层次结构中每个标题的大小都是下一个标题的 1.4 倍,而在最小的视窗下,大小只有 1.05 倍。
查看
“流体字体”的灵感来自 @MikeRiethmuller,现在已发布到 @CodePen 博客。包括“流体模块化尺度!” pic.twitter.com/0yJk8Iq8fR
— Chris Coyier (@chriscoyier) 2016 年 10 月 27 日
使用我们的 Sass mixin,代码如下
$mod_1: 1.2; // mobile
$mod_2: 1.5; // desktop
h1 {
font-size: $mod_1*$mod_1*$mod_1*$mod_1 *1rem;
@include fluid-type($min_width, $max_width, $mod_1*$mod_1*$mod_1 *$min_font, $mod_2*$mod_2*$mod_2 *$min_font);
}
h2 {
font-size: $mod_1*$mod_1*$mod_1 *1rem;
@include fluid-type($min_width, $max_width, $mod_1*$mod_1*$mod_1 *$min_font, $mod_2*$mod_2*$mod_2 *$min_font);
}
h3 {
font-size: $mod_1*$mod_1 *1rem;
@include fluid-type($min_width, $max_width, $mod_1*$mod_1 *$min_font, $mod_2*$mod_2 *$min_font);
}
其他阅读
- 使用 CSS 锁定实现灵活排版,由 Tim Brown 撰写
- 平衡之道:响应式显示文本,由 Richard Rutter 撰写
- 流体字体示例,由 Mike Riethmuller 撰写
非常棒的小技巧!浏览器支持情况如何?IE11+?
应该在 IE11 和 Edge 中正常工作
https://caniuse.cn/#feat=viewport-units
https://caniuse.cn/#feat=calc
如果我错了,请纠正我。
我认为,如果你为视窗单位和 calc 包含一个 polyfill,你就可以在 polyfill 支持的任何浏览器中使用它,对吧?对吧?
不要使用 polyfill。让旧版浏览器优雅降级。添加 polyfill 只会降低性能,尤其是在旧设备上。这种额外的大小细微差别并不值得。
与 CSS 变量结合使用
今天早上我正在研究如何将它整合到我的工作流程中,你这里漏掉了一个非常关键的东西。这种流体字体大小计算应该在一个媒体查询中,并设置最小和最大视窗。否则,它将继续超出最小值和最大值。查看原始文章:
https://madebymike.com.au/writing/fluid-type-calc-examples/
Sass mixin 包含了所有这些内容,超出了基本概念。
请告诉我我错了,但上面的例子在 Safari 中不起作用?
干杯
Thomas
我认为这与 Safari 中视窗单位的实时计算有关。例如,如果你刷新页面,它就正常了,只是在调整大小的时候不流畅。太可惜了。我认为这是一个临时错误。它仍然有用。
Safari(以及 IE11)的某些版本存在一个错误,这意味着它不会在调整大小的时候进行计算,但正如 Chris 所说,它应该在第一次加载时正确计算。
这涵盖了大多数情况。但我听说在计算结果的末尾添加 +100% 可以修复 Safari 中的调整大小错误。
尝试了 Chris 共享的 Sass Mixin 后,它完美运行,甚至在 Safari 中也能运行。
可能是 CodePen 中的问题吗?我的意思是所有共享的例子在 Safari 中都无法运行(可能是新的 IE?)。
只是想告诉你一下,谢谢你的分享。非常酷。
干杯
Thomas
哎呀,完全没有注意到你的评论,Mike。抱歉。
干杯
Thomas
我还注意到,在 Safari 中,calc 仅在页面重新加载时执行,但很明显,在父容器中将字体大小设置为任何 vw 大小都可以解决此问题,并且你可以拥有流体字体大小。
https://jsfiddle.net/hbyzLcj1/52/
@Konrad... 谢谢你的“在父级元素上使用 font-size: 1vw 的 hack”。在 2019 年,Safari 仍然没有像其他浏览器那样处理这个问题。
实际上,这也不起作用。它只是缩小了尺寸,没有最小/最大尺寸。
但我找到了一个针对 Safari 的修复/hack,它确实有效
在文本中添加
min-height: 0vw;
有人能告诉我它与 vw 有什么区别吗?
这种技巧确实使用了 vw。只是不是仅使用 vw,因为那样就无法控制最小值和最大值,也无法实现这里提到的其他技巧。
感谢你的解答。
我经常使用 vw,但在小型设备上,文本有时会变得太小。然后我会使用针对小型设备的媒体查询来增大字体大小。而使用这种技巧,你就无需使用媒体查询,对吧?
嘿,Chris,分享这些由 James Nowland 提供的示例非常值得:http://codepen.io/jnowland/pen/GWgbMP/ 他创建了一个非常棒的 mixin,有些人可能更喜欢这种语法。
感谢分享这个 Codepen,Mixin 很棒……除了几个问题。
行高包含不起作用。Chrome 称该属性值为无效值。我也尝试了 responsive-resize Mixin 和 responsive-type Mixin。两者对行高都不起作用……但对字体大小起作用。
很想使用这些 Mixin。
@include responsive-type('14px@400px', '50px@1900px');
@include responsive-type('1.2@400px', '1.05@1900px', line-height);
但是当我编译时,Sass 给出了错误:“index out of bounds for
nth($list, $n)
。似乎 Sass 有个奇怪的地方,你需要在只有一个项目的嵌套数组末尾添加一个额外的逗号。似乎无法弄清楚如何用这个特定的字符串分割来做到这一点。非常感谢任何帮助。responsive-resize Mixin 对字体大小非常有效!
我过去 2.5 年一直在做流体文本。
我在同一个 CSS 属性块中使用 vw 和 rem。
甚至使用它将整个 HTML 对象视为一个可缩放的大型设计。
Joe,你愿意一起讨论这个吗?我也在使用它来为页面上的大多数元素(除了排版)设置样式,以便获得整齐流畅的布局,我可以在哪里联系你?我有一些(可能还处于半成品状态)的 pens 和 gists,也许你喜欢看看?
今天我实际上给 Mike 发了一封邮件,概述了我对流体类型 Sass mixin 遇到的小问题,即当对多个区域/媒体查询使用它时,它确实会为同一个选择器生成多个值,请看这里 https://www.sassmeister.com/gist/0a451c254e43c07a7e487771d3590476 (如果 CSS 没有立即编译,请在 SCSS 中添加一个空格,然后再将其删除,SassMeister 将重新触发编译过程)。
我还没有读,poly fluid 帖子 https://css-tricks.org.cn/poly-fluid-sizing/ ,它刚到我的收件箱,我马上就去看看,也许解决方案就在那里,因为我认为这就是我想要的。
正如 Joe Hoeller 写的那样,不仅将它用于排版,还将其用于 dom 中的所有样式,从极端的 50px 宽度到 2500px 及以上,非常有趣,一旦你掌握了它,你就可以获得真正令人印象深刻且响应式的布局。
一个易于使用的
<a href="https://websemantics.uk/tools/responsive-font-calculator/">流体响应式字体大小计算器</a>
。以及一个
<a href="https://codepen.io/2kool2/pen/PKGrdj">乱七八糟的 Safari 大小调整修复</a>
。厚颜无耻的宣传!
流体响应式字体大小计算器
乱七八糟的 Safari 大小调整修复
@return $value / ($value * 0 + 1); 任何数字乘以 0 等于 0,而 0 + 1 始终等于 1。
@return $value / 1; 任何数字除以 1 等于该数字。
@return $value;
还是我漏掉了什么?
该函数的目的是从 $value 中去除单位(例如,“px”)。我相信 ($value * 0) 等于 $value 单位的 0(例如,“0px”)。然后加上 1 使其成为该单位的 1(例如,“1px”)。将 $value(例如,“20px”)除以其单位的 1(“1px”)将得到一个无单位的数字(例如,20),而 $value/1 只是 $value,带有单位。
calc([最小尺寸] + ([最大尺寸] – [最小尺寸]) * ((100vw – [最小视窗宽度]) / ([最大视窗宽度] – [最小视窗宽度])));
有人可以解释构建这个数学方程的逻辑吗?
我们如何为数学选择媒体查询范围?
我真的不明白这是什么?我认为你在向我们展示如何通过字体大小使文本扩展以占据其容器宽度。jquery fitText() 脚本没有这样做,它需要一个“神奇”的猜测系数,最终你需要像调整吉他一样对其进行微调——我永远不会擅长这种事,你知道吗。
在捣鼓了这个插件一段时间后,我写了一个简短的脚本,做了我认为 fitText 会做的事情:它调整文本大小以适应其父容器的宽度。我没有限制大小调整事件(或去抖或其他任何东西),它有很多问题,但它更符合我认为你建议 fitText 所做的事情。我在哪里迷路了?
太棒了,谢谢!
我想在带有 WordPress 的外部样式表中使用 calc 行。
我必须使用表达式 !important 来覆盖现有规则。
不幸的是,我无法弄清楚将 !important 放在哪里。
我尝试了以下方法,但 calc 行不起作用。
@media screen and (min-width: 320px) {
html {
font-size: calc(16px + 6 * ((100vw – 320px) / 680))!important;
}
}
@media screen and (min-width: 1000px) {
html {
font-size: 22px!important;
}
}
感谢您的帮助!
此致,
Michael
我刚刚发现了一个更短的 SASS 版本,不需要 mixin。我没有在变量中设置
px
。这样,我们可以在字体大小计算中需要时添加它。font-size: calc(#{$min_font * 1px} + #{$max_font - $min_font} * (100vw - #{$min_width * 1px}) / #{$max_width - $min_width});
好文章,非常有用。
不过,是否可以使用“rem”来表示尺寸?
我试过,计算有点“不对”。
我尝试在 6.4rem 和 3.2rem 之间进行调整,但无法超过“38.7968px”。还是我必须使用最大/最小宽度的“rem”等效值才能正确计算?
我修复了。最大/最小宽度也需要使用“rem”,只需省略单位。
这是一个很棒的解决方案!
虽然,我们对字体缩放有稍微不同的要求。
要求是:按比例缩小字体大小以适应视窗宽度,使其始终具有相同的纵横比,并且不会导致换行。但仅在给定的视窗内。并且仅使用最大字体大小和最小字体大小。
您的解决方案导致缩小速度比要求的慢,因为两个断点之间的两个字体大小之间的线性函数。
这是我针对我们的要求的方法:https://codepen.io/shooby83/pen/JQyRao
希望对某人有用。
干杯
@Matthias Schubert: 做得好,很棒的方法。
你好,Chris。很棒的代码。问题:当我使用这种方法时,我发现 Chrome 开发工具中的“从 body 继承”摘要显示了字体大小和带有删除线的计算,即使它似乎实际上使用了计算公式。你能解释一下为什么吗?谢谢!
一个非常有用的解决方案!
有没有办法使字体大小动态化,例如,如果我们从用户那里接收交互页面的字体大小?
嘿,哥们!
我必须说,我非常喜欢你的作品,以至于我在我的最新博客文章中链接了你。你可以在这里查看 https://pixelzui.com/components/typography。
干杯,
Salman Ramzan 工程师
附注:如果你分享它,它会让我很高兴。
“@if $u1 == $u2 and $u1 == $u3 and $u1 == $u4 {”
为什么所有单位都需要相等?
我可以看到这对于文本密集型网站(如博客)非常有用,但你会在 Web/移动应用程序中使用相同的方法吗?在我看来,在这些情况下,它可能过时了,甚至会破坏 UI。
有什么想法吗?
有人尝试过使用自定义属性和相对字体单位 (em/rem) 吗?
非常棒的指南,非常感谢!我刚在“safari”方面遇到了一些问题,因为我无法“动态”调整字体大小。调整大小仅在重新加载页面后出现。
然而,这个 codepen 通过在类中添加一个“min-height: 0vw”帮助我很多。对我有用。
这是一个很棒的解决方案!
为什么不使用:calc(14px + (12) * ((100vw – 300px) / (1600 – 300)));
在你的例子中
calc(14px + (26 – 14) * ((100vw – 300px) / (1600 – 300)));
这太棒了!超级酷。Bootstrap 应该实现这个功能!
我相信这是可能的,但可以扩展到其他属性,例如特定 div 的宽度和高度吗?
哇,这听起来像是容器查询的一个很好的用例!希望我们很快就能得到这些。
Bootstrap 去年没有整合一个叫做 RFS 的流体/响应式类型 mixin 吗?作者在一段时间前写过它,并提到它计划在 Bootstrap 5 中使用。
我刚了解了新的 CSS 函数
min()
、max()
和clamp()
(当我写这篇文章时,clamp()
在 Safari 中不受支持,但其他两个可以,并且可以组合起来像clamp()
一样工作)。https://mdn.org.cn/en-US/docs/Web/CSS/min
看起来它实现了像这篇博文建议的东西,只是代码更简洁!
嗨,Josh,
虽然 clamp 和 min-max 方法不像媒体查询版本那样支持广泛,但只要你使用 Safari 修复 min-height: 0vw;,所有这些方法都可以在当前的 Safari 中工作。
尝试一下此页面上的测试窗口:https://websemantics.uk/tools/responsive-font-calculator/
我遇到的最好的代码之一。适用于边距、填充......总之它就是好用,太棒了!!非常感谢你。
非常感谢你的这篇文章!再也不用为每个标题创建响应式样式而发愁了。
非常棒的技巧!
尽管如此,数学有点复杂。
你认为
clamp()
会是实现流体排版的更简洁的方法吗?再说一次,真的很棒的技巧!
是的!
clamp()
绝对提供了一种更简洁的方法,因为它将最小值和最大值直接包含在内。Chris 在另一篇文章中讲解了这一点。发现非常有用!感谢 Graham 先生。