字距调整 — 是对特定字符对之间的间距进行选择性调整,以实现文本视觉均匀性。与均匀改变所有字符之间距离的字间距不同,字距调整考虑每对字母的形状:A和V、T和o、W和a。没有字距调整时,带有突出元素的组合看起来不均匀——字母之间会出现视觉空白或压缩。根据Apple NSAttributedString 文档,iOS上的字距调整通过.kern属性设置,支持正值和负值。
要点
字距调整 — 是手动或自动调整特定字符对之间距离以消除视觉伪影的过程。问题出现是因为每个字母都有独特的几何形状:A有顶点,V有右斜,T有宽横杠。当这样的字母相邻时,它们轮廓之间的距离看起来不均匀,尽管字符间距相同。
字体的字距调整表包含带有预设调整值的字符对。一个优秀字体可能有300到2000个字距调整对。专业字体——例如Apple的SF Pro或Google的Roboto——包含精心制作的字距调整表,涵盖拉丁字母和西里尔字母的所有可能组合。根据Fontshop字距调整指南,字距调整表的质量是专业字体的主要标志之一。
视觉效果 字距调整在标题、徽标和大号文本(24pt起)中尤其明显。在小文本(12-14pt)中,字母之间的距离很小,字距调整不太明显,尽管它仍在工作。Web浏览器和移动操作系统默认应用内置字距调整,但开发人员可以禁用它或针对特定设计进行调整。
初级开发人员经常混淆字距调整和字间距,但这是排版中根本不同的参数。字距调整在字符对级别工作,仅调整字母几何形状造成视觉不平衡的特定组合之间的距离。字间距(letter-spacing)均匀地更改选定片段中所有字符之间的间距——统一增大或减小。
何时使用字间距:用于改善小文本的可读性(正字间距),用于创建重音标题(负字间距),用于界面设计中的文本样式化。字间距通过数值设置,并应用于每个字符,包括已经调整过的字距对——字距调整校正得以保留,但在它们之上添加了整体偏移。
| 参数 | 字距调整 | 字间距 |
|---|---|---|
| 应用范围 | 单个字符对 | 整个文本片段 |
| 值 | 每个对单独设置 | 所有字符统一 |
| 目的 | 视觉均匀性 | 调节文本密度 |
| iOS属性 | NSAttributedString中的.kern | CSS中的letter-spacing |
| 可见性 | 在24pt起的标题中 | 在所有字号中 |
重要规则:在负字间距(压缩)时,请注意字距调整对——它们可能造成不需要的字母重叠。在CSS中,letter-spacing属性应用于字体的字距调整表之上,在强压缩(letter-spacing: -1px)时,字距调整校正可能导致字符合并。
在iOS中,字距调整通过NSAttributedString中的.kern属性管理。属性的值是Float,正数增加间距,负数减少间距,0禁用字距调整。默认值是nil,表示使用字体的字距调整表。用于处理字距调整的主要API是NSMutableAttributedString,将属性添加到文本范围。
let text = "Kerning in mobile interfaces"
let attributedText = NSMutableAttributedString(
string: text
)
// 启用字距调整(使用字体表)
attributedText.addAttribute(
.kern,
value: 0.5,
range: NSRange(
location: 0,
length: text.count
)
)
// 应用于UILabel
label.attributedText = attributedText
默认值 .kern = nil启用来自字体表的字距调整。如果需要完全禁用字距调整——设置.kern = 0。值0.0和nil是不同的状态:nil使用表,0强制将所有字距调整对归零。根据Apple Text Programming Guide,显式设置0对于等宽文本或字距调整造成干扰的情况很有用——例如,在固定宽度的按钮中。
SwiftUI为Text提供了.kerning()修饰符。与UIKit不同,在SwiftUI中,字距调整在视图级别设置,而不是在属性字符串中。修饰符接受CGFloat并应用于Text块内的所有文本。对于SwiftUI中的部分字距调整,使用+运算符组合Text和单独的修饰符。
struct KerningView: View {
var body: some View {
Text("带有字距调整的标题")
.kerning(1.0)
.font(.title)
}
}
性能:带有字距调整属性的NSAttributedString在渲染时重新计算字符位置。对于静态文本,这发生一次。对于动态文本(UICollectionView中变化的文本)——每次更改时。在长字符串(超过500个字符)中使用大字距调整范围可能会在滚动时降低FPS。
在Android中,字距调整通过TextView和XML布局中的letterSpacing属性管理。属性类型为Float,作为em中字体大小的乘数。值0对应默认字距调整,正值增加间距,负值减少间距。letterSpacing从API Level 21(Android 5.0 Lollipop)开始可用。
通过SpannableString实现允许将字距调整应用于字符串的一部分,而不是整个文本。使用ScaleXSpan类或自定义ReplacementSpan进行精确控制。根据Android开发者指南,ScaleXSpan按宽度缩放字符,模拟字符间距的变化,但不提供对字距调整对的直接控制。
// 在XML布局中
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Text with kerning"
android:letterSpacing="0.05" />
// 在Kotlin中以编程方式
val textView = findViewById<TextView>(R.id.myTextView)
textView.letterSpacing = 0.05f
限制:Android不直接支持字距调整表——letterSpacing对所有字符都像字间距一样工作。Android上的成对字距调整使用带有内置字距调整表的字体(OpenType GPOS feature kern)。支持取决于操作系统版本和渲染引擎:在Android 10+上,使用Minikin完全支持OpenType功能;在更早版本上,使用HarfBuzz有局限性。建议:在Android 8.0以下设备上检查字距调整显示。
在Web上,字距调整通过CSS属性font-kerning管理,它启用或禁用字体的内置字距调整表。值:auto(浏览器决定)、normal(字距调整启用)、none(字距调整禁用)。该属性自2016年起受到所有现代浏览器支持。根据MDN Web Docs,font-kerning仅适用于带有字距调整表的OpenType字体。
CSS属性letter-spacing——是字间距的对应物,但也可用于类似字距调整的效果。与font-kerning不同,letter-spacing均匀改变所有字符之间的间距,不考虑字距调整对。当同时使用这两个属性时,font-kerning首先应用,然后letter-spacing在其之上添加均匀偏移。
/* Enable kerning for headings */
h1 {
font-kerning: normal;
letter-spacing: 0.02em;
}
/* Disable kerning for monospace */
code, pre {
font-kerning: none;
}
TypeScript工具用于计算考虑字距调整的最佳letter-spacing,可以通过Canvas API分析字体的字距调整表。但在实践中,Web开发者依赖font-kerning: normal——在大多数情况下能提供最佳结果。额外的letter-spacing调整仅用于设计强调——例如,在具有大排版的落地页上。
字距调整是微调工具,错误使用会降低可读性。第一条规则:不要更改正文文本的字距调整。专业字体的字距调整表已经包含12-16pt字号的优化值。干预正文文本的字距调整会导致不均匀和视觉噪声。
第二条规则:对于24pt起的标题,使用正字距调整(根据字体0.5-1.5 pt)。大文本需要更多字母间距以提高可读性。x-height低的字体(例如Didot)比x-height高的字体(例如Helvetica)需要更多字距调整。测试数据:在iOS Apple Music应用中,标题使用0.8 pt的字距调整。
第三条规则:始终在实际字符串上测试字距调整,而不是在测试Lorem Ipsum上。不同的字符组合产生不同的视觉效果。特别注意带有突出元素的元音和辅音对:AV、Te、To、Wa、LT。在负字距调整时,观察fi、fl、fj对——在某些字体中它们可能在没有连字的情况下合并。
可访问性方面:诵读困难的用户阅读带有轻微正字距调整(0.3-0.5 pt)的文本效果更好。iOS和Android支持可覆盖应用字距调整的可访问性设置。使用带Dynamic Type的UIFontDescriptor,并通过UIAccessibility在可访问性设置中考虑字距调整。重要:不要阻止系统字距调整设置——这违反了关于文本适应的WCAG 2.2指南1.4.12。
常见问题
在NSAttributedString中设置.kern = 0属性。值0强制将所有字距调整对归零,包括字体的内置表。要在整个文本级别完全禁用,请通过attributedText在UILabel参数中设置.kern = 0。
字距调整改变字符之间的距离,保持它们的形状不变。连字用单个图形元素替换两个或多个字符。连字通常应用在字距调整无法消除不需要合并的地方——例如fi对。
是的,从Android 10(API 29)开始,使用Minikin渲染引擎,完全支持OpenType GPOS feature kern。在更早版本上,支持取决于设备制造商和HarfBuzz版本。建议在多个设备上进行测试。
使用字符串AVOWaToLt——它包含有问题的字距调整对。如果视觉间隙用肉眼可见,字体的字距调整表质量较低。对于专业检查,使用FontForge或Glyphs工具。
是的。在UICollectionView中动态更新带有字距调整的NSAttributedString时,重新计算字符位置可能会在滚动时降低FPS。对于长列表,缓存属性字符串或使用默认设置的UILabel。
总结
我们将开发一款交钥匙移动应用程序
IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。