Go to top Go to bottom

the_post_navigation()およびprevious_post_link() / next_post_link()は初期設定で、リンクに記事のタイトルを使います。記事のタイトルが長くなると、見た目がおかしくなったり、左右でリンク同士が衝突したりすることもありますので、ここではタイトルの文字数を制限する方法を紹介します。

CSSでの回避

前後のリンクが衝突
前後のリンクが衝突

「リンクが衝突する」というのは例えば上のようなケースです。キャッチーな言葉づかいや、SEOを考慮した言い回しにしようとすると、タイトルは得てして長くなりがちですので、しばしばこのような問題に直面します。

すでにこちらでも述べましたが、この問題はCSSで解決することができます(floatで左右に振っていることを想定しています。スタイルの全容はこちらを参照してください)。

.nav-previous, .nav-next {
  width: 40%;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

幅を全体の40%に限定し、それをはみ出る場合は改行せず(white-space: nowrap)かつ非表示にしています(overflow: hidden)。また、テキストがはみ出た場合に「…」を付けるtext-overflow: ellipsis;を有効にしています。

スタイル適用結果
スタイル適用結果

CSSで定義すると、全体の幅が変わっても確実に衝突することはありません。

CSSのサポートに注意

white-spacetext-overflowは古いブラウザでサポートされていません。モダンブラウザ以外の動作を保証する必要がある場合はCan I Use…などで状況を確認の上、適宜ベンダープレフィックスを入れるか、または別の方法を検討してください。

PHPで文字数を限定する

previous_post_link()は自動的にリンクを生成して挿入してくれるので便利ですが、記事のタイトルだけを取得してくることはできません。そこで、ある投稿の1つ前の投稿オブジェクトを取得できるget_previous_post()を利用します。

基本的な考え方

まずはべた書きしてみます。

<?php
  $max_length   = 10;
  $trim_marker  = '...';
  $html         = '';

  $prev_post = get_previous_post();
  
  if( !empty( $prev_post ) ) {
    $title = apply_filters( 'the_title', $prev_post->post_title );

    if( mb_strlen( $title ) > $max_length ) {
      $title = mb_substr( $title, 0, $max_length ) . $trim_marker;
    }    

    $html .= sprintf(
      '<a href="%s">%s</a>',
      esc_url( get_permalink( $prev_post->ID ) ),
      $title
    );

    echo $html;
  }  
?>

6行目で1つ前の投稿を取得し、$prev_postに格納しています。

このオブジェクトからタイトルを取得している処理が9行目です。記事のタイトルはthe_title()で出力する場合the_titleフィルターを通りますので、念のためここでも通してあります。必要ない場合は$prev_post->post_titleをそのままタイトルとして使用して構いません。

11~13行目で、もし文字数が最大数を超えていた場合に、部分文字列を取得し、最後に'...'を付ける処理を行っています。15行目以降はリンクタグを生成する処理です。

このコードを投稿ページの下あたりで実行すると、次のような出力を得ることができます。

PHPで最大文字数を設定
PHPで最大文字数を設定

今回は前の投稿を取得する処理でしたが、次の投稿を取得する場合も考え方は全く同じです。previousやprevをnextで置き換えれば事足りると思います。

関数にしてまとめる

前後の投稿を取得するために、上で示したコードをコピーし部分改変するのは冗長であり、あまり望ましくありません。そこで、functions.phpにどちらでも使える関数を作成し、使う場所で適宜呼び出すようにするのが得策です。

function twpp_adjacent_post_link( $previous = true, $max_length = 10, $trim_marker = '...' ) {
  $html = '';
  $post = get_adjacent_post( false, '', $previous );
  
  if( !empty( $post ) ) {
    $title = apply_filters( 'the_title', $post->post_title );

    if( mb_strlen( $title ) > $max_length ) {
      $title = mb_substr( $title, 0, $max_length ) . $trim_marker;
    }    

    $html .= sprintf(
      '<a href="%s">%s</a>',
      esc_url( get_permalink( $post->ID ) ),
      $title
    );

    echo $html;
  }  
}

$previousで前後を、$max_lengthで切り取る文字数を、そして$trim_markerで切り取った場合に後ろにつける文字列を指定します。たとえばリンクを出力したい箇所で、次のようにして使います。

<?php
  twpp_adjacent_post_link( true );
  twpp_adjacent_post_link( false );
?>
<?php
  twpp_adjacent_post_link( true, 20, '......' );
  twpp_adjacent_post_link( false, 20, '......' );
?>

実際にはHTMLのタグでマークアップして使うことになると思います。たとえば次のようになるでしょう。

<nav class="navigation post-navigation" role="navigation">
  <div class="nav-links">
    <div class="nav-previous">
      <?php twpp_adjacent_post_link( true ); ?>
    </div>
    <div class="nav-next">
      <?php twpp_adjacent_post_link( false ); ?>
    </div>
  </div>
</nav>

この結果、最大文字数を超える場合は切り取り、かつ省略文字を付加し、そうでない場合はそのまま出力するという処理を適用した投稿前後のリンクを得ることができます。

作成した関数を利用した出力結果
作成した関数を利用した出力結果

オプショナル引数のデフォルト値や、HTMLのマークアップはサイトに合わせて変更してください。