モバイル開発におけるカスタムフォント — 概要、形式と活用方法

著者: IT Sectr 公開日: 2026-07-23 読了時間: 10 分

Custom Fontは、デベロッパーがデフォルトのシステムフォントを置き換えるためにモバイルアプリケーションに追加するフォントファイル(TTF、OTF、WOFF2)です。カスタムフォントは、ユニークなビジュアルスタイルの作成、ブランドの一貫性の維持、さまざまな言語での可読性の向上に使用されます。Apple Fontsによると、カスタムフォントはすべてのAppleプラットフォームでサポートされており、AndroidはFont Familyメカニズムを提供して読み込みを簡素化しています。適切なフォント統合は、タイポグラフィとアプリケーションの全体的な印象に重要な影響を与えます。

重要ポイント

  • Custom Fontはシステム書体を置き換えるためにアプリに追加されるフォントファイル
  • 主な形式:TTF(TrueType)、OTF(OpenType)、WOFF2(Web Open Font Format)
  • iOSはInfo.plistとUIFontでフォントを読み込み、Androidはres/fontとTypefaceで読み込む
  • 各フォントはAPKまたはIPAサイズに50KB〜5MB追加する
  • バリアブルフォントはすべてのウェイトを1ファイルに格納できる

カスタムフォントとは?

Custom Font(カスタムフォント)は、オペレーティングシステムのデフォルトフォントセットに含まれない書体ファイルです。デベロッパーは、ブランドに一貫した独自のタイポグラフィを実現するために、このようなフォントをプロジェクトに追加します。カスタムフォントは、有料の商用書体の場合もあれば、Inter、Montserrat、カスタムバージョンのRobotoなどの無料のオープンソースフォントの場合もあります。

カスタムフォントの典型的なユースケースには、ブランドアプリのロゴや見出し、特定のタイポグラフィ要件を持つ読書アプリ、テーマフォントを使用したゲーム、システムフォントが目的のグリフをサポートしていない非ラテン言語のアプリケーションなどがあります。Google Fontsによると、トップ100アプリの60%以上が視覚的な差別化のためにフォントをカスタマイズしています。

カスタムフォントが必要な理由

システムフォント(iOSのSan Francisco、AndroidのRoboto)はインターフェース向けに最適化されていますが、ブランドのタイポグラフィには適していません。カスタムフォントはブランド認知を強化し、特殊文字(アイコンフォント)を含めることができ、特定のユーザーにとっての可読性を向上させます。ただし、異なるフォントを過剰に使用するとユーザー体験が低下するため、アプリケーションあたり2〜3ファミリー以下にすることをお勧めします。

モバイルアプリケーション向けフォント形式

モバイルプラットフォームはいくつかのフォント形式をサポートしています。TrueType(TTF)は最も一般的な形式で、iOSとAndroidのすべてのバージョンと互換性があります。OpenType(OTF)はTTFの拡張版で、合字、代替グリフ、OpenType機能をサポートしています。どちらの形式も.ttfと.otfの拡張子を持ち、モバイルプラットフォームで同じように動作します。

WOFF2(Web Open Font Format 2)はウェブ向けの圧縮形式で、Androidバージョン10以降でサポートされています。WOFF2はTTFと比較して30〜50%の圧縮率を提供します。iOSでは、WOFF2はSafariを介してサポートされますが、ネイティブアプリケーションではTTF/OTFへの変換が必要です。バリアブルフォント(Variable Fonts)は、すべてのウェイトを1つのファイルに格納する最新の形式です。

形式iOSAndroid圧縮特徴
TTF対応対応なし標準形式、幅広い互換性
OTF対応対応なしOpenType機能、合字、代替グリフ
WOFF2Safari経由API 29+30〜50%圧縮済み、APKサイズを削減
VariableiOS 11+API 29+高い全ウェイトを1ファイルに

モバイル開発では、主要な形式としてOTFを使用することをお勧めします。TTFと同じサイズでOpenType機能をサポートします。APKの容量を節約するには、woff2による圧縮またはオンデマンドのフォント読み込みを使用します。

iOSでのカスタムフォント統合

iOSでカスタムフォントを統合するプロセスは、ファイルをプロジェクトバンドルに追加し、Info.plistに登録するという2つのステップで構成されます。フォントファイルはプロジェクトディレクトリ(通常はResources/Fonts)に配置され、ターゲットに含まれます。Info.plistには、拡張子を含むフォントファイル名を指定してUIAppFonts配列(Fonts provided by application)が追加されます。

