轻松响应的排版

2025-06-10

轻松响应的排版

印刷页面上的排版设计原则并不总是适用于数字屏幕。在网页开发中,我们无需担心最大化每页字数或最小化总页数。印刷页面的经济性在网页上并不重要。对于数字开发者和设计师来说,可能性几乎是无穷无尽的。

问题就在这里。我们拥有的广阔可能性也同样适用于我们的读者(就像现在的你一样),他们可以在智能手机、平板电脑、笔记本电脑或超宽 8K 显示屏上垂直阅读文本。印刷页面总是有明确的定义(毕竟文本是排版的),而数字视口则是一个不断变形的幽灵,永远萦绕在我们的设计中。

如何确保您的文本在任何视口下都读起来舒适?

值得庆幸的是,有一些解决方案可以根据视口大小的变化来缩放设计的字体大小(我在此要感谢Geoff GrahamMichael Riethmuller就此主题发表的帖子)。一般来说(这或许与直觉相反),字体大小应该随着视口的增大而增大,因为大屏幕上的空间更大,而且与手机相比,用户可能坐得离视口更远。

下面我提供了三种解决方案。虽然每种方案都能实现根据视口宽度增加字体大小的目标,但我推荐第三种方案,因为它是最好的(这个网站也实现了它):

  1. 响应式排版(最容易启动和运行)
  2. 流体排版(实现连续的字体大小缩放)
  3. 通过 SASS mixin 实现流体排版(流体缩放的最简单实现)
  4. 通过 JavaScript 实现流体排版(无障碍友好解决方案)

响应式排版

响应式排版基于媒体查询定义不同的字体大小,是最容易实现的解决方案,并且拥有最广泛的浏览器支持。首先,通过 CSS 在 HTML 选择器中定义所需的最小字体大小(建议 16px)。然后,针对每个媒体查询断点增加字体大小。请参阅下面的示例以了解详情。

/* Define minimum font size */
html {
 font-size:16px;
}

/* Define breakpoints and font sizes */
@media (min-width:640px) and (max-width:1023px) {
 html {
  font-size: 17px
 }
}

@media (min-width:1024px) and (max-width:1279px) {
 html {
  font-size: 18px
 }
}

/* Define max font size and viewport */
@media (min-width:1280px) {
 html {
  font-size: 19px
 }
}
Enter fullscreen mode Exit fullscreen mode

通过改变根字体大小,我们可以使用 rem CSS 单位来改变其他排版元素的大小。例如,对于大小为 2.5rem 的 H1 标签,根据上述 CSS 规则,它将具有以下大小。

视口宽度 < 640 像素 > 639像素 > 1023像素 > 1279像素
基本字体大小 16像素 17像素 18像素 19像素
H1字体大小 40像素 42.5像素 45像素 47.5像素

流体排版

流体排版扩展了响应式排版,通过实现一个公式来根据视口大小缩放文本。流体排版并非像上图所示那样根据媒体查询断点分步更改字体大小,而是根据视口宽度连续设置字体大小。

为了实现此结果,需要在 CSS 中定义一个能够动态更新 font-size 属性的公式。该公式的关键是 CSS 单位“vw”,即视口宽度。

公式如下:min font size + (max font size - min font size) * (100vw - min vw) / (max vw - min vw)

例如,给定以下参数:最小字体大小为 16px,最大字体大小为 23px,最小 vw 为 640px,最大 vw 为 1440px;该公式将产生以下结果:

视口宽度 基本字体大小
< 640像素 16像素
700像素 16.5167像素
750像素 16.95像素
1200像素 20.9像素
> 1440像素 23像素

要在 CSS 中实现公式,您需要编写以下规则:

/* Define minimum font size */
html {
    font-size: 16px;
}

/* Fluid typography formula */
@media (min-width: 640px) and (max-width: 1439px) {
    font-size: calc(16px + (23 - 16) * (100vw - 640px) / (1439 - 640));
}

/* Define max font size */
@media (min-width: 1440px) {
    font-size: 23px;
}
Enter fullscreen mode Exit fullscreen mode

通过 SASS Mixin 实现流体排版

如果您使用的是 SASS/SCSS,则可以使用 mixin 实现上述解决方案。使用 mixin 的优势在于能够轻松更新变量并自动生成媒体查询断点。mixin 及其用法如下所示。

/* Define the mixin */
@mixin fluid-typography($minFont,$maxFont,$minBreakpoint,$maxBreakpoint) {

  /* Define variable for media query */
  $maxLessOne: $maxBreakpoint - 1;

  /* Define variable for fallback */
  $avg: ($maxFont + $minFont) / 2;

  /* Base font size */
  font-size: #{$minFont}px;

  @media (min-width: #{$minBreakpoint}px) and (max-width: #{$maxLessOne}px) {

    /* Adds a fallback for unsupported browsers */
    font-size: #{$avg}px;

    /* The fluid typography magic 🌟 */
    font-size: calc(#{$minFont}px + (#{$maxFont} - #{$minFont}) * (100vw - #{$minBreakpoint}px) / (#{$maxBreakpoint} - #{$minBreakpoint}))
  }

  @media (min-width: #{$maxBreakpoint}px) {
    font-size: #{$maxFont}px;
  }
}

/* Generate the CSS */
html {

  /* Just add your arguments */
  @include fluid-typography(16,25,300,1500);
}
Enter fullscreen mode Exit fullscreen mode

看看实际效果。记得调整浏览器大小来查看变化 👉

通过 JavaScript 实现流体排版

先前的解决方案在可访问性方面存在局限性,因为以像素为单位设置字体大小会覆盖用户定义的值。例如,如果用户在浏览器中将字体大小设置为 22px,则上述解决方案会将该值覆盖为 16px,这是不可取的。

不幸的是,CSS 中的 calc 机制不允许使用基于 rem 的解决方案。您可以使用响应式解决方案(如上例所示),但这样会失去流畅性。不过,使用 JavaScript,您可以保留字体大小的流畅性、用户自定义的偏好设置以及设计本身的某些方面。

下面定义的构造函数通过接受四个参数来工作,与上面的相同:。然后,如果用户没有设置字体大小首选项,它会在 DOM 上实现这些大小。如果用户设置了首选项,那么该函数会实现您在最小字体大小和最大字体大小之间定义的相同比率。例如,如果您将最小字体大小定义为 16px,将最大字体大小定义为 23px,那么这代表增加了 43.75%。如果用户定义的最小字体大小为 22px,那么该函数将根据用户提供的最小值和 43.75% 的增幅来计算页面的 rem。对于 22px,这意味着最大值为 31.625px。函数如下。

class FluidTypography {
  constructor(minVW, maxVW, minFontSize, maxFontSize) {
    this.minVW = minVW;
    this.maxVW = maxVW;
    this.minFontSize = minFontSize;
    this.maxFontSize = maxFontSize;
    this.maxRem = this.computeRem().maxRem;
    this.minRem = this.computeRem().minRem;
  }

  // Compute the maxRem based on arguments and user's browser preferences
  computeRem() {
    const body = document.documentElement;
    const properties = window.getComputedStyle(body);
    const baseFontSize = properties.fontSize.replace(/px/, '');
    // Gets the max font size of either the browser or the dev
    const max = Math.max(this.minFontSize, baseFontSize);
    const relativeMax = (this.maxFontSize * max) / this.minFontSize;
    const maxRem = relativeMax / baseFontSize;
    const minRem = max / baseFontSize;
    return { maxRem, minRem };
  }

  // Calculate font size based on arguments and user's browser preferences
  fontSize() {
    const width = document.documentElement.offsetWidth;
    let rem = this.minRem;

    if (width > this.minVW && width < this.maxVW) {
      rem =
        this.minRem +
        ((this.maxRem - this.minRem) * (width - this.minVW)) /
          (this.maxVW - this.minVW);
    }

    if (width > this.maxVW) {
      rem = this.maxRem;
    }

    document.documentElement.style = `font-size: ${rem}rem`;
  }

  resizeHandler() {
    this.fontSize();
    window.addEventListener('resize', this.fontSize.bind(this));
  }
}

new FluidTypography(640, 1280, 17.5, 22).resizeHandler();
Enter fullscreen mode Exit fullscreen mode

👉 看看实际效果。记得调整浏览器大小来查看变化。

这篇文章最初出现在我的博客上

鏂囩珷鏉ユ簮锛�https://dev.to/royalfi/easy-responsive-typography-507a
PREV
使用 TypeScript 设置 Node Express API(2021)
NEXT
Vue.js 是 omakase