私は何十年もの間、開発効率向上とパイプライン設計の最前線に立ち、数多のプロジェクトでデザインシステムがその生命を全うする様を見てきた。その中で、最も普遍的かつ深刻な問題の一つが、タイポグラフィの管理だ。特にSketchのような強力なデザインツールにおいて、その機能の深奥を理解せず、表層的な使い方に終始すれば、大規模プロジェクトにおけるText Stylesは必ずや破綻する。
本稿では、Sketchのスマートフォント設定とText Stylesのネスト管理に焦点を当て、デザインシステムのタイポグラフィ崩壊を防ぐための極限の設計図、そしてそれを実現する自動化戦略を、低レイヤの知見を交えながら解説する。これは、単なるマニュアルの焼き直しではない。現場で血と汗を流し、システムの骨格から再構築してきた者のみが語り得る、真の設計思想と実装哲学である。
—
Sketch Text Stylesの深淵:大規模デザインシステムを崩壊から救う、ネスト管理と自動化の極限戦略
1. タイポグラフィ崩壊の序章:なぜ一般的なText Styles管理は機能しないのか
多くのデザインチームは、SketchのText Styles機能に飛びつき、安易にスタイルを定義し始める。`H1`, `Body Text`, `Caption`…。最初は順調に見えるだろう。しかし、プロジェクトが成長し、デザインシステムが複雑化するにつれて、以下のような問題が噴出する。
- スタイルの乱立と重複: デザイナーごとに微妙に異なるスタイルが作成され、類似のスタイルが無限に増殖する。
- 命名規則の破綻: 一貫性のない命名により、どのスタイルが正しいのか、どこで使うべきなのかが不明確になる。
- レスポンシブ対応の欠如: デスクトップ、タブレット、モバイルで異なるフォントサイズや行間が必要になった際、既存のスタイルが機能せず、新しいスタイルが場当たり的に追加される。
- 開発者との乖離: デザインツール上のスタイルと、CSS/SCSSで定義されるスタイルとの間に齟齬が生じ、手動での調整や確認が頻発する。
- メンテナンスコストの増大: 既存スタイルの変更が、意図せぬ箇所に影響を及ぼし、変更が困難になる。
これらの問題は、Text Stylesが「ただの見た目のプリセット」として捉えられていることに起因する。しかし、デザインシステムにおけるタイポグラフィは、単なる見た目ではない。それは「情報伝達の骨格」であり、「ユーザー体験の基盤」であり、そして「システム全体の一貫性を担保するDNA」である。このDNAが損傷すれば、システム全体が癌に冒されるように崩壊していく。
2. Sketchファイル構造の深層理解:Text Stylesが「どこに」存在するか
この崩壊を防ぐには、SketchがText Stylesをどのように管理しているか、その内部構造を理解する必要がある。Sketchファイルは、実体としてはZIPアーカイブである。これを解凍すると、JSONファイル群が姿を現す。最も重要なのは、`document.json`と`pages/`ディレクトリ内の各ページに対応するJSONファイルだ。
Text Stylesは、`document.json`内の`sharedStyles`オブジェクトに格納されている。各共有スタイルは一意の`do_objectID`を持ち、その中に`name`(Sketch UIで表示されるスタイル名)、`value`(フォントファミリー、サイズ、ウェイト、カラー、行間などの詳細設定)、そして`styleType`(Text Stylesの場合は`0`)が含まれる。
// document.json (抜粋)
{
“_class”: “document”,
// …
“sharedStyles”: {
“_class”: “MSImmutableSharedStyleContainer”,
“objects”: [
{
“_class”: “MSImmutableSharedStyle”,
“do_objectID”: “YOUR_UNIQUE_STYLE_ID_1”, // このIDが重要
“name”: “Heading/Display/XL/Bold”, // 階層化されたスタイル名
“value”: {
“_class”: “textStyle”,
“encodedAttributes”: {
“MSAttributedStringFontAttribute”: {
“_class”: “fontDescriptor”,
“attributes”: {
“name”: “Inter-Bold”,
“size”: 64
}
},
“paragraphStyle”: {
“_class”: “paragraphStyle”,
“alignment”: 0,
“allowsDefaultTighteningForTruncation”: 0,
“maximumLineHeight”: 76,
“minimumLineHeight”: 76
},
“textColor”: {
“_class”: “color”,
“alpha”: 1,
“blue”: 0.133333340293169,
“green”: 0.133333340293169,
“red”: 0.133333340293169
}
},
“verticalAlignment”: 0
},
“styleType”: 0
},
// … 他のスタイル
]
},
// …
}
この内部構造を理解することが、Text Stylesを「管理する」のではなく「支配する」ための第一歩となる。
3. 命名規則と階層設計の極意:タイポグラフィのDNAを設計する
Text Stylesの命名は、その存在意義そのものだ。場当たり的な命名は許されない。私たちは、Atomic Designの思想、BEMの構造、そしてレスポンシブデザインのコンテキストを統合した、多層的な命名規則を採用する。
基本構造: `[Category]/[Size]/[Weight]/[State]`
- Category (必須): テキストの用途やセマンティクスを示す。
- 例: `Heading`, `Body`, `Label`, `Button`, `Caption`, `Code`
- Size (必須): フォントのスケール。意味論的(`XL`, `L`, `M`, `S`, `XS`)または具体的なピクセル値(`64px`, `48px`)。推奨は意味論的スケール。
- 例: `Display/XL`, `H1`, `H2`, `Body/L`, `Body/M`
- Weight (必須): フォントの太さ。
- 例: `Regular`, `Medium`, `SemiBold`, `Bold`
- State (任意): 特定の状態でスタイルが変化する場合。
- 例: `Active`, `Hover`, `Disabled`, `Error`, `Placeholder`
- Breakpoint (任意): レスポンシブ対応のために、特定のブレークポイントでのみ適用されるスタイル。これは`Category`の直後や`Size`の直後に挿入する。
- 例: `Heading/Desktop/XL/Bold`, `Body/M/Tablet/Regular`
- これは純粋なText Stylesの機能ではないため、コンポーネントのOverridesと連携させる前提。
例:
- `Heading/Display/XL/Bold`
- `Heading/H1/SemiBold`
- `Body/L/Regular`
- `Body/S/Medium`
- `Label/Default/Bold`
- `Button/Primary/L/SemiBold`
- `Caption/XS/Regular`
- `Heading/H1/Desktop/Bold`
- `Heading/H1/Mobile/Bold`
特別な命名規則:
- `_DEPRECATED/`: 非推奨となったスタイル。削除せず、移行期間を設けるために残す。
- `_DO_NOT_USE/`: 特殊な理由で一時的に作成されたが、一般的な使用を禁止するスタイル。
- `_TEMP/`: プラグインや一時的な実験で生成されたスタイル。定期的なクリーンアップ対象。
この厳格な命名規則により、Text Stylesのインデックスが整理され、デザイナーは意図するスタイルを迷うことなく選択できる。そして何より、この階層構造は、後述する自動化スクリプトにおいて、デザイントークンへのマッピングを極めて容易にする。
4. 自動化と同期の極限:`sketchtool`とデザイントークン駆動開発
Text Stylesが数百、数千に及ぶ大規模プロジェクトで、手動での管理は自殺行為に等しい。我々は`sketchtool`(Sketch CLI)と、カスタムスクリプト、そしてデザイントークンを組み合わせて、Text Stylesの生成、同期、検証を完全に自動化する。
4.1. `sketchtool`の活用
`sketchtool`はSketchのCLIであり、ファイルの検証、テキストレイヤーの抽出、アートボードのエクスポートなど、多岐にわたる操作が可能だ。残念ながら、`sketchtool`はText Stylesの直接的な「作成」や「更新」のコマンドを提供していない。しかし、「抽出」と「検証」には絶大な威力を発揮する。
既存のText Stylesを抽出する:
sketchtool dump “your-design-system.sketch” –json > text_styles_dump.json
このコマンドは、Sketchファイル全体の構造をJSON形式でダンプする。これを用いて`document.json`に相当する情報を取得し、`sharedStyles`オブジェクトをパースすることで、現在のText Stylesの状態をプログラム的に把握できる。
4.2. デザイントークンからのText Styles生成(擬似コードとアプローチ)
真の自動化は、デザインの「ソースオブトゥルース」をデザインツールから分離し、デザイントークンとして一元管理することから始まる。我々はJSONやYAML形式でタイポグラフィのトークンを定義し、それを元にSketch Text Stylesを生成するスクリプトを構築する。
`typography.json`の例:
{
“fontFamily”: {
“primary”: “Inter”,
“secondary”: “Roboto Mono”
},
“fontSize”: {
“xs”: { “value”: “12px”, “lineHeight”: “16px” },
“s”: { “value”: “14px”, “lineHeight”: “20px” },
“m”: { “value”: “16px”, “lineHeight”: “24px” },
“l”: { “value”: “18px”, “lineHeight”: “28px” },
“xl”: { “value”: “24px”, “lineHeight”: “32px” }
},
“fontWeight”: {
“regular”: 400,
“medium”: 500,
“semibold”: 600,
“bold”: 700
},
“colors”: {
“text”: { “primary”: “#222222”, “secondary”: “#666666” }
},
“textStyles”: [
{
“name”: “Heading/H1/Bold”,
“fontFamily”: “primary”,
“fontSize”: “xl”,
“fontWeight”: “bold”,
“color”: “text.primary”,
“lineHeight”: “32px”
},
{
“name”: “Body/M/Regular”,
“fontFamily”: “primary”,
“fontSize”: “m”,
“fontWeight”: “regular”,
“color”: “text.secondary”,
“lineHeight”: “24px”
}
// … その他すべてのスタイル
]
}
Sketch Text Styles生成スクリプトの概要:
1. デザインソースの取得: `typography.json`をパースし、すべての定義済みスタイルを読み込む。
2. Sketchファイル解析: `sketchtool dump`で既存のSketchファイルを解析し、現在の`document.json`構造を抽出する。特に`sharedStyles`オブジェクトに注目。
3. スタイルオブジェクトの生成/更新:
- デザイントークンで定義された各スタイルに対し、Sketchの`MSImmutableSharedStyle`オブジェクトにマッピングする。
- `do_objectID`は、既存のスタイルに一致する場合はそのIDを再利用し、新規スタイルであればUUIDを生成する。これにより、Sketchファイル内でのスタイルの参照が維持される。
- `value.encodedAttributes`内の`MSAttributedStringFontAttribute`や`paragraphStyle`を、トークンの値に基づいて構築する。色もRGBA値に変換。
4. `document.json`の更新: 新しい`sharedStyles`オブジェクトで`document.json`を書き換える。
5. Sketchファイルの再アーカイブ: 更新されたJSONファイル群を元の構造に戻し、`your-design-system.sketch`としてZIPアーカイブする。
注意点: Sketchファイルを直接JSONとして操作することは、非常に高度な知識と細心の注意を要する。不正なJSON構造はファイル破損に直結するため、必ずバックアップを取り、慎重にテストされたスクリプトを用いること。また、Sketchの内部構造はバージョンアップで変更される可能性があるため、常に最新情報を追う必要がある。Node.jsの`sketch-json`などのライブラリが、このJSON操作をより安全に行うための抽象化レイヤーを提供してくれる場合もある。
4.3. CI/CDパイプラインへの組み込み
この自動化スクリプトは、Gitリポジトリにコミットされたデザイントークンファイルの変更をトリガーに、CI/CDパイプラインで自動実行されるべきだ。
1. `main`ブランチへのマージ: デザイナーが新しいデザイントークンを`main`ブランチにマージ。
2. CI/CDトリガー: GitHub ActionsやGitLab CI/CDが変更を検知。
3. Sketchファイル生成:
- クリーンなベースのSketchファイルをダウンロード。
- 自動化スクリプトを実行し、`typography.json`に基づいてText Stylesを更新したSketchファイルを生成。
4. 成果物のデプロイ/通知:
- 更新されたSketchファイルを、共有ストレージ(Google Drive, SharePointなど)にアップロードし、デザイナーが最新版をダウンロードできるようにする。
- または、Sketch Cloudへの自動アップロード(もしAPIが利用可能であれば)。
- SlackやTeamsで更新を通知。
これにより、デザインシステムのタイポグラフィは常にデザイントークンを真のソースオブトゥルースとし、Sketchファイルはそこから自動生成される「副産物」となる。手動でのスタイル追加や変更は許容せず、常にトークンを介して変更を行う運用を徹底する。
5. レスポンシブ対応とコンテキスト依存のスタイル:柔軟性の追求
SketchのText Styles自体には、CSSのメディアクエリのような「レスポンシブ」な概念は存在しない。しかし、上記で定義した命名規則と、SketchのSymbol Overridesを組み合わせることで、擬似的にレスポンシブなタイポグラフィを実現できる。
1. ブレークポイント別スタイルの定義:
`Heading/H1/Desktop/Bold` と `Heading/H1/Mobile/Bold` のように、ブレークポイントごとに異なるText Stylesを定義する。
2. コンポーネントの構築:
`Button`や`Card`などのSymbolコンポーネントに、テキストレイヤーを含める。
3. Symbol Overridesの活用:
親Symbolで、テキストレイヤーのOverrideとして、ブレークポイントに応じたText Styleを選択できるようにする。
例えば、`Button`コンポーネントのインスタンスを配置した際、プロパティインスペクタで「Text Style (Desktop)」と「Text Style (Mobile)」を切り替えられるように設計する。
4. 自動化スクリプトでの支援:
コンポーネント生成スクリプトが、これらのOverrideプロパティを自動的に設定できるよう支援する。
これにより、デザイナーは特定のコンポーネントを使う際、デバイスコンテキストに応じて適切なText Styleを適用できるようになる。これは、単にText Styleを適用する以上の、深いコンポーネント設計の領域に踏み込んでいる。
6. パフォーマンスと最適化ハック:システムの健全性を保つ
Text Stylesの数が無制限に増えれば、Sketch自身のパフォーマンスに影響を及ぼす。大規模なSketchファイルは、メモリ消費の増大、描画速度の低下、そしてクラッシュのリスクを高める。
- スタイルの厳選: 階層設計を徹底し、本当に必要なスタイルのみを定義する。冗長なスタイルは容赦なく削除する。`_DEPRECATED`や`_DO_NOT_USE`のような命名規則は、クリーンアップの対象を明確にする。
- 定期的な監査とクリーンアップ: 自動化スクリプトに、未使用のText Stylesを検出し、削除を提案する機能を組み込む。または、`sketch-json`パーサーを用いて、どのText Styleがどのレイヤーで参照されているかを分析し、参照されていないスタイルを自動削除する。
- Sketchのバージョン管理: Sketchはファイルのバイナリを最適化しようとするが、それでも限界がある。Git LFS(Large File Storage)などを利用して、Sketchファイルのバージョン管理を行う。
- メモリ消費の理解: Sketchはレンダリングのために、フォントグリフやレイヤー情報をメモリ上に展開する。多数の異なるフォントファミリーやサイズを使用すると、それだけ多くのリソースを消費する。フォントファミリーの数を最小限に抑え、フォントファイルを最適化(サブセット化など)することも考慮に入れる。
7. 開発者との連携とデザインシステムの真髄
デザインシステムの究極の目的は、デザイナーと開発者が共通の言語と資産で協調し、高品質なプロダクトを効率的に生み出すことにある。Text Stylesの厳格な管理と自動化は、この目的を達成するための重要な柱だ。
- デザイントークンの共有: `typography.json`は、デザイナーだけでなく、開発者にとっても共通のソースオブトゥルースとなる。Style Dictionaryのようなツールを使えば、このJSONからCSS変数、SCSS変数、JavaScriptオブジェクトなど、開発者が直接利用できる形式に変換できる。
// typography.json から Style Dictionary で生成される CSS 変数の例
:root {
–font-family-primary: “Inter”;
–font-size-xs: 12px;
–font-size-s: 14px;
–line-height-xs: 16px;
–font-weight-bold: 700;
–color-text-primary: #222222;
/ Text Styles /
–text-style-heading-h1-bold-font-family: var(–font-family-primary);
–text-style-heading-h1-bold-font-size: var(–font-size-xl);
–text-style-heading-h1-bold-font-weight: var(–font-weight-bold);
–text-style-heading-h1-bold-color: var(–color-text-primary);
–text-style-heading-h1-bold-line-height: var(–line-height-xl);
}
- コンポーネントライブラリとの連携: Storybookなどのコンポーネントライブラリで、デザインシステムが提供するすべてのタイポグラフィコンポーネントを展示する。そこでは、Sketch Text Stylesと完全に同期したCSSクラスやスタイルが適用されていることを保証する。
- LintingとValidation: `sketchtool dump`とカスタムスクリプトを組み合わせることで、Sketchファイル内のText Stylesがデザインシステムガイドラインに準拠しているかを自動的にチェックできる。
- 命名規則の違反。
- 定義されていないフォントの使用。
- 許容されていないフォントサイズや行間の使用。
これらのチェックをCI/CDパイプラインに組み込むことで、問題のある変更がマージされるのを防ぎ、デザインシステムの健全性を維持する。
結論:タイポグラフィはシステムの魂である
Sketchのスマートフォント設定とText Stylesのネスト管理は、単なるデザイン作業の効率化に留まらない。それは、大規模デザインシステムにおけるタイポグラフィの「崩壊」を未然に防ぎ、システムの健全性、保守性、拡張性を保証するための、極めて戦略的なアプローチである。
我々が追求するのは、表面的な美しさだけではない。その背後にあるデータ構造、自動化のパイプライン、そして開発者とのシームレスな連携にまで及ぶ、システム全体の整合性である。デザインシステムのタイポグラフィ管理は、もはやデザイナー単独の責務ではない。それは、プロダクトマネージャー、デザイナー、フロントエンドエンジニア、そしてDevOps担当者、全員が関与すべき、プロジェクトの根幹を成す重要な設計課題なのだ。
この極限の知見が、あなたのプロジェクトにおけるタイポグラフィの聖域を護り、システム全体の魂を救う一助となることを切に願う。真のプロフェッショナルは、ツールの裏側に隠された深層を理解し、それを支配することで、不可能を可能にする。