WordPressのテーマ開発でよく使う「条件分岐タグ」ですが、意外と落とし穴が多いです。
筆者もつい最近まで勘違いしていたのですが、
is_single()は通常の投稿(post)専用だと思っていた
実は違います。is_single() はカスタム投稿タイプにも true を返します。
この記事では「投稿ページ・カスタム投稿・固定ページ・その他」に正確に分けるための書き方を、コピペで使えるテンプレートつきで解説します。
よくある誤解:is_single() はカスタム投稿も対象
まず最初に確認しておきたい重要なポイントです。
// ❌ よくある誤解:is_single() は通常投稿だけに反応する
<?php if (is_single()) : ?>
<!-- 通常投稿のつもりが、カスタム投稿でも true になる -->
WordPressの公式ドキュメントによると、is_single() は固定ページと添付ファイル以外の、主要な投稿タイプの個別ページで true を返します。
| 条件分岐タグ | 通常投稿 | カスタム投稿 | 固定ページ |
|---|---|---|---|
is_single() | ✅ | ✅ | ❌ |
is_page() | ❌ | ❌ | ✅ |
is_singular() | ✅ | ✅ | ✅ |
これを知らずにテンプレートやCSS分岐を書いていると、意図しない挙動が起きます。
基本の分類と正しい書き方
テーマ開発でよくある分類の正しい条件分岐はこう書きます。
<?php if (is_single() && get_post_type() === 'post') : ?>
<!-- 1. 通常投稿ページ(post)のみ -->
<?php elseif (is_singular() && get_post_type() !== 'post' && !is_page()) : ?>
<!-- 2. カスタム投稿のみ(通常投稿・固定ページを除く) -->
<?php elseif (is_singular() && !is_page()) : ?>
<!-- 1&2. 通常投稿&カスタム投稿(固定ページを除く) -->
<?php elseif (is_page()) : ?>
<!-- 3. 固定ページのみ -->
<?php else : ?>
<!-- 4. その他(アーカイブ・カテゴリー・タグ・検索結果など) -->
<?php endif; ?>
なぜ get_post_type() が必要なのか
is_single() だけでは通常投稿とカスタム投稿を区別できないため、get_post_type() と組み合わせて投稿タイプ名で絞ります。
// 通常投稿のみ
is_single() && get_post_type() === 'post'
// 特定のカスタム投稿タイプのみ
is_singular() && get_post_type() === 'bulletin'
// カスタム投稿全般(通常投稿・固定ページを除く)
is_singular() && get_post_type() !== 'post' && !is_page()
よく使う条件分岐パターン集
カテゴリー別で分岐する
<?php if (is_single() && in_category('news')) : ?>
<!-- カテゴリー「news」の投稿ページ -->
<?php elseif (is_single() && in_category('column')) : ?>
<!-- カテゴリー「column」の投稿ページ -->
<?php endif; ?>
スラッグの代わりにカテゴリーIDも使えます。
<?php if (is_single() && in_category(5)) : ?>
投稿タイプ別で分岐する
<?php if (is_singular('bulletin')) : ?>
<!-- カスタム投稿「bulletin」のみ -->
<?php elseif (is_singular('news')) : ?>
<!-- カスタム投稿「news」のみ -->
<?php endif; ?>
is_singular('post_type_name') は is_singular() && get_post_type() === 'post_type_name' の短縮形です。
テンプレートファイル別で分岐する
固定ページでカスタムテンプレートを使っている場合の分岐です。
<?php if (is_page_template('page-contact.php')) : ?>
<!-- コンタクトページ専用のCSS・JSを読み込む -->
<link rel="stylesheet" href="fm-contact.css">
<?php elseif (is_page_template('page-about.php')) : ?>
<!-- 会社概要ページ -->
<?php endif; ?>
⚠️ is_page_template() は固定ページ専用です。カスタム投稿では使えません。
スラッグ別で分岐する
<?php if (is_page('privacy-policy')) : ?>
<!-- スラッグ「privacy-policy」の固定ページ -->
<?php endif; ?>
IDでも指定できます(ただしサイトをまたいで使い回す場合はIDが変わるためスラッグ推奨)。
<?php if (is_page(42)) : ?>
アーカイブ・一覧ページで分岐する
<?php if (is_post_type_archive('bulletin')) : ?>
<!-- カスタム投稿「bulletin」のアーカイブ -->
<?php elseif (is_category()) : ?>
<!-- カテゴリーアーカイブ -->
<?php elseif (is_tag()) : ?>
<!-- タグアーカイブ -->
<?php elseif (is_tax()) : ?>
<!-- カスタムタクソノミーアーカイブ -->
<?php elseif (is_search()) : ?>
<!-- 検索結果ページ -->
<?php endif; ?>
コピペで使えるテンプレート
テンプレート①:CSS分岐(head.phpなど)
ページ種別ごとにCSSを読み分けたいときに使えます。
<?php if (is_404()) : ?>
<!-- 404ページ(最優先) -->
<link rel="stylesheet" href="ly-404.css">
<?php elseif (is_single() && get_post_type() === 'post') : ?>
<!-- 通常投稿ページ -->
<link rel="stylesheet" href="ly-single.css">
<?php elseif (is_singular('bulletin')) : ?>
<!-- カスタム投稿「bulletin」 -->
<link rel="stylesheet" href="ly-bulletin.css">
<?php elseif (is_singular() && !is_page() && get_post_type() !== 'post') : ?>
<!-- その他のカスタム投稿 -->
<link rel="stylesheet" href="ly-singular.css">
<?php elseif (is_front_page() || is_home() || is_page()) : ?>
<!-- 固定ページ系 -->
<link rel="stylesheet" href="ly-page.css">
<?php if (is_page_template('page-contact.php')) : ?>
<!-- コンタクトページ追加CSS -->
<link rel="stylesheet" href="pg-contact.css">
<?php endif; ?>
<?php else : ?>
<!-- アーカイブ・カテゴリー・タグ・検索結果 -->
<link rel="stylesheet" href="ly-archive.css">
<?php endif; ?>
テンプレート②:body IDにスラッグを割り当て
CSSのセレクタ #page-slug でページ別スタイルを当てるためによく使うパターンです。
<?php
$body_id = '';
global $post;
if (is_404()) {
$body_id = 'error-404';
} elseif (is_front_page()) {
$body_id = 'front';
} elseif (is_home()) {
$body_id = 'home';
} elseif (is_singular()) {
if ($post && isset($post->post_name)) {
$body_id = esc_attr($post->post_name);
}
} elseif (is_post_type_archive()) {
$body_id = 'archive-' . esc_attr(get_post_type());
} elseif (is_category() || is_tag() || is_tax()) {
$term = get_queried_object();
if ($term && isset($term->slug)) {
$body_id = 'archive-' . esc_attr($term->slug);
}
} elseif (is_search()) {
$body_id = 'search-results';
} else {
$body_id = 'default';
}
?>
<body id="<?php echo $body_id; ?>" <?php body_class(); ?>>
テンプレート③:テンプレートファイルの分岐(functions.php)
カスタム投稿に singular.php を使いたいとき、template_include フィルターで制御します。
// functions.php
function my_custom_template_include($template) {
if (get_post_type() === 'post' && is_single()) {
// 通常投稿 → single.php
$new_template = locate_template(['single.php']);
if ($new_template) return $new_template;
} elseif (is_singular() && !is_page() && get_post_type() !== 'post') {
// カスタム投稿 → singular.php
$new_template = locate_template(['singular.php']);
if ($new_template) return $new_template;
}
return $template;
}
add_filter('template_include', 'my_custom_template_include');
singular.php 内でさらに投稿タイプ別に分岐することもできます。
// singular.php
<?php if (get_post_type() === 'bulletin') : ?>
<?php get_template_part('parts/content', 'bulletin'); ?>
<?php elseif (get_post_type() === 'news') : ?>
<?php get_template_part('parts/content', 'news'); ?>
<?php endif; ?>
テンプレート階層と条件分岐の関係まとめ
WordPressがどのテンプレートファイルを読み込むかはテンプレート階層で決まります。条件分岐タグはそのファイル内での処理分岐に使います。
テンプレートファイル(WordPress が自動選択)
└─ 個別表示
├─ single-{post_type}.php ← カスタム投稿専用を作るならここ
├─ single.php ← 通常投稿&カスタム投稿の共通
├─ singular.php ← 上記がない場合のフォールバック
└─ index.php
└─ 固定ページ
├─ カスタムテンプレート.php
├─ page-{slug}.php
├─ page.php
└─ singular.php
└─ アーカイブ
├─ archive-{post_type}.php
├─ category.php / tag.php
├─ archive.php
└─ index.php ← search.php はここにフォールバック(archive.php ではない)
注意点:search.php は archive.php にフォールバックしません。search.php → index.php の順です。検索結果ページのレイアウトはカテゴリーページと似ていても、テンプレートは独立して作る必要があります。
まとめ
| やりたいこと | 正しい書き方 |
|---|---|
| 通常投稿のみ | is_single() && get_post_type() === 'post' |
| カスタム投稿のみ | is_singular() && !is_page() && get_post_type() !== 'post' |
| 特定のカスタム投稿のみ | is_singular('post_type_name') |
| 固定ページのみ | is_page() |
| 特定の固定ページ | is_page('slug') |
| カスタムテンプレート | is_page_template('template.php') ※固定ページのみ |
| 404ページ | is_404() を最優先で書く |
is_single() がカスタム投稿にも反応するという仕様を知っているだけで、テーマ開発の多くの「なぜか動かない」を防げます。ぜひこの記事のテンプレートをベースにカスタマイズしてみてください。

