1. HOME
  2. WordPress
  3. プラグインを使わずにWordPressにページネーションを実装する方法
WordPress - 2025-07-22

プラグインを使わずにWordPressにページネーションを実装する方法

WordPressでブログやお知らせ一覧を作成する際に必須となる「ページネーション(ページ送り機能)」。デフォルトのthe_posts_pagination()でも基本的な実装は可能ですが、「もっと自由にHTMLやCSSクラスをカスタマイズしたい!」と感じたことはありませんか?

この記事では、WordPressのコア関数paginate_links()を活用し、再利用可能でカスタマイズ性に優れたページネーションを自作する方法を解説します。

なぜ自作するのか? デフォルト機能との違い

WordPressには the_posts_pagination() という便利な関数が用意されています。しかし、この関数が出力するHTML構造は決まっており、例えばBootstrapのような特定のCSSフレームワークが要求するクラス(例: page-item, page-link)を付与するには、一手間必要です。

今回紹介する方法では、paginate_links()関数を使い、ページネーションの各パーツ(次へ、前へ、ページ番号など)を配列として取得します。これにより、HTML構造をループ処理で自由に組み立てることが可能になり、デザインの要求に柔軟に応えられます。

functions.phpにページネーション関数を定義する

まずは、テーマのfunctions.phpに、ページネーションを生成するための汎用関数を追加します。この関数を一度定義しておけば、サイト内のどこからでも呼び出すことができます。

/**
 * カスタマイズ可能なページネーションを出力する関数
 * @param WP_Query $query WP_Queryオブジェクト (オプション)
 */
function my_custom_pagination( $query = null ) {
    // $queryが指定されていない場合は、グローバルな$wp_queryを使用
    if ( $query === null ) {
        global $wp_query;
        $query = $wp_query;
    }

    // ページ数が1以下の場合は何も出力しない
    if ( $query->max_num_pages <= 1 ) {
        return;
    }

    // paginate_linksの引数を設定
    $links = paginate_links( array(
        'base'         => get_pagenum_link(1) . '%_%',
        'format'       => get_option('permalink_structure') ? 'page/%#%/' : '&paged=%#%',
        'current'      => max( 1, get_query_var('paged') ),
        'total'        => $query->max_num_pages,
        'prev_text'    => '«',
        'next_text'    => '»',
        'type'         => 'array', // ★重要:リンクを配列として取得する
        'mid_size'     => 2, // 現在のページの両側に表示するページ数
        'end_size'     => 1, // 先頭と末尾に表示するページ数
    ) );

    // リンクが生成された場合のみHTMLを出力
    if ( ! empty( $links ) ) {
        echo '<ul class="pagination">';

        foreach ( $links as $link ) {
            // 現在のページ番号には 'current' クラスが含まれる
            if ( strpos( $link, 'current' ) !== false ) {
                // <span>タグを<li>で囲み、Bootstrap用のクラスを付与
                echo '<li class="page-item active" aria-current="page">' . str_replace( 'page-numbers', 'page-link', $link ) . '</li>';
            } elseif ( strpos( $link, 'dots' ) !== false ) {
                // 「...」(三点リーダー) にはクリックできないようにクラスを付与
                echo '<li class="page-item disabled">' . str_replace( 'page-numbers', 'page-link', $link ) . '</li>';
            } else {
                // 通常のページリンク
                echo '<li class="page-item">' . str_replace( 'page-numbers', 'page-link', $link ) . '</li>';
            }
        }

        echo '</ul>';
    }
}

関数のポイント解説

  • 'type' => 'array': paginate_links()の最も重要な設定です。これにより、戻り値がHTML文字列ではなく、リンクパーツごとの配列になります。このおかげで、foreachループで各要素を個別に処理できます。
  • str_replace(): paginate_links()が自動で付与するpage-numbersというクラスを、Bootstrapで使われるpage-linkに置換しています。
  • if (strpos(...) ...): 配列の各要素(リンク文字列)にcurrent(現在のページ)やdots(…)が含まれているかを判定し、それぞれに応じた<li>タグのクラス(active, disabled)を動的に付与しています。

テンプレートファイルから関数を呼び出す

functions.phpに関数を定義したら、あとは表示したい場所で呼び出すだけです。

通常の投稿一覧(archive.phpなど)での使い方

archive.phpcategory.phpindex.phpなど、メインクエリを使用するテンプレートでは、ループの終了後(endwhile;の後)に以下のように記述します。

<?php if ( have_posts() ) : ?>

    <?php while ( have_posts() ) : the_post(); ?>

        <?php // 記事のタイトルなどを表示 ?>
        <h2><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h2>

    <?php endwhile; ?>

    <?php // ここにページネーションを呼び出す ?>
    <nav class="pagination-wrapper">
        <?php my_custom_pagination(); ?>
    </nav>

<?php else : ?>

    <p>記事が見つかりませんでした。</p>

<?php endif; ?>

カスタム投稿タイプ(WP_Query)での使い方

固定ページなどでサブループ(new WP_Query())を使用している場合は、作成したクエリオブジェクトを関数の引数として渡します。

<?php
$paged = get_query_var( 'paged' ) ? get_query_var( 'paged' ) : 1;
$args = array(
    'post_type'      => 'news',       // カスタム投稿タイプ名
    'posts_per_page' => 5,            // 1ページあたりの表示件数
    'paged'          => $paged,
);
$news_query = new WP_Query( $args );

if ( $news_query->have_posts() ) :
    while ( $news_query->have_posts() ) : $news_query->the_post();
        // 投稿タイトルなどを表示
        the_title( '<h2>', '</h2>' );
    endwhile;

    // ★作成したクエリを引数に渡す
    my_custom_pagination( $news_query );

    wp_reset_postdata(); // クエリをリセット
endif;
?>

CSSでスタイリングする

上記のPHP関数は、Bootstrap 5と互換性のあるHTMLを出力します。
もしBootstrapを導入していない場合は、以下のCSSを参考に独自のスタイルを適用してください。

/* ページネーション全体のコンテナ */
.pagination {
    display: flex;
    padding-left: 0;
    list-style: none;
    border-radius: 0.25rem;
}

/* 各ページリンクのスタイル */
.page-link {
    position: relative;
    display: block;
    padding: 0.5rem 0.75rem;
    margin-left: -1px;
    line-height: 1.25;
    color: #007bff;
    background-color: #fff;
    border: 1px solid #dee2e6;
    text-decoration: none;
}

.page-link:hover {
    color: #0056b3;
    background-color: #e9ecef;
    border-color: #dee2e6;
}

/* アクティブ(現在)のページ */
.page-item.active .page-link {
    z-index: 1;
    color: #fff;
    background-color: #007bff;
    border-color: #007bff;
}

/* 無効化された(クリックできない)リンク */
.page-item.disabled .page-link {
    color: #6c757d;
    pointer-events: none;
    background-color: #fff;
    border-color: #dee2e6;
}

/* 角丸の調整 */
.page-item:first-child .page-link {
    margin-left: 0;
    border-top-left-radius: 0.25rem;
    border-bottom-left-radius: 0.25rem;
}

.page-item:last-child .page-link {
    border-top-right-radius: 0.25rem;
    border-bottom-right-radius: 0.25rem;
}

まとめ

paginate_links()を配列として扱うことで、WordPressのページネーションは飛躍的に柔軟になります。今回作成した関数をベースに、さらに独自のクラスを追加したり、構造を変更したりすることも簡単です。