【WordPress】個別投稿ページで特定カテゴリーのみ要素を表示・非表示にする方法

【WordPress】個別投稿ページで特定カテゴリーのみ要素を表示・非表示にする方法 WordPress

WordPressサイトを運営していると、特定カテゴリーの記事だけ表示内容やレイアウトを変えたいケースが出てきます。この記事では、個別投稿ページ(single.php)で特定のカテゴリーに応じて要素を表示・非表示にする方法を、3つのアプローチで紹介します。

3つの方法の使い分け

  • PHPで条件分岐in_category()):一部の要素だけ出し分けたい
  • 専用テンプレートsingle_template フィルター):レイアウトを丸ごと変えたい
  • CSSで切り替えbody_class):見た目の制御だけならPHP不要
スポンサーリンク

PHPでカテゴリーを条件分岐して表示を切り替える

single.php 内で in_category() を使うと、表示中の投稿が特定カテゴリーに属するかを判定できます。次の例は、news カテゴリーの記事にだけお知らせバナーを表示し、それ以外の記事では非表示にするものです。

single.php:newsカテゴリーだけバナーを表示
<?php if (in_category('news')) : ?>
  <div class="news-banner">
    <p>ニュース記事に関するお問い合わせはこちらへ。</p>
  </div>
<?php endif; ?>

<div class="entry-content">
  <?php the_content(); ?>
</div>

逆に「特定カテゴリーでは隠す」なら if (!in_category('news')) と否定にします。in_category() にはスラッグ・ID・配列を渡せます。複数カテゴリーに対応するなら in_category(array('news', 'column')) のように書きます。

ループ外では投稿IDを渡す
in_category() はループ内なら現在の投稿を自動判定しますが、ループ外で使う場合は第2引数に投稿IDを渡します(例:in_category('news', $post_id))。条件分岐の書き方は特定のカテゴリーを指定して条件分岐を実装する方法、バナーの出し分けの実例は特定のカテゴリーの記事にだけ共通のバナーを表示する方法も参考になります。

カテゴリー専用テンプレートで丸ごと切り替える

「single-カテゴリー.php」は自動では効きません
single-news.php を置けば news カテゴリーの投稿に適用される」という解説を見かけますが、これは誤りです。single-news.php が自動で使われるのは news というカスタム投稿タイプの場合だけで、WordPressのテンプレート階層にカテゴリー別の個別投稿テンプレートは存在しません。カテゴリーで切り替えるには、次の single_template フィルターを使います。

functions.php に次のコードを追加すると、news カテゴリーの投稿だけ、子テーマに置いた single-news.php を使うようになります。

functions.php:newsカテゴリーだけ専用テンプレートを使う
add_filter('single_template', 'my_category_single_template');
function my_category_single_template($template) {
  if (in_category('news')) {
    $new_template = locate_template('single-news.php'); // 子テーマ優先で探す
    if ($new_template) {
      return $new_template;
    }
  }
  return $template;
}

あとは子テーマに single-news.php を作成すれば、news カテゴリーの記事だけレイアウトを丸ごと変えられます。共通パーツの読み込みにはget_template_part()で指定したテンプレートファイルを読み込む方法が便利です。

CSSで特定カテゴリーにだけスタイルを適用する

WordPressは body_class() を使っているテーマなら、<body> タグに category-スラッグ のクラスを自動で付与します。これを起点にすれば、PHPを触らずCSSだけで出し分けできます。

CSS:newsカテゴリーの投稿だけ要素を非表示
/* newsカテゴリーの投稿ページでだけ .target-element を隠す */
body.category-news .target-element {
  display: none;
}

デザイン面の制御だけならこの方法が最も手軽です。body に付くクラスの仕組みや独自クラスの追加はbody_class()でbodyタグにクラスを追加・削除する方法を参照してください。

CSSの非表示は「隠すだけ」
display: none はHTML自体は出力されたまま画面から隠すだけです。会員限定情報などを確実に出し分けたい場合はPHP側(方法1・2)で制御してください。ソースを見れば内容が見えてしまいます。

よくある質問(FAQ)

Q固定ページで特定カテゴリーの関連記事を表示するには?
A固定ページ自体にカテゴリーはありませんが、WP_Query でカテゴリーを指定して取得できます。new WP_Query(array('category_name' => 'news', 'posts_per_page' => 5));page.php や固定ページ用テンプレートに追加します。
Qカスタム投稿タイプ+カスタムタクソノミーで絞り込むには?
Atax_query を使います。new WP_Query(array('post_type' => 'custom_post', 'tax_query' => array(array('taxonomy' => 'custom_tax', 'field' => 'slug', 'terms' => 'term-slug')))); のようにカスタムタクソノミーの条件で取得できます。
Q表示・非表示の条件分岐にはどの関数を使えばよいですか?
Aページ種別は is_single()is_page()is_category()is_archive()is_front_page() などの条件分岐タグ、投稿のカテゴリー判定は in_category() を使います。カスタム投稿タイプには is_singular('post_type') が使えます。

まとめ

  • 一部の要素だけin_category() で条件分岐(確実に出し分けたいならPHP)
  • レイアウトごとsingle_template フィルター+子テーマの専用テンプレート(single-カテゴリー.php は自動では効かない)
  • 見た目だけbody.category-スラッグ を起点にCSSで制御(隠すだけな点に注意)

変更の範囲(要素・レイアウト・見た目)に合わせて方法を選ぶと、管理しやすい実装になります。