カーニングとは、テキストの視覚的な均一性を達成するために、特定の文字ペア間のスペースを選択的に調整することです。すべての文字間の距離を均一に変更するトラッキングとは異なり、カーニングは各文字ペア(AとV、Tとo、Wとaなど)の形状を考慮します。カーニングがない場合、突出した要素を持つ組み合わせは不均一に見え、文字間に視覚的な隙間や圧縮が生じます。Apple NSAttributedString ドキュメントによると、iOSでのカーニングは.kern属性を介して設定され、正の値と負の値の両方をサポートします。
重要なポイント
カーニングとは、光学アーティファクトを除去するために、特定の文字ペア間の距離を手動または自動で調整するプロセスです。この問題は、各文字が独自の形状を持つために発生します。Aは頂点を持ち、Vは右傾斜、Tは幅広のクロスバーを持ちます。このような文字が隣り合うと、セット幅が同じでも、それらの輪郭間の距離が不均一に見えます。
フォントのカーニングテーブルには、プリセットされた調整値を持つ文字ペアが含まれています。優れた書体には300から2000のカーニングペアが含まれる場合があります。プロフェッショナルな書体 — AppleのSF ProやGoogleのRobotoなど — には、ラテン文字とキリル文字のすべての可能な組み合わせをカバーする、綿密に作成されたカーニングテーブルが含まれています。Fontshop Guide to Kerningによると、カーニングテーブルの品質はプロフェッショナルフォントの主要な指標の1つです。
カーニングの視覚効果は、特に見出し、ロゴ、大きなフォントサイズ(24pt以上)で顕著です。小さなテキスト(12~14pt)では文字間隔が狭く、カーニングは目立ちにくくなりますが、それでも機能します。WebブラウザとモバイルOSはデフォルトで組み込みカーニングを適用しますが、開発者は特定のデザインに合わせて無効化または調整できます。
初心者の開発者はしばしばカーニングとトラッキングを混同しますが、これらは根本的に異なるタイポグラフィパラメータです。カーニングは文字ペアレベルで機能し、文字の形状が光学的な不均衡を生み出す特定の組み合わせ間のみのスペースを調整します。トラッキング(文字間隔)は、選択したフラグメント内のすべての文字間の間隔を均等に変更します — 均一に増加または減少させます。
トラッキングが使用される場合:小さなテキストの可読性を向上させるため(正のトラッキング)、アクセント見出しを作成するため(負のトラッキング)、インターフェースデザインでテキストをスタイリングするため。トラッキングは数値として設定され、既にカーニングされたペアを含むすべての文字に適用されます — カーニング補正は保持されますが、その上にグローバルシフトが追加されます。
| パラメータ | カーニング | トラッキング |
|---|---|---|
| 適用範囲 | 個別の文字ペア | テキストフラグメント全体 |
| 値 | 各ペアに固有 | すべての文字で均一 |
| 目的 | 視覚的な均一性 | テキスト密度の調整 |
| 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は、レンダリング中に文字位置を再計算します。静的テキストの場合は1回のみです。動的テキスト(UICollectionViewで変化するテキスト)の場合は、変更のたびに再計算されます。長い文字列(500文字以上)でカーニングを含む広い範囲を使用すると、スクロール中にFPSが低下する可能性があります。
Androidでは、カーニングはTextViewとXMLレイアウトのletterSpacingプロパティを介して管理されます。属性はFloat型で、フォントのemサイズの乗数として機能します。値0はデフォルトのカーニングに対応し、正の値は間隔を広げ、負の値は狭めます。letterSpacingはAPI Level 21(Android 5.0 Lollipop)から利用可能です。
SpannableStringを使った実装では、テキスト全体ではなく文字列の一部にカーニングを適用できます。正確な制御にはScaleXSpanクラスまたはカスタムReplacementSpanが使用されます。Android Developer Guideによると、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)を持つフォントが使用されます。サポートはOSバージョンとレンダリングエンジンに依存します。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サイズに最適な値が既に含まれています。本文テキストのカーニングに干渉すると、不均一さと視覚的なノイズが生じます。
2番目のルール:24pt以上の見出しには、正のカーニング(書体に応じて0.5~1.5pt)を使用してください。大きなテキストは可読性のためにより多くの文字間スペースを必要とします。x-heightが低いフォント(Didotなど)は、x-heightが高いフォント(Helveticaなど)よりも多くのカーニングを必要とします。参考データ:iOSのApple Musicアプリでは、見出しに0.8ptのカーニングが使用されています。
3番目のルール:Lorem Ipsumではなく、実際の文字列で常にカーニングをテストしてください。異なる文字の組み合わせは異なる視覚効果を生み出します。突出した要素を持つ母音と子音のペア(AV、Te、To、Wa、LT)に特に注意してください。負のカーニングでは、fi、fl、fjのペアに注意してください — 一部のフォントでは合字なしで結合する可能性があります。
アクセシビリティの側面:失読症のユーザーは、わずかに正のカーニング(0.3~0.5pt)を施したテキストをより良く読むことができます。iOSとAndroidは、アプリのカーニングを上書きできるアクセシビリティ設定をサポートしています。Dynamic Typeと共にUIFontDescriptorを使用し、UIAccessibilityを介してアクセシビリティ設定でカーニングを考慮してください。重要:システムのカーニング設定をブロックしないでください — これはテキスト適応に関するWCAG 2.2ガイドライン1.4.12に違反します。
よくある質問
NSAttributedStringで.kern = 0属性を設定します。値0は、組み込みフォントテーブルを含むすべてのカーニングペアを強制的にゼロにします。テキスト全体レベルで完全に無効にするには、attributedTextを介してUILabelパラメーターで.kern = 0を設定します。
カーニングは文字間の距離を変更し、形状は変わりません。合字は2つ以上の文字を1つのグリフに置き換えます。合字は、カーニングでは不要な結合を除去できない場合(例えばfiペア)によく使用されます。
はい。Android 10(API 29)以降では、OpenType GPOS feature kernを完全にサポートするMinikinレンダリングが使用されます。以前のバージョンでは、サポートはデバイスメーカーとHarfBuzzのバージョンに依存します。複数のデバイスでテストすることをお勧めします。
AVOWaToLt文字列を使用してください — これには問題のあるカーニングペアが含まれています。視覚的な隙間が肉眼で目立つ場合、フォントのカーニングテーブルの品質は低いです。専門的な検証には、FontForgeまたはGlyphsツールを使用してください。
はい。UICollectionViewでカーニングを含むNSAttributedStringを動的に更新する場合、文字位置の再計算によりスクロール中にFPSが低下する可能性があります。長いリストの場合は、属性文字列をキャッシュするか、デフォルト設定でUILabelを使用してください。
まとめ
ターンキー方式のモバイルアプリケーションを開発します
IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。