登録後、フォントはPostScript名を使用してUIFont(name:size:)でアクセス可能になります。PostScript名はUIFont.familyNamesとUIFont.fontNames(forFamilyName:)で確認できます。名前が間違っている場合、UIFont(name:size:)はnilを返します。デバッグのためには、初回起動時に登録されたすべてのフォントを画面に表示することをお勧めします。

統合例

SwiftでiOSプロジェクトにMontserratフォントを統合する全サイクルを見てみましょう。Montserrat-Regular.ttfファイルがプロジェクトに追加され、Info.plistで宣言され、UIFontを介して読み込まれ、UILabelに適用されます。各ウェイト(regular、bold、italic)には個別のファイルとInfo.plistへの個別のエントリが必要です。

swift
// 1. Info.plist: UIAppFonts → "Montserrat-Regular.ttf"
// 2. コードでフォントを読み込む
guard let customFont = UIFont(name: "Montserrat-Regular", size: 16) else {
    // システムフォントにフォールバック
    label.font = UIFont.systemFont(ofSize: 16)
    return
}
label.font = customFont
// 3. NSAttributedStringで使用
let attributes = [NSAttributedString.Key.font: customFont]
let attributed = NSAttributedString(string: "Text", attributes: attributes)

フォントが読み込まれない場合(UIFontがnilを返す)の処理は必須です。アプリケーションをクラッシュさせる代わりに、システムフォントをフォールバックとして使用します。これは、ネットワークから読み込まれたフォントやオプショナルモジュールに追加されたフォントで特に重要です。

CTFontManagerによる動的読み込み

オンデマンドでダウンロードされるフォントには、CTFontManagerRegisterGraphicsFontが使用されます。このメソッドはメモリ内のデータ(Data)からフォントを登録し、UIFontで使用可能にします。使用後は、CTFontManagerUnregisterGraphicsFontでフォントの登録を解除できます。動的読み込みは、すべてを即座に必要としない大規模なフォントセットを持つアプリケーションに役立ちます。

Androidでのカスタムフォント統合

Androidでは、カスタムフォントはres/fontリソースシステムを介して追加されます。TTFまたはOTFファイルはres/font/に配置され、その後、ウェイトをグループ化するためのXML Font Familyリソースが作成されます。Android 8.0(API 26)以降、これが唯一の推奨方法です。古いバージョンでは、assetsとTypeface.createFromAssetが使用されます。

XML Font Familyは、ウェイト(regular、bold、italic)とフォントファイルの間のマッピングを記述します。XMLレイアウトでは、属性android:fontFamily="@font/my_font"が、対応するスタイルでsetTypefaceが呼び出されたときに自動的に正しいファイルを選択します。これによりタイポグラフィが簡素化されます。テーマでファミリーを指定するだけで、setTypeface(textView, Typeface.BOLD)が呼び出されたときにAndroidが自動的にboldバージョンを選択します。

Font Familyの作成

res/font/my_font.xmlにXMLファイルを作成し、異なるウェイトのすべてのフォントファイルをリストします。各要素にはfontStyle(normal/italic)とfontWeight(100〜900)の属性があります。次に、レイアウトでandroid:fontFamily="@font/my_font"を指定します。textStyle="bold"が使用されると、Androidは自動的にfontWeight 700のファイルを選択します。

xml
<!-- res/font/my_font.xml -->
<?xml version="1.0" encoding="utf-8"?>
<font-family xmlns:app="http://schemas.android.com/apk/res-auto">
    <font
        android:fontStyle="normal"
        android:fontWeight="400"
        app:font="@font/my_font_regular" />
    <font
        android:fontStyle="normal"
        android:fontWeight="700"
        app:font="@font/my_font_bold" />
</font-family>

Font Familyを使用する場合、リソースアプローチは自動的にフォントをキャッシュし、正しいウェイトを選択します。必要なウェイトがファミリーにない場合、Androidは最も近い利用可能なウェイトから合成します。フォントを正確に制御するには、明示的なファイル参照を指定してTypeface.create()を使用します。

FlutterとReact Nativeでの統合

クロスプラットフォームフレームワークでは、フォント統合が統一されています。Flutterはpubspec.yamlを使用してフォントを宣言します。ファイルはプロジェクトのfonts/フォルダに配置され、ファミリーとウェイトを指定してfontsセクションにリストされます。その後、フォントはTextStyle(fontFamily: 'Montserrat')またはアプリのテーマを介して適用されます。FlutterはTTFとOTFをサポートしています。

React Nativeは2つのアプローチを使用します。ネイティブ(Info.plistとres/font経由)またはreact-native-vector-iconsや@expo-google-fontsなどのライブラリを介する方法です。Expoはプロセスを簡素化します。フォントはexpo-fontを介して読み込まれます:Font.loadAsync({ 'Montserrat': require('./assets/fonts/Montserrat.ttf') })。React Navigationとテーマを使用すると、フォントをグローバルに設定できます。

Flutterの例

pubspec.yamlでのフォント宣言とMaterialAppテーマでの適用。Montserrat-Regular.ttfとMontserrat-Bold.ttfのファイルはfonts/に配置されます。宣言後、フォントはアプリケーション全体でTextStyleを介してアクセス可能になります。fontWeight: FontWeight.boldが指定されると、Flutterは自動的にboldファイルを使用します。

dart
// pubspec.yaml
flutter:
  fonts:
    - family: Montserrat
      fonts:
        - asset: fonts/Montserrat-Regular.ttf
        - asset: fonts/Montserrat-Bold.ttf
          weight: 700
// テーマでの使用
MaterialApp(
  theme: ThemeData(
    textTheme: TextTheme(
      headlineLarge: TextStyle(
        fontFamily: 'Montserrat',
        fontWeight: FontWeight.bold,
        fontSize: 28
      )
    )
  )
)

Flutterが指定されたパスでフォントを見つけられない場合、アプリケーションはエラーなしでシステムのフォールバックフォントを使用します。デバッグのためには、MaterialAppでcheckConsistencyを有効にします。これによりフォントの可用性がチェックされ、フォントがない場合にコンソールに警告が表示されます。

フォントサイズの最適化

APKとIPAのサイズは、含まれるフォントの数に直接依存します。1つのTTFファイルは、ラテン文字セットで50〜500KB、キリル文字、CJK文字、その他の拡張セットをサポートするフォントで最大2〜5MBになります。10個のフォントはアプリケーションのサイズに10〜20MB追加する可能性があり、モバイルダウンロードにとって重要です。

最適化には、サブセッティング(フォントファイルから未使用の文字を削除すること)を使用します。glyphhanger、fonttools(pyftsubset)、Google Webfont Optimizerなどのツールは、必要なグリフ(ラテン文字+キリル文字+数字+句読点)のみを含むフォントバージョンを作成します。これによりサイズが50〜80%削減されます。iOSでは、初回起動時に必要のないフォントにオンデマンドリソースを使用できます。

バリアブルフォント

バリアブルフォントは、ThinからBlack、CondensedからExpandedまでのすべてのウェイトを含む単一のファイルです。1つのバリアブルフォントで、異なるウェイトの10〜20個の個別ファイルを置き換えることができます。このようなファイルのサイズは、約1〜2個の静的ファイルに相当します。対応状況:iOS 11+、Android 10+、Flutter(FontVariation経由)、React Native(カスタムライブラリ経由)。

圧縮とオンデマンド読み込み

フォントサイズを30〜50%削減するにはWOFF2を使用します。API 29のAndroidでは、WOFF2を直接使用できます。iOSでは、登録前にWOFF2をTTFに変換する必要があります。オンボーディング時や特定の画面でのみ使用されるフォントは、オンデマンドリソース(iOS)またはDynamic Feature(Android)を介して読み込む必要があります。これらはベースAPKには含まれません。

パフォーマンスとベストプラクティス

カスタムフォントは、読み込み時間とメモリの2つの方法でパフォーマンスに影響を与えます。最初のアクセス時に、システムはディスクからファイルを読み取り、フォントテーブルを解析し、レンダリング用の内部構造を作成します。1MBのフォントの場合、これには20〜50msかかります。初回読み込み後のキャッシュにより、後続のアクセス時の遅延が解消されます。

メモリ:読み込まれた各フォントはプロセスキャッシュに保存されます。システムフォントはプリロードされています。カスタムフォントは最初の使用時に読み込まれます。メモリ内では、解析された構造(cmap、glyf、head、hmtxテーブル)のため、フォントはディスク上の約2〜3倍の容量を占有します。平均サイズの5つのカスタムフォント(合計3MB)には、約6〜9MBのRAMが必要です。

推奨事項

カスタムフォントはアプリケーションあたり2〜3ファミリーに制限します。複数のウェイトを置き換えるにはバリアブルフォントを使用します。UI要素(ボタン、ラベル、リスト)にはシステムフォントを適用し、アクセントタイポグラフィ(見出し、バナー)にのみカスタムフォントを使用します。AndroidではMapを介してTypefaceをキャッシュし、iOSでは静的変数を介してUIFontをキャッシュします。

kotlin
object FontCache {
    private val cache = mutableMapOf<String, Typeface>()
    fun get(context: Context, fontId: Int): Typeface {
        return cache.getOrPut(fontId.toString()) {
            ResourcesCompat.getFont(context, fontId)
        }
    }
}
// RecyclerViewでの使用
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
    holder.textView.typeface = FontCache.get(context, R.font.montserrat_regular)
}

onBindViewHolderでのTypefaceの読み込みは、キャッシュがある場合にのみ許容されます。キャッシュがない場合、createFromAssetが呼び出されるたびに新しいオブジェクトが作成され、ディスクからファイルが読み取られます。RecyclerViewのスクロール中に、これにより顕著な遅延が発生します。キャッシュはフォントが一度読み込まれて再利用されるため、問題を解決します。

よくある質問

モバイルアプリケーションに最適なフォント形式は?

OTFがモバイルアプリケーションに最適な選択です。TTFと同じサイズでOpenType機能(合字、代替グリフ)をサポートします。容量を節約するには、サブセッティングを施したバリアブルフォント(TTXまたはOTF)を使用します。WOFF2はAndroid 10+にのみ適しており、ネイティブアプリケーションのiOSではサポートされていません。

モバイルアプリケーションでGoogle Fontsを使用できますか?

はい。Google Fontsは商用利用向けにOFL(Open Font License)の下でフォントを提供しています。フォントはfonts.google.comからダウンロードしてプロジェクトに追加できます。AndroidはGoogle Play Servicesを介してダウンロード可能フォントをサポートしており、フォントファイルをAPKに含めずに初回使用時に読み込むことができます。

カスタムフォントが表示されないのはなぜですか?

最も一般的な原因:ファイルがターゲットに追加されていない(iOS)、Info.plistで宣言されていない(iOS)、ファイルがres/fontにない(Android)、PostScript名が間違っている、ファイルが破損している。iOSでの診断には、コンソールにUIFont.familyNamesを出力します。Androidでは、FontLoaderを使用してassetsからのフォント読み込みをデバッグします。

APKのフォントサイズを削減するには?

サブセッティング(pyftsubset)を使用して未使用の文字を削除します。サイズが50〜80%削減されます。10個の個別ファイルの代わりにバリアブルフォントを使用します。Android 10+にはWOFF2圧縮を使用します。ProGuardを設定してフォントパスを難読化します。iOSにはオンデマンドリソースを使用します。

アプリケーションで使用できるカスタムフォントの数は?

2〜3ファミリー(異なるウェイトを含む)に制限することをお勧めします。各ファミリーはアプリケーションのサイズに200KB〜3MB追加します。システムフォントはアプリに負荷をかけないため、UI要素にはシステムフォントを使用し、見出しやアクセントブロックにはカスタムフォントを残します。

まとめ

  • Custom Fontはブランドタイポグラフィのためにアプリに追加されるフォントファイル(TTF、OTF、WOFF2)
  • iOS:バンドル内のファイル + Info.plistのUIAppFonts + UIFont(name:size:)
  • Android:res/font内のファイル + XML Font Family + Typefaceまたはandroid:fontFamily
  • Flutter:pubspec.yamlでの宣言 + TextStyle(fontFamily:)
  • 最適化:サブセッティングにより必要な文字を保持しながらフォントサイズを50〜80%削減
  • バリアブルフォントはすべてのウェイトを含む1ファイルで10〜20の静的ファイルを置き換え
  • キャッシュ:読み込み時にフォントをキャッシュ — アプリケーションセッションごとに1インスタンス

ターンキー方式のモバイルアプリケーションを開発します

IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。

プロジェクトについて相談

こちらもお読みください