MIT License

技术解读

以下内容由 GitRead 中文社区 编辑团队基于项目 README 与官方资料整理, 结合中文开发者的常见使用场景补充技术选型建议。具体以项目官方文档为准。

Typography.js 深度剖析:把排版规则变成一行配置

项目背景与痛点

Web 排版长期处在一个尴尬的位置:它足够重要,却又足够枯燥。一个页面里,h1 到 h6 的字号、行高、上下间距、列表缩进、引用块边距、代码块内边距——每一条都要手写,而且彼此耦合。你改了基础字号,整页的垂直韵律就断了,标题和正文的基线对不齐,段落间距看起来忽大忽小。

2015 年前后,Ruby 生态里的 Compass 提供了一套 vertical-rhythm 混入,Sass 用户可以靠它维持基线网格。但 Compass 已停止维护,且与前端工程化的 JS 工具链格格不入。Kyle Mathews 做的事情很直接:把 Compass 那套"垂直韵律 + 模块化比例"的排版方法论,整体移植到 JavaScript 里,抽象成一个只吃配置、吐 CSS 的引擎。这就是 typography.js。

它要解决的核心问题只有一个:让排版从"逐条手写 CSS"变成"声明一个主题"。你只需要告诉它基础字号和缩放比例,剩下的字号阶梯与间距系统由算法推导。

核心技术揭秘

Typography.js 的本质不是一个组件库,而是一个样式编译器。它的数据流非常清晰:主题配置进入,经过韵律计算与比例缩放,最终输出一段可直接注入的 CSS 字符串。

graph TD A[用户配置 theme 对象] --> B[Typography 构造函数] B --> C[合并默认参数与主题预设] C --> D[计算垂直韵律基准单元] D --> E[按模块化比例推导 h1-h6 字号] E --> F[行高与间距对齐到韵律整数倍] F --> G[遍历各 HTML 元素生成 CSS 规则] G --> H{"是否提供 overrideStyles?"} H -->|"是"| I[追加自定义覆盖规则] H -->|"否"| J[直接输出样式表] I --> J J --> K[gatsby-plugin-typography 注入 head] J --> L[手动注入 style 标签]

关键实现有三层。

第一层是韵律单元(rhythm unit)。 它被定义为 baseLineHeight / baseFontSize,默认是 1.45 / 1rem 量级。整个样式表的 margin、padding、line-height 都必须是这个单元的整数倍,这是"垂直韵律"能够成立的前提——只有所有间距共享同一个公约数,跨元素的基线才可能对齐。

第二层是模块化比例(modular scale)。 标题字号不做线性递增,而是按一个比例因子(默认 ratio: 2,也可设为 1.618 黄金比例)做指数缩放:fontSize = base * ratio^n。这让字号阶梯在视觉上保持一致的"跳跃感",而不是靠设计师手动试出来的数值。

第三层是取整对齐。 拿到字号后不能直接用,因为 1.618rem 乘出来的行高大概率不是韵律单元的整数倍。引擎会把行高向上取整到最接近的韵律倍数,再据此反推 margin。这一步是整套算法里最容易出 bug 的地方:取整过度会导致大标题下留白过多,取整不足则韵律断裂。Typography.js 选择"宁可多留白,不可断韵律",这也解释了为什么它生成的标题下方间距普遍偏大。

工程上,它依赖 lodash 做配置合并,用 modularscale 包处理比例计算,用 compass-vertical-rhythm 承担韵律运算。Typography 类对外暴露 createStyles() 方法返回 CSS 字符串,并通过 overrideThemeStyles、overrideStyles 两个钩子留出逃生舱——前者接收主题上下文,可以按元素条件化地改样式;后者是纯字符串层面的最后兜底。

功能亮点与差异

对比同类方案,它的独特性在于维度的收窄。Bootstrap 是组件型框架,Tailwind 是原子化工具集,两者都覆盖布局、颜色、阴影、交互态;Typography.js 只做一件事——文字排版。这种收窄带来了两个直接好处:一是产物极小,一段 CSS 而已,没有运行时、没有 DOM 结构约束;二是可替换性极强,你完全可以在 Tailwind 项目里单独用它接管排版层。

第二个亮点是主题即 npm 包。typography-theme-github、typography-theme-wordpress-2016、typography-theme-lawton 这些包,本质上是把成熟产品的排版规格逆向提炼成配置对象。这形成了一个可复用的"排版配方"生态,社区可以互相 fork 微调。

第三个亮点是与 Gatsby 的原生耦合。gatsby-plugin-typography 把生成的 CSS 在构建期注入,避免了 FOUC,也让排版配置成为 gatsby-config.js 里的一等公民。考虑到作者本人就是 Gatsby 的创造者,这条集成路径的完成度明显高于其他框架。

应用场景与落地建议

它最适合内容密集型站点:技术博客、文档站、长文阅读类产品。这类场景对排版精度敏感,而组件复杂度低,正好落在它的甜区。

生产环境落地需要注意几点。其一,主题配置与设计系统要对齐:如果你已经有设计规范,别直接套用现成主题,把 baseFontSize、ratio、scale 三个参数调成与规范一致,再去改细节。其二,CSS 优先级问题:生成的规则是元素选择器级别,很容易被组件库的类选择器覆盖,必要时用 overrideStyles 提升选择器权重,而不是堆 !important。其三,响应式断层:它是静态生成,不会随视口变化重算字号,移动端通常需要额外配置一套 mediaQuery 内的覆盖规则。其四,这个项目近年维护频率很低,依赖版本偏旧,接入前建议锁版本并做一次完整的构建验证。

综合评价

优点:概念极简但完备,"一个配置对象搞定全站排版"这件事至今没有更好的替代品;算法层面的韵律对齐是真正解决痛点的工程实现,不是噱头;主题包生态降低了审美门槛;产物是纯 CSS,零运行时开销。

缺点:维护活跃度低,生态基本停留在 2019 年前后的状态;配置对象字段繁多且文档粒度粗,第一次调参容易陷入试错;静态生成意味着响应式排版要手动补;与 CSS-in-JS、Tailwind 这类现代方案缺少官方桥接。

一句话总结:它是一把做工精良但久未上油的专用工具——如果你的项目核心价值在"读",它依然值得一用;如果你追求的是全链路的设计系统一致性,它更像一个排版层的参考实现,而非最终答案。

关于

GitHub 原始描述(英文)

A powerful toolkit for building websites with beautiful design

描述取自 GitHub 官方 API,保持仓库作者书写的原文。

简要分析

热度分
4238
价值分
2367
活跃状态
活跃

语言占比

CoffeeScript
JavaScript

Release

README

Typography.js Build Status Coverage Status

A powerful toolkit for building websites with beautiful design.

Install

npm install typography

Demo/playground

https://kyleamathews.github.io/typography.js

Why

The goal of Typography.js is to provide a high-level elegant API for expressing typographic design intent.

Typography is a complex system of interrelated styles. 100s of style declarations on dozens of elements must be in harmonious order. Trying one design change can mean making dozens of tedious recalculations and CSS value changes. Creating new Typography themes with CSS feels hard.

Typography.js provides a vastly simpler way to define and explore typography designs.

You provide configuration to the Typography.js JS api and it uses its Typography engine to generate CSS for block and inline elements.

Typography.js makes it easy to create designs that are unique, personal, and custom to your project.

Themes & Plugins

  • themes: Typography.js themes are simple Javascript objects. As such they’re easy to share across projects or even open source and share via NPM.
  • plugins: Plugins are functions that extend or modify the core Typography engine. They can change how headers are styled or add specialized styles e.g. for code or tables.

Sites that use Typography.js

Javascript usage

import Typography from 'typography'

const typography = new Typography({
  baseFontSize: '18px',
  baseLineHeight: 1.45,
  headerFontFamily: ['Avenir Next', 'Helvetica Neue', 'Segoe UI', 'Helvetica', 'Arial', 'sans-serif'],
  bodyFontFamily: ['Georgia', 'serif'],
  // See below for the full list of options.
})

// Output CSS as string.
typography.toString()

// Or insert styles directly into the <head> (works well for client-only
// JS web apps.)
typography.injectStyles()

Themes

We maintain 30 (and counting) themes that are ready to use on your next project. These are each published as separate NPM packages. Explore themes at http://kyleamathews.github.io/typography.js.

Using themes

Here’s an example of how to use the Funston theme.

  1. First save the package to your project npm install --save typography-theme-funston
  2. Then import and pass into Typography when initializing.
import Typography from 'typography'
import funstonTheme from 'typography-theme-funston'

const typography = new Typography(funstonTheme)

Customizing themes

Themes are just javascript objects so it’s easy to modify them as needed. For example, if you’re using the Funston theme but want to increase the base font size slightly:

import Typography from 'typography'
import funstonTheme from 'typography-theme-funston'
funstonTheme.baseFontSize = '22px' // was 20px.

const typography = new Typography(funstonTheme)

Or you can use the imperative API overrideThemeStyles to directly set/override styles on a theme:

import Typography from 'typography'
import funstonTheme from 'typography-theme-funston'
funstonTheme.overrideThemeStyles = ({ rhythm }, options) => ({
  'h2,h3': {
    marginBottom: rhythm(1/2),
    marginTop: rhythm(2),
  }
})

const typography = new Typography(funstonTheme)

Published Typography.js Themes

Plugins

Plugins are functions that extend or modify the core typography engine. they can change how headers are styled or add specialized styles e.g. for code or tables. Currently there’s one plugin available, typography-plugin-code.

To use the Code plugin, first install using NPM.

npm install --save typography-plugin-code

Then add to your theme before creating a new typography object.

import Typography from 'typography'
import CodePlugin from 'typography-plugin-code'
import sternGroveTheme from 'typography-theme-stern-grove'

sternGroveTheme.plugins = [
  new CodePlugin(),
]

const typography = new Typography(sternGroveTheme)

React.js helper components.

Typography.js includes two helper components for your React.js projects, TypographyStyle and GoogleFont. These are ideal for server-rendering.

  • TypographyStyle creates a style element and inserts the generated CSS for your theme.
  • GoogleFont creates the link element to include the Google Fonts & weights specified in your theme.

To use, first install the package npm install --save react-typography then import them into your html.js file.

import { TypographyStyle, GoogleFont } from 'react-typography'
// Best practice is to have a typography module
// where you define your theme.
import typography from 'utils/typography'

// Inside your React.js HTML component.
<html>
  <head>
    <TypographyStyle typography={typography} />
    <GoogleFont typography={typography} />
  </head>
  <body>
    // stuff
  </body>
</html>

Using with create-react-app

If you use the default create-react-app template, the above React.js solution will not work, and the typography.injectStyles() solution will not enable Google Fonts… A workaround is to install typography-inject-fonts and do

import Typography from 'typography'
import funstonTheme from 'typography-theme-funston'
import injectFonts from 'typography-inject-fonts'

const typography = new Typography(funstonTheme)
typography.injectStyles()
injectFonts(typography)

API

Configuration

When creating a new instance of Typography, you can pass in a configuration object. All configuration keys are optional.

  • title: The theme title.
  • baseFontSize: The base font size in pixels, defaults to 16px.
  • baseLineHeight: The base line height using the css unitless number, defaults to 1.45.
  • scaleRatio: The “scale ratio” for the theme. This value is the ratio between the h1 font size and the baseFontSize. So if the scale ratio is 2 and the baseFontSize is 16px then the h1 font size is 32px.
{
  scaleRatio: 2,
}
  • googleFonts: An array specifying Google Fonts for this project.
googleFonts: [
  {
    name: 'Montserrat',
    styles: [
      '700',
    ],
  },
  {
    name: 'Merriweather',
    styles: [
      '400',
      '400i',
      '700',
      '700i',
    ],
  },
],
  • headerFontFamily: An array of strings specifying the font family stack for headers e.g. ['Helvetica', 'sans-serif']. Defaults to a system UI font stack.
  • bodyFontFamily: An array of strings specifying the font family stack for the body, defaults to ['georgia', 'serif'].
  • headerColor: A css color string to be set on headers. Defaults to inherit.
  • bodyColor: A css color string to be set for body text. Defaults to hsl(0,0%,0%,0.8).
  • headerWeight: Specify the font weight for headers. Defaults to bold.
  • bodyWeight: Specify the font weight for body text. Defaults to normal.
  • boldWeight: Specify the font weight for “bold” (b, strong, dt, th) elements. Defaults to bold.
  • blockMarginBottom: Specify the default margin-bottom for block elements. Defaults to one “rhythm unit” (i.e. the height of the base line height).
  • includeNormalize: Include normalize.css. Normalize.css is an excellent project which works to normalize the base browser CSS across browsers and serves as an excellent foundation for Typography.js. We include normalize.CSS by default but if you’re already including it elsewhere in your project, you can disable including it here by passing false.
  • overrideStyles: Imperative API for directly adding to or overriding auto-generated styles. It’s called with a Vertical Rhythm object, the options object, and the algorithmically generated styles.
overrideStyles: ({ adjustFontSizeTo, rhythm }, options, styles) => ({
  h1: {
    fontFamily: ['Montserrat', 'sans-serif'].join(','),
  },
  blockquote: {
    ...adjustFontSizeTo('19px'),
    color: gray(41),
    fontStyle: 'italic',
    paddingLeft: rhythm(13/16),
    marginLeft: rhythm(-1),
    borderLeft: `${rhythm(3/16)} solid ${gray(10)}`,
  },
  'blockquote > :last-child': {
    marginBottom: 0,
  },
})
  • overrideThemeStyles: This has the same function signature as overrideStyles but should be used in place of overrideStyles when using a 3rd-party theme so as to not delete the theme’s own overrideStyles function.
overrideThemeStyles: ({ rhythm }, options, styles) => ({
  'h2,h3': {
    marginBottom: rhythm(1/2),
    marginTop: rhythm(2),
  }
})

Developing Typography.js

Typography.js is a monorepo facilitated by Lerna.

TODO: document constants + compass-vertical-rhythm + using typgraphy.js for inline styles.

=======

Backers

Support us with a monthly donation and help us continue our activities. [Become a backer]

Sponsors

Become a sponsor and get your logo on our README on Github with a link to your site. [Become a sponsor]

评论

暂无评论