2行以上の長いタイトルでも1行に収まるように文字サイズをJavaScriptで調整する

記事タイトルが長くなって折り返され、2行になってしまっている…だけど、文字サイズを小さくしてでも1行にきっちり収めたい…!!Webサイトをデザインしているときに、そんな場面に遭遇したことはありませんか。僕はありません。

ということで、2行表示になっている文字列が1行に収まるように、JavaScriptでいい感じに文字サイズを小さくしてみます。

デモ

この記事のタイトルを1行に収めてみましょう。下のボタンを押してみてください。

ソース

function textAdjust(Class) {
  document.addEventListener('DOMContentLoaded', adjust);

  function adjust(){
    const title = document.getElementsByClassName(Class);
    for(i=0; i < title.length; i++) {
      title[i].style.display = 'block';
      const contentWidth = title[i].clientWidth;
      const font_size = document.defaultView.getComputedStyle(title[i], null).fontSize;

      title[i].style.display = 'inline-block';
      title[i].style.whiteSpace = 'nowrap';
      const titleWidth = title[i].clientWidth;

      if(titleWidth > contentWidth){
        const percent =  Math.floor(contentWidth / titleWidth * 100);
        const fontEm_size = percent / 100 + 'em';

        title[i].parentNode.style.fontSize = font_size;
        title[i].style.fontSize = fontEm_size;
      }
    }
  }
}
textAdjust('post-header__title');

引数(緑色でハイライトされている部分)に、文字サイズを調整したい要素のclass名を書いてください。ドットは必要ありません。

調整したい要素が複数ある場合は以下のように関数を複数回実行してください。

textAdjust('post-header__title');
textAdjust('post-list__title');

仕組み

emは親要素に指定されているfont-sizeを1とする、相対的な指定方法です。このスクリプトではこの特性を活かして文字サイズを調整しています。

  1. そのまま1行で表示したときの幅と、表示領域の幅を調べる
  2. 文字列が表示領域より大きかったら?
  3. 表示領域に対して文字列がどれくらい大きいのかを考えて文字サイズを計算する
  4. 文字列とその親要素に、計算したfont-sizeと基準となるfont-sizeを指定する

といった流れです。

注意点

文字列の要素の幅が、flexboxで自動的に決まっている場合、意図したとおりに動作しない場合があります。

また、ブラウザの設定にはアクセシビリティのため最小フォントサイズという項目があり、PC版のChromeの場合、デフォルトで10pxに設定されています。スクリプトで調整した結果、その設定以下のフォントサイズとなった場合は、コンテンツ幅をはみ出す場合があります。

参考にさせていただいた記事

上記のページのものは、アメブロ専用のものでjQueryで書かれていますが、汎用的に使えるようにネイティブJSで書き直させていただきました。ありがとうございました。