文字排版与字体
字体管理和高级文本渲染
字体
imgrender 预设了常用字体,也支持在请求 API 时自定义字体。
系统预设字体
imgrender 内预设了以下字体,这些字体可免费商用。
| Font Family | General Font Family | Supported Font Weight | Supported Font Style |
|---|---|---|---|
| AlibabaPuHuiTi | sans-serif | 100 300 400 500 700 900 | normal |
| Alibaba Sans KR | sans-serif | 100 300 400 500 700 900 | normal |
| Source Han Serif CN | serif | 200 300 400 500 600 700 900 | normal |
| Source Han Serif JP | serif | 200 300 400 500 600 700 900 | normal |
| Source Han Serif KR | serif | 200 300 400 500 600 700 900 | normal |
| Source Han Sans CN | sans-serif | 100 300 350 400 500 700 900 | normal |
| Source Han Sans TW | sans-serif | 100 300 350 400 500 700 900 | normal |
| Source Han Sans JP | sans-serif | 100 300 350 400 500 700 900 | normal |
| Source Han Sans KR | sans-serif | 100 300 350 400 500 700 900 | normal |
| Geist | sans-serif | 100 200 300 400 500 600 700 800 900 | normal oblique |
| Geist Mono | monospace | 100 200 300 400 500 600 700 800 900 | normal |
| Twemoji | emoji | 不适用 | 不适用 |
关于字重和字体样式
字重说明:
100- Thin(极细)200- ExtraLight(特细)300- Light(细)400- Regular(常规)500- Medium(中等)600- SemiBold(半粗)700- Bold(粗)800- ExtraBold(特粗)900- Black/Heavy(黑体/特粗)
关于斜体:
- 中日韩(CJK)字体(如思源宋体、思源黑体、阿里巴巴普惠体)通常不包含真正的斜体(italic)字形
- Geist 字体的
oblique样式是通过机械倾斜正体字实现的伪斜体 - 如需中文斜体效果,可使用 CSS 的
transform: skewX()或font-style: oblique实现
使用字体
使用通用字体名:
<div style={{ fontFamily: 'sans-serif' }}>Hello imgrender</div>会使用 sans-serif 字体。由于存在多个 sans-serif 字体,具体使用到的字体遵循字体回退机制。
<div style={{ fontFamily: 'serif' }}>Hello imgrender</div>会使用 serif 字体。由于存在多个 serif 字体,具体使用到的字体遵循字体回退机制。
<div tw="font-sans">Hello imgrender</div>会使用 sans-serif 字体。由于存在多个 sans-serif 字体,具体使用到的字体遵循字体回退机制。
<div tw="font-serif">Hello imgrender</div>会使用 serif 字体。由于存在多个 serif 字体,具体使用到的字体遵循字体回退机制。
- 请参考 TailwindCSS - font-family 文档获取更多有关字体的设置方法。
使用指定字体:
<div style={{ fontFamily: 'Source Han Serif CN' }}>Hello imgrender</div>指定使用 Source Han Serif CN 字体。
<div tw="font-[Source_Han_Serif_CN]">Hello imgrender</div>指定使用 Source Han Serif CN 字体。
- 请参考 TailwindCSS - font-family 文档获取更多有关字体的设置方法。
TailwindCSS 对 Font Family 中空格的特殊处理
TailwindCSS 中,空格需要使用下划线 _ 代替。
例如,指定使用 Source Han Serif CN 字体,应使用 font-[Source_Han_Serif_CN],而不是 font-[Source Han Serif CN]。
字体回退机制
字体回退(Font Fallback)机制用于在首选字体不可用或不包含所需字符时,自动选择替代字体。imgrender 根据以下规则处理字体回退:
未指定字体时的回退
当没有明确指定 font-family 时,imgrender 会按照系统预设字体表格的顺序依次尝试,直到找到能够渲染当前字符的字体:
// 未指定 font-family
<div>Hello 世界 🎉</div>渲染过程:
Hello- 尝试 AlibabaPuHuiTi,包含拉丁字母,直接渲染世界- AlibabaPuHuiTi 包含中文字符,直接渲染🎉- AlibabaPuHuiTi 不包含 emoji,按表格顺序查找,最终由 Twemoji 渲染
完整回退顺序(按表格从上到下):
AlibabaPuHuiTi → Alibaba Sans KR → Source Han Serif CN → Source Han Serif JP →
Source Han Serif KR → Source Han Sans CN → Source Han Sans TW → Source Han Sans JP →
Source Han Sans KR → Geist → Geist Mono → Twemoji默认字体的选择
由于 AlibabaPuHuiTi 位于表格首位,且包含中日韩文字和拉丁字母,大多数文本在未指定字体时会直接使用 AlibabaPuHuiTi 渲染。这意味着:
- 中文、英文、数字默认使用 AlibabaPuHuiTi(无衬线黑体风格)
- Emoji 默认使用 Twemoji
- 如需衬线字体或特定风格,请显式指定
font-family
使用通用字体名时的回退
当使用通用字体名(如 sans-serif、serif、monospace、emoji)时,imgrender 会按照系统预设字体表格中的顺序,从上到下查找该类别的第一个可用字体:
| 通用字体名 | 回退顺序(按表格顺序) |
|---|---|
sans-serif | AlibabaPuHuiTi → Alibaba Sans KR → Source Han Sans CN → Source Han Sans TW → Source Han Sans JP → Source Han Sans KR → Geist |
serif | Source Han Serif CN → Source Han Serif JP → Source Han Serif KR |
monospace | Geist Mono |
emoji | Twemoji |
示例:
// 使用 sans-serif 时,会优先使用 AlibabaPuHuiTi
<div style={{ fontFamily: 'sans-serif' }}>你好世界</div>
// 使用 serif 时,会优先使用 Source Han Serif CN
<div style={{ fontFamily: 'serif' }}>你好世界</div>字符缺失时的回退
当渲染某个字符时,如果当前字体不包含该字符的字形(glyph),系统会按以下顺序查找:
- 检查字体列表中的下一个字体 - 如果
font-family指定了多个字体,依次尝试 - 检查同类别的其他字体 - 在同 General Font Family 的预设字体中查找
- 跨类别查找 - 尝试其他类别的字体
- 使用后备字体 - 最后使用系统默认后备字体
示例:
// 混合文本的回退过程
<div style={{ fontFamily: 'Geist' }}>Hello 世界 🎉</div>渲染过程:
Hello- Geist 包含拉丁字母,直接渲染世界- Geist 不包含中文,回退到 AlibabaPuHuiTi(首个 sans-serif 中文字体)🎉- 所有文本字体都不包含 emoji,回退到 Twemoji
自定义字体回退列表
你可以在 font-family 中指定多个字体,用逗号分隔,实现自定义的回退顺序:
<div style={{ fontFamily: 'Geist, Source Han Sans CN, sans-serif' }}>
Hello 世界
</div>回退顺序:
- 优先使用 Geist 渲染拉丁字母
- 中文回退到 Source Han Sans CN
- 最后使用系统默认 sans-serif
<div tw="font-[Geist,Source_Han_Sans_CN,sans-serif]">Hello 世界</div>TailwindCSS 中,字体名称之间的空格需要用下划线替代,但逗号后的空格可以保留。
最佳实践
- 指定回退字体 - 始终在
font-family末尾添加通用字体名作为保底 - 考虑语言特性 - 混合多语言内容时,明确指定各语言的回退字体
- Emoji 处理 - 如需精确控制 emoji 渲染,在字体列表末尾添加
emoji
<div style={{ fontFamily: 'Geist, Source Han Sans CN, Twemoji, sans-serif' }}>
Hello 世界 🎉
</div>文字排版
空白控制
默认情况下,imgrender 遵循 HTML 标准的默认空白规则:合并连续空白(空格、制表符、换行符均被合并为一个空格)、忽略行首尾空白 以及自动换行。
你也可以使用 white-space 属性来控制空白的渲染规则:
| 属性值 | 合并空白符 | 保留换行符 | 自动换行 | 说明 |
|---|---|---|---|---|
normal | ✅ | ❌ | ✅ | 默认行为,连续空白符合并为一个空格,换行符也被合并,文本自动换行 |
nowrap | ✅ | ❌ | ❌ | 合并空白符和换行符,但禁止自动换行,文本在同一行内显示 |
pre | ❌ | ✅ | ❌ | 保留所有空白符和换行符,禁止自动换行,行为类似 <pre> 元素 |
pre-line | ✅ | ✅ | ✅ | 合并空白符但保留换行符,文本自动换行,源码中的换行会被保留 |
pre-wrap | ❌ | ✅ | ✅ | 保留所有空白符和换行符,同时允许自动换行,适合显示格式化代码 |
break-spaces | ❌ | ✅ | ✅ | 与 pre-wrap 相同,但行末的空格和换行符也会占用空间并影响布局 |
使用示例
保留源码中的换行和缩进:
<div style={{ whiteSpace: 'pre-wrap' }}>
{`第一行文字
第二行有缩进
第三行无缩进`}
</div>禁止文本换行:
<div style={{ whiteSpace: 'nowrap' }}>
这段文字不会自动换行,即使容器宽度不够
</div>保留源码中的换行和缩进:
<div tw="whitespace-pre-wrap">
{`第一行文字
第二行有缩进
第三行无缩进`}
</div>禁止文本换行:
<div tw="whitespace-nowrap">这段文字不会自动换行,即使容器宽度不够</div>- 请参考 TailwindCSS - white-space 文档获取更多用法
关于换行符
在 JSX 中,直接在字符串中输入换行符可能不太方便。可以使用模板字符串(反引号)来保留源码中的换行,或者使用 {'\n'} 显式插入换行符。
换行
CSS 的 text-wrap 属性用于控制元素内的文本换行方式。imgrender 支持以下值:
| 属性值 | 说明 |
|---|---|
wrap | 默认值,文本在行尾自动换行,受 word-break 和 overflow-wrap 等属性影响 |
nowrap | 禁止文本换行,所有文本将在同一行内显示(效果等同于 white-space: nowrap) |
balance | 平衡换行,自动调整换行位置使每行的字符数尽可能相近,适合标题、段落等短文本 |
pretty | 美观换行,与 balance 类似但更注重排版美观,可能会调整连字符断字等,适合长段落,计算成本更高 |
balance vs pretty
balance更适合标题、卡片内容等短文本,换行决策较快pretty更适合长段落,会考虑更多排版因素(如避免孤词),但渲染开销更大
使用示例
平衡换行(适合标题):
<h1 style={{ textWrap: 'balance' }}>
This is a long title that will be wrapped evenly across lines
</h1>美观换行(适合段落):
<p style={{ textWrap: 'pretty' }}>
This is a long paragraph text that benefits from prettier line breaking with
better typography considerations like preventing orphans.
</p>禁止换行:
<div style={{ textWrap: 'nowrap' }}>这段文本不会换行</div>平衡换行(适合标题):
<h1 tw="text-wrap-balance">
This is a long title that will be wrapped evenly across lines
</h1>美观换行(适合段落):
<p tw="text-wrap-pretty">
This is a long paragraph text that benefits from prettier line breaking with
better typography considerations like preventing orphans.
</p>禁止换行:
<div tw="text-wrap-nowrap">这段文本不会换行</div>- 请参考 TailwindCSS - text-wrap 文档获取更多用法
与 white-space 的关系
text-wrap: nowrap 与 white-space: nowrap 效果相同。两者的区别在于:
white-space主要控制空白符的处理方式text-wrap专注于换行行为控制
在需要禁止换行但保留空白符的场景下,建议使用 text-wrap: nowrap 配合 white-space: pre 等值。
文字溢出省略
当容器空间不足以显示完整文本时,可以使用 text-overflow 属性控制溢出文本的显示方式。
text-overflow 属性
| 属性值 | 说明 |
|---|---|
clip | 默认值,直接裁剪溢出文本,不显示任何提示 |
ellipsis | 在溢出文本末尾显示省略号 ... |
string | 使用自定义字符串代替省略号(部分浏览器支持有限) |
生效条件
text-overflow 生效需要同时满足以下条件:
- 元素设置
overflow: hidden(或overflow: scroll/auto) - 元素有明确的宽度限制(如
width、max-width或flex-shrink) - 对于单行省略:设置
white-space: nowrap或text-wrap: nowrap
单行文本省略
<div
style={{
width: '200px',
overflow: 'hidden',
whiteSpace: 'nowrap',
textOverflow: 'ellipsis',
}}
>
这是一段很长很长的文本,超出容器宽度时会显示省略号
</div><div tw="w-48 truncate">这是一段很长很长的文本,超出容器宽度时会显示省略号</div>TailwindCSS 的 truncate 工具类同时设置了 overflow: hidden、text-overflow: ellipsis 和 white-space: nowrap。
多行文本省略
对于多行文本的省略,使用 -webkit-line-clamp 属性限制显示行数:
<div
style={{
width: '300px',
display: '-webkit-box',
WebkitBoxOrient: 'vertical',
WebkitLineClamp: 3,
overflow: 'hidden',
}}
>
这是一段很长很长的文本,当超过三行时会被截断并显示省略号。
多行省略在实际开发中非常常见,比如文章摘要、商品描述等场景。 imgrender
会自动处理这些样式,确保渲染效果符合预期。
</div><div tw="w-72 line-clamp-3">
这是一段很长很长的文本,当超过三行时会被截断并显示省略号。
多行省略在实际开发中非常常见,比如文章摘要、商品描述等场景。 imgrender
会自动处理这些样式,确保渲染效果符合预期。
</div>TailwindCSS 提供 line-clamp-{n} 工具类(n 为 1-6),配合 overflow: hidden 使用。
- 请参考 TailwindCSS - line-clamp 文档获取更多用法
imgrender 的特殊处理
在 imgrender 中,使用 line-clamp 时无需手动设置 display: -webkit-box 等属性,imgrender 会自动识别并处理。你也可以使用简化的写法:
<div style={{ lineClamp: 3, overflow: 'hidden' }}>多行文本内容...</div>