使用 Mixin 简化响应式字体大小的计算

Avatar of Martijn Cuppens
Martijn Cuppens 发布

DigitalOcean 为您旅程的每个阶段提供云产品。立即开始使用 200 美元的免费额度!

响应式字体大小 (RFS) 是一种引擎,它自动计算并更新元素的font-size属性,使其基于浏览器视口的尺寸进行调整。

如果您觉得这听起来很熟悉,那是因为有很多工具提供了各种方法来实现流体排版。事实上,Chris 之前整理过一些这样的方法。您可以查看一下,因为了解现有方法和最适合特定任务的方法总是好的。

RFS 的不同之处在于,它使编写流体字体的代码感觉更像是在您现有的样式表中直接编写原生 CSS(或更准确地说,像使用预处理器一样编写)——而无需处理和管理大量的媒体查询。它甚至与 Sass、Less、Stylus 和 PostCSS 兼容,因此可以插入几乎任何技术栈中。

它究竟有多么集成?好吧,让我们比较一下使用calc()函数的流体排版代码片段

html {
  font-size: 16px;
}

@media screen and (min-width: 320px) {
  html {
    font-size: calc(16px + 6 * ((100vw - 320px) / 680));
  }
}

@media screen and (min-width: 1200px) {
  html {
    font-size: 22px;
  }
}

…以及如何在 Sass 中使用 RFS 实现类似的效果

.title {
  @include font-size(4rem);
}

编译结果为

.title {
  font-size: 4rem;
}

@media (max-width: 1200px) {
  .title {
    font-size: calc(1.525rem + 3.3vw);
  }
}

好奇它是如何工作的?让我们先了解一下,然后再深入探讨如何在项目中设置它。

自动重新缩放背后的原理

以下图表可以帮助您更好地理解 RFS 如何重新缩放字体大小

每种颜色代表一个传递给 RFS 提供的font-size() mixin 的字体大小。图表的 y 轴表示字体大小(单位为px),x 轴表示视口的宽度(同样,单位为px)。

让我们关注绿色线条,它是通过将 mixin 应用于元素生成的

.title {
  @include font-size(40);
}

在本例中,将40px的字体大小传递给 mixin。该值用作元素的最大字体大小,当视口宽度为1200px或更宽时达到该大小,之后保持该大小。

相反,字体大小将降至最低20px,永远不会低于此值。

其他情况呢?好吧,这就是字体大小值自动计算的地方,它使用后台函数根据视口的当前宽度确定数字。

RFS 也有一些固定的观点,它将自己限制在20px及以上的字体大小。其理由是,较小的文本(例如普通正文文本)通常不需要太大程度的灵活调整,并且比较大的内容(例如标题等)更容易管理。这与FitText非常一致,FitText 也更适合用于大型文本(尽管它不会阻止您在其他地方使用它)。

如果您喜欢查看底层代码,则可以在RFS GitHub 仓库中查看每个预处理器的 mixin。例如,这里有一个指向 SCSS 版本的直接链接。里面有很多数学计算!

请注意,每个字体大小都是由remvw单位的组合生成的,但为了便于理解,它们在图表中映射到px。换句话说,它确实去除了所有繁琐的数学计算。

所有内容都可配置

说真的。每一个。单个。东西。

例如,您可能想知道为什么在前面的示例中,字体大小在1200px及更宽的视口中达到上限。这可以更改,以及许多其他内容,包括

  • 基本字体大小:最低的字体大小值。
  • 字体大小单位:输出值中使用的单位类型(pxem)。
  • 断点:视口最大宽度,在此宽度下元素的字体大小达到其最大值。
  • 断点单位:mixin 生成的媒体查询中使用的单位(pxemrem)。
  • 因子:这充当一种音量控制,通知 mixin 从最大视口宽度一直到最小宽度计算字体大小时的积极程度。
  • Rem 值:这定义了1rem以像素 (px) 为单位的值。
  • 二维:一项功能,它检测视口中最小的边并使用它来计算字体大小值。这在您希望在设备从纵向旋转到横向时防止字体变小的情况下非常有用。
  • 类:提供可添加到 HTML 中元素的类名,以启用或禁用流体大小调整。

所以,是的。这里有很多选项和灵活性。需要了解的重要一点是,所有这些选项都是可以在样式表中定义的变量。

尽管如此,默认设置非常安全,并且可以防止许多较长的单词从视口中截断。对于某些语言(如德语或荷兰语)尤其如此,这些语言包含许多复合词。

在项目中使用 RFS

让我们直接深入代码。查看每个预处理器的代码将非常繁琐,因此我将使用.scss语法解释所有内容。但是,如果您更喜欢其他方法,则可以在 GitHub 仓库的使用部分中查看其他语言的示例。

首先,需要在项目中安装 RFS。它可以在 npm 和 Yarn 中获得

## npm
npm install rfs

## Yarn
yarn add rfs

## Bower is available, but has been deprecated
bower install rfs --save

然后,必须确保 mixin 与其他样式一起导入,无论您在哪里导入其他部分。

@import "~rfs/scss";

现在,我们可以开始使用 mixin 了!

.title {
  color: #333;
  @include font-size(64px);
}

.subtitle {
  color: #666;
  @include font-size(48px);
}

.paragraph {
  @include font-size(16px);
}

我以px为单位传递了值,但也支持rem单位。如果传递的值没有单位,则默认使用px。字体大小始终以rem(与vw结合使用)呈现,以确保当浏览器中的默认字体大小增加时,字体大小也会增加(这是一种视力障碍者经常使用的功能)。

输出结果为

.title {
  color: #333;
  font-size: 4rem;
}

@media (max-width: 1200px) {
  .title {
    font-size: calc(1.525rem + 3.3vw);
  }
}

.subtitle {
  color: #666;
  font-size: 3rem;
}

@media (max-width: 1200px) {
  .subtitle {
    font-size: calc(1.425rem + 2.1vw);
  }
}

.paragraph {
  font-size: 1rem;
}

请注意,mixin 为font-size(),但 RFS 还允许您以另外两种方式使用它

.title {
  @include font-size(4rem);
  // or
  @include responsive-font-size(64px);
  // or
  @include rfs(64);
}

RFS 内置于 Bootstrap

这里有一个小故事。

有一天,我突发奇想,想要将 RFS 集成到Bootstrap中。实际上,我当时并没有使用 Bootstrap,但我相信它是一个 Bootstrap 绝对可以使用的功能。我提交了一个拉取请求,并等待了几个月看看会发生什么。

在此期间,我对 Bootstrap 越来越感兴趣,并且版本 4 刚刚发布。慢慢地,我越来越多地参与到项目的贡献中,当我发现它背后的社区时,一个全新的世界向我敞开了。在Hacktoberfest(是的,我得到了我的 T 恤)2018 年 10 月,我被mdo邀请加入 Bootstrap 团队。

我相信为开源项目做出贡献是一件非常有趣且有益的事情。如果您有兴趣成为贡献者,Andrés Galante 撰写了一篇关于此主题的精彩文章

从那时起,RFS 已经成为Bootstrap 团队的一个项目,并且在今年 2 月 11 日,我们发布了包含 RFS 的 Bootstrap 4.3。它目前默认情况下处于禁用状态,但可以通过设置 Sass 变量$enable-responsive-font-sizes: true轻松启用。

但不要误会:RFS 仍然可以独立使用。只是很酷的是它内置于一个广泛使用的框架中。

哦,对了,我们来谈谈浏览器支持

支持相当不错!事实上,RFS 可以工作在任何支持媒体查询视口单位的地方。RFS 将为旧版浏览器(如 Internet Explorer 8)设置字体大小,但不会有流畅的效果。换句话说,应该可以安全地用于生产环境!

RFS 的未来发展方向

Bootstrap 的下一个主要版本是 5,我们计划默认启用 RFS。目前我们没有计划更改其工作方式。很有可能,$enable-responsive-font-sizes 变量将简单地设置为 true,仅此而已。

将来,我希望能够使用 min() 函数,因为它可以生成更少的 CSS 并简化很多事情。浏览器似乎还没有很好地支持此函数,但如果您对此功能感兴趣,可以关注此 GitHub 问题 中的进展。

还有什么吗?没有了,但我可以留给你们一首小歌和小舞:Na na na na, na na na na, hey hey hey 再见