PerfectVector
著者: Irene Kim2 分で読める

SVGのtextLength:文字を変形せずラベルを収める

実際のラベル例でSVGのtextLengthのspacingとspacingAndGlyphsを比較します。文字形状を保ち、最大幅を処理し、文言を編集可能なままにします。

目次

SVGラベルを指定した長さにする必要があり、小さな字間調整を許容できる場合は、textLength と lengthAdjust="spacing" を使います。字形は変わりません。spacingAndGlyphs を選ぶと、レンダラーは文字列に沿って文字自体を伸縮できます。この2モードはSVG文字仕様で定義されています。

注意点は目標値です。textLength は要求する長さであり、最大幅ではありません。 長いラベルを詰めるだけでなく、短いラベルも広げます。また、折り返した行は作りません。

各調整で変わるもの

設定変わるもの確認事項
textLength なしフォントの通常のレイアウトが長さを決めます。自然な長さでラベルが収まるか。
lengthAdjust="spacing"字間が変わり、字形は維持されます。広すぎる間隔や文字の衝突。
lengthAdjust="spacingAndGlyphs"字間と字形の比率が変わる場合があります。横に伸びたり縮んだりした文字。

lengthAdjust の値を付けずに textLength を設定した場合、spacing が既定です。MDNのtextLengthリファレンスは要求する長さと調整モードの関係を説明しています。

一般的なブランド表現には、小さな補正を使って確認してください。大きく縮める必要があるラベルには、通常、フォントサイズを小さくする、文言を短くする、レイアウトの空間を広げる方が適しています。

同じ目標値の短いラベルと長いラベル

私たちはオリジナルのひし形の紋章を描き、Abel Regular、フォントサイズ64 SVG単位で2つの編集可能なラベルをテストしました。意図したフォントの読み込み後、ブラウザーは PINE を約 115.6単位、PINE & FIELD を 325.3単位 と測定しました。両調整行は240単位を要求します。

同じ目標値でも異なる文字の見た目
短いラベルと長いラベルを自然な幅、spacingで240単位に調整、spacingと字形で240単位に調整した実際のSVG描画の比較
Abel Regularを読み込んだ実際のブラウザー描画。spacingは字形を保ちますが、ここでは間隔が広すぎたり文字が詰まったりします。spacingAndGlyphsは文字の比率を変えます。

短いラベルでは spacing が目立つ隙間を作り、長いラベルでは文字を詰めます。どちらも字形は保ちますが、このデザインに良い収まりではありません。spacingAndGlyphs の行は、書体の比率を見て分かるほど変えて同じ長さに到達します。

テストにはアプリ内ブラウザーのChrome 154を使いました。最初の文字の開始位置から最後の文字の終点までの横幅を測定し、各調整行は約240単位になりました。この例は1つのラテン文字フォントと単純な左から右の文字列を使っており、複数レンダラーや多言語の互換性テストではありません。

控えめな長さの補正を設定する

上の長いラベルでは330単位が自然な325.3単位に近くなります。240に押し込むより、有用な調整例です。

Google FontsのAbelディレクトリーから Abel-Regular.ttf と OFL.txt をダウンロードしてください。次のマークアップを含むHTMLファイルの隣の fonts フォルダーに置き、フォルダーをローカルで配信します。

<style>
  @font-face {
    font-family: Abel;
    src: url('./fonts/Abel-Regular.ttf') format('truetype');
    font-style: normal;
    font-weight: 400;
  }
</style>
 
<svg xmlns="http://www.w3.org/2000/svg"
     width="540" height="136" viewBox="0 0 540 136"
     role="img" aria-label="Pine and Field emblem and label">
  <path d="M25 80L63 24L101 80L63 114Z" fill="#287967"/>
  <path d="M43 80L63 49L83 80L63 97Z" fill="#c2d998"/>
  <text id="label" x="135" y="86"
        font-family="Abel" font-size="64" font-weight="400"
        textLength="330" lengthAdjust="spacing"
        fill="#17372e">PINE &amp; FIELD</text>
</svg>

単位なしの 330 はSVGの座標系に属します。ページ上でSVG全体を拡大縮小すると、画面の距離も変わります。文字の変更が図形を変えないよう、紋章と文字は分けて保持してください。

フォントは依然として重要です。textLength は文字をアウトラインにせず、書体をパッケージ化もしません。別のコンピューターで文字形状が変わるなら、字間を調整する前にSVGのフォント置換を診断します。

最大幅には、先に測定する

「短いラベルはそのまま、長いラベルだけ縮める」という規則なら、その条件を自分で追加します。この例はフォントサイズを減らすため、文字は両方向に小さくなりながら比率を保ちます。

上のSVGの後に次のスクリプトを置きます。固定330単位の調整を、最大240単位に置き換えます。

<script type="module">
  const label = document.querySelector('#label');
  const baseSize = 64;
  const maxWidth = 240;
 
  await document.fonts.load('64px Abel', label.textContent);
  await document.fonts.ready;
 
  label.removeAttribute('textLength');
  label.removeAttribute('lengthAdjust');
  label.setAttribute('font-size', String(baseSize));
 
  const naturalWidth = label.getComputedTextLength();
  if (naturalWidth > maxWidth) {
    const fittedSize = baseSize * maxWidth / naturalWidth;
    label.setAttribute('font-size', String(fittedSize));
  }
</script>

document.fonts.readyは、文書のフォント読み込みとレイアウトが完了するのを待ちます。明示的な load() は先にこの例の書体を要求します。意図した書体が読み込まれる前に測ると、代替の文字で収まりを判断する場合があります。

この分岐には自然な長さが必要なので、getComputedTextLength() を呼ぶ前に textLength を除きます。ブラウザーテストでは、表示上の開始点から終点の幅が変わっていても、このメソッドは spacing 行の自然な長さを返しました。調整済みの見た目の幅を常に測ると考えないでください。

このスクリプトでは短い PINE は64単位のサイズを維持し、長いラベルは約47.2単位に下がります。実際の表示や印刷サイズで確認してください。小さくした文字が読みにくければ、際限なくサイズを下げずレイアウトや文言を変えます。文言やフォント設定を変えたら、収める工程を再実行します。

最終ラベルを利用先で確認する

数値での収まりは1つの確認にすぎません。最終サイズで文字の組み合わせと紋章との間隔を見ます。デザインに調整が必要でなければ、通常のラベルは自然な字間を保ちます。

複数行では行を意図的に作って配置してください。textLength だけでは折り返し規則は得られません。曲がったバッジには別のSVGのパス上の文字の手順を使います。そのガイドは文字が沿うベースラインを制御します。

編集可能な文字を持つ元データを保持し、納品ファイルを実際の編集ソフト、ブラウザー、レンダラーで開きます。SVGファイルガイドは、同じ拡張子でも編集可能な文字、ベクターパス、埋め込み画像を含められる理由を説明しています。

元のロゴがラスター画像だけなら、PerfectVectorのロゴベクター化ツールで紋章の図形を復元できます。パスを確認して整理し、ラベルを収める前に文言を編集可能な文字で打ち直します。トレースした単語はパス形状なので、textLength はその字間を調整できません。ロゴベクター化の手順は、その元データの復元を扱っています。

よくある質問

textLengthは長すぎる文字だけを縮めますか? いいえ。長さを要求するため、自然な長さが短い文字を広げることもあります。最大幅の規則が必要なら、自然なラベルを測定して自分の条件を適用します。

どのlengthAdjust値が文字形状を保ちますか? spacingを使うと字形を伸ばさず字間を調整します。ただし大きな調整は不自然な隙間や衝突を作るので、最終サイズで文字を確認してください。

PNGからトレースした文字をtextLengthで収められますか? SVGの文字に作用するもので、文字形状のパスには作用しません。textLengthや編集可能な字間が必要なら、紋章を別のベクター図形として保ち、文言を編集可能な文字で打ち直します。

参考資料

  1. W3C — SVG 2の文字調整 — 2つのモードと、字形や文字送りへの影響を説明しています。
  2. MDN — textLength属性 — 要求する長さと既定のspacingモードを説明しています。
  3. MDN — FontFaceSet.ready — フォント読み込みとレイアウトを待つ方法を説明しています。
  4. MDN — getComputedTextLength — SVG文字要素の測定を説明しています。
  5. Google Fonts — Abel — オリジナルの比較に使ったフォントとライセンスです。

必要ならロゴベクター化ツールでラスターの紋章を復元し、文字は別のテキスト要素として保持してください。アウトラインの納品コピーやラスター書き出しを作る前に、通常サイズで最終ラベルを比較します。

ブログのその他の記事

編集しやすい
よりきれいなSVGから始めましょう