カテゴリーページで、ソートできるボタンを作る方法

WordPressのカテゴリーページ(例: https://example.com/category/)で、
記事を「新着順」「古い順」「タイトル順」などにソートできるボタンを追加する方法を解説します。

実装のポイント

  • functions.php にクエリ変更用のコードを追加する
  • JavaScriptでボタンをクリックするとソート条件を切り替える
  • CSSで見やすいボタンデザインにする
  • LightningやCocoonテーマに合わせた調整サンプルも紹介

functions.php にコードを追加

カテゴリーページでのソート処理を追加します。



// カテゴリーページでソート処理を追加
add_action('pre_get_posts', 'custom_category_sort');
function custom_category_sort($query) {
    if (!is_admin() && $query->is_main_query() && (is_category() || is_archive())) {
        if (isset($_GET['sort'])) {
            $sort = sanitize_text_field($_GET['sort']);
            if ($sort === 'new') {
                $query->set('orderby', 'date');
                $query->set('order', 'DESC');
            } elseif ($sort === 'old') {
                $query->set('orderby', 'date');
                $query->set('order', 'ASC');
            } elseif ($sort === 'title') {
                $query->set('orderby', 'title');
                $query->set('order', 'ASC');
            }
        }
    }
}

// JS・CSSを読み込む
add_action('wp_enqueue_scripts', 'enqueue_category_sort_assets');
function enqueue_category_sort_assets() {
    wp_enqueue_script(
        'category-sort',
        get_stylesheet_directory_uri() . '/js/category-sort.js',
        array(),
        '1.0',
        true
    );
    wp_enqueue_style(
        'category-sort-css',
        get_stylesheet_directory_uri() . '/style.css',
        array(),
        '1.0'
    );
}
  

アーカイブ・カテゴリーページ用ソートボタンのコード

テーマ別サンプルphp

Lightning用

ファイル名:main-archive.php
保存先:wp-content/themes/child-theme/g3/template-parts/main-archive.php


<?php
/**
 * Archive main template
 *
 * @package Lightning G3
 */

/* =========================================
   ソートボタン(新着順・古い順・タイトル順)
   検索ページでは非表示
========================================= */
if ( ! is_search() ) {
    $sort_buttons_html  = '<div class="sort-buttons">';
    $sort_buttons_html .= '<button class="sort-button" data-sort="new">新着順</button>';
    $sort_buttons_html .= '<button class="sort-button" data-sort="old">古い順</button>';
    //$sort_buttons_html .= '<button class="sort-button" data-sort="title">タイトル順</button>';
    $sort_buttons_html .= '</div>';
    echo wp_kses_post( $sort_buttons_html );
}

/* =========================================
   アーカイブタイトルと説明文
========================================= */
if ( ! is_search() ) {

    $post_top_info = VK_Helpers::get_post_top_info();

    // タイトル表示
    if ( $post_top_info['use'] || get_post_type() !== 'post' ) {
        if ( is_year() || is_month() || is_day() || is_tag() || is_tax() || is_category() ) {
            $archive_title = get_the_archive_title();
            $archive_header_html = '<header class="archive-header"><h1 class="archive-header-title">'
                . esc_html( $archive_title ) .
                '</h1></header>';

            echo wp_kses_post( apply_filters( 'lightning_archive_header', $archive_header_html ) );
        }
    }

    // 説明文表示
    if ( is_category() || is_tax() || is_tag() ) {
        $archive_description = term_description();
        if ( ! empty( $archive_description ) && 0 === get_query_var( 'paged', 0 ) ) {
            $archive_description_html = '<div class="archive-description">' . wp_kses_post( $archive_description ) . '</div>';
            echo wp_kses_post( apply_filters( 'lightning_archive_description', $archive_description_html ) );
        }
    }
}

/* =========================================
   投稿ループ開始
========================================= */
$post_type_info = VK_Helpers::get_post_type_info();
do_action( 'lightning_loop_before' );

if ( have_posts() ) :

    if ( apply_filters( 'lightning_is_extend_loop', false ) ) :
        do_action( 'lightning_extend_loop' );
    else :
        $post_list_class = lightning_the_class_name( 'post-list' ) . ' vk_posts vk_posts-mainSection';
        echo '<div class="' . esc_attr( $post_list_class ) . '">';

        global $lightning_loop_item_count;
        $lightning_loop_item_count = 0;

        while ( have_posts() ) :
            the_post();
            // ループアイテムを読み込む
            lightning_get_template_part( 'template-parts/loop-item', $post_type_info['slug'] );
            $lightning_loop_item_count++;
            do_action( 'lightning_loop_item_after' );
        endwhile;

        echo '</div> <!-- /.post-list -->';
    endif;

    // ページネーション
    $pagination_args = array(
        'mid_size'           => 1,
        'prev_text'          => '«',
        'next_text'          => '»',
        'type'               => 'list',
        'before_page_number' => '<span class="meta-nav screen-reader-text">' . __( 'Page', 'lightning' ) . ' </span>',
    );
    the_posts_pagination( apply_filters( 'lightning_pagenation_array', $pagination_args ) );

else :
    echo '<div class="main-section-no-posts"><p>' . wp_kses_post( lightning_get_no_post_text() ) . '</p></div>';

endif;

do_action( 'lightning_loop_after' );
?>
  

子テーマのディレクトリ構造

  • child-theme/
    • g3/
      • template-parts/
        • main-archive.php
    • tmp/
      • category-content.php
    • archive.php
    • category.php
    • functions.php
    • footer.php
    • header.php
    • style.css
    • js/
      • category-sort.js
    • images/
      • logo.png

Cocoon用

ファイル名:category-content.php
保存先:wp-content/themes/child-theme/tmp/category-content.php


<?php
/**
 * Cocoon WordPress Theme
 * category.php カスタマイズ版
 *
 * カテゴリーページにソートボタンを追加し、
 * ボタン用のスタイルを同じファイル内に記述。
 *
 * - 新着順 / 古い順 のボタンを表示
 * - 検索ページでは非表示
 * - 管理画面でも見やすいようにコード整理済み
 */

if ( ! defined( 'ABSPATH' ) ) exit;


/* =========================================
   ソートボタン(新着順・古い順)
   ※検索結果ページでは非表示
========================================= */
if ( ! is_search() ) : ?>

  <!-- ソートボタン用のスタイル -->
  <style>
    /* ソートボタン全体の配置 */
    .sort-buttons {
      display: flex;
      flex-wrap: wrap;
      gap: 10px;
      margin: 1.5em 0;
      justify-content: center; /* 中央寄せ */
    }

    /* 各ボタンのデザイン */
    .sort-buttons .sort-button {
      background: #f5f5f5;
      border: 2px solid #ddd;
      border-radius: 30px;
      padding: 10px 18px;
      font-size: 15px;
      font-weight: 600;
      color: #333;
      cursor: pointer;
      transition: all 0.25s ease;
      min-width: 110px;   /* ボタン幅を確保してタップしやすく */
      text-align: center;
    }

    /* ホバー時のアニメーション */
    .sort-buttons .sort-button:hover {
      background: #0073aa; /* Cocoon管理画面に近いブルー */
      color: #fff;
      border-color: #0073aa;
      transform: translateY(-2px);
      box-shadow: 0 3px 6px rgba(0,0,0,0.15);
    }

    /* アクティブ状態(クリック後に付与する想定) */
    .sort-buttons .sort-button.active {
      background: #ff6f61; /* コーラル系で強調 */
      border-color: #ff6f61;
      color: #fff;
    }

    /* スマホ対応 */
    @media (max-width: 600px) {
      .sort-buttons {
        gap: 8px;
      }
      .sort-buttons .sort-button {
        flex: 1 1 100px;
        padding: 12px 10px;
        font-size: 14px;
      }
    }
  </style>

  <!-- ソートボタン本体 -->
  <div class="sort-buttons">
    <button class="sort-button" data-sort="new">新着順</button>
    <button class="sort-button" data-sort="old">古い順</button>
    <!-- タイトル順が必要なら以下を有効化 --
    <button class="sort-button" data-sort="title">タイトル順</button>
    -->
  </div>

<?php endif; ?>


<?php
/* =========================================
   カテゴリーアイキャッチ・説明文の表示
========================================= */
$cat_id = get_query_var('cat');
$eye_catch_url = get_the_category_eye_catch_url($cat_id);
$content = get_the_category_content($cat_id);

if ( $eye_catch_url || $content ) : ?>

  <article class="category-content article<?php echo esc_attr(get_additional_entry_content_classes()); ?>">

    <header class="article-header category-header">

      <!-- カテゴリータイトル -->
      <?php cocoon_template_part('tmp/list-title'); ?>

      <?php if ( $eye_catch_url ) :
        $display_none = is_eyecatch_visible() ? '' : ' display-none';
        $caption = get_caption_from_image_url($eye_catch_url);
      ?>

        <div class="eye-catch-wrap<?php echo esc_attr($display_none); ?>">
          <figure class="eye-catch">
            <img src="<?php echo esc_url($eye_catch_url); ?>" 
                 class="eye-catch-image wp-category-image"
                 alt="<?php echo esc_attr(get_the_category_title($cat_id)); ?>">

            <?php if ( is_eyecatch_label_visible() && apply_filters('is_eyecatch_category_label_visible', true) ) : ?>
              <span class="cat-label cat-label-<?php echo esc_attr($cat_id); ?>">
                <?php single_cat_title( '', true ); ?>
              </span>
            <?php endif; ?>

            <?php if ( is_eyecatch_caption_visible() && $caption ) : ?>
              <figcaption class="eye-catch-caption">
                <?php echo esc_html($caption); ?>
              </figcaption>
            <?php endif; ?>

          </figure>
        </div>

        <?php do_action('category_eye_catch_after'); ?>

      <?php endif; ?>

      <!-- カテゴリーシェアボタン -->
      <?php cocoon_template_part('tmp/category-sns-share-top'); ?>

      <?php if ( is_large_pr_labels_visible() ) generate_large_pr_label_tag(); ?>

    </header>

    <?php if ( $content ) : ?>
      <div class="category-page-content entry-content">
        <?php echo $content; ?>
      </div>
    <?php endif; ?>

  </article>

<?php else : ?>

  <!-- アイキャッチ・説明が無い場合 -->
  <?php cocoon_template_part('tmp/list-title'); ?>
  <?php cocoon_template_part('tmp/category-sns-share-top'); ?>
  <?php if ( is_large_pr_labels_visible() ) generate_large_pr_label_tag(); ?>

<?php endif; ?>


  

子テーマのディレクトリ構造

  • child-theme/
    • g3/
      • template-parts/
        • main-archive.php
    • tmp/
      • category-content.php
    • archive.php
    • category.php
    • functions.php
    • footer.php
    • header.php
    • style.css
    • js/
      • category-sort.js
    • images/
      • logo.png

JavaScript にコードを追加

ソートボタンをクリックするとページをリロードしてソートを反映します。

ファイル名:category-sort.js
保存先:wp-content/themes/child-theme/js/category-sort.js


document.addEventListener('DOMContentLoaded', function() {
    document.querySelectorAll('.sort-button').forEach(function(btn) {
        btn.addEventListener('click', function() {
            const sort = this.dataset.sort;
            const url = new URL(window.location.href);
            url.searchParams.set('sort', sort);
            window.location.href = url.toString();
        });
    });
});
  

子テーマのディレクトリ構造

  • child-theme/
    • g3/
      • template-parts/
        • main-archive.php
    • tmp/
      • category-content.php
    • archive.php
    • category.php
    • functions.php
    • footer.php
    • header.php
    • style.css
    • js/
      • category-sort.js
    • images/
      • logo.png

汎用CSS


.sort-buttons {
    margin: 20px 0;
    text-align: center;
}

.sort-button {
    display: inline-block;
    padding: 8px 15px;
    margin: 5px;
    border: 1px solid #0073aa;
    border-radius: 5px;
    background: #f7f7f7;
    color: #0073aa;
    cursor: pointer;
    transition: 0.3s;
    font-size: 14px;
}

.sort-button:hover {
    background: #0073aa;
    color: #fff;
}
  

テーマ別サンプルCSS

Lightning用


.sort-buttons { margin: 20px 0; text-align: center; }

.sort-button {
    display: inline-block;
    padding: 8px 15px;
    margin: 5px;
    border: 1px solid #0073aa;
    border-radius: 5px;
    background: #f7f7f7;
    color: #0073aa;
    cursor: pointer;
    transition: 0.3s;
    font-size: 14px;
    font-weight: bold;
}

.sort-button:hover {
    background: #0073aa;
    color: #fff;
}
  

(例)
カテゴリーページで、ソートできるボタンを作る方法

Cocoon用

CocoonのCSSは、category-content.phpに直書きしてます。

(例)
カテゴリーページで、ソートできるボタンを作る方法

代用プラグイン

コード編集が難しい場合は「Content Views」や「WP Grid Builder」などのプラグインを使って、
カテゴリーページにソート機能を実装することも可能です。

まとめ

カテゴリーページにソートボタンを追加することで、ユーザーが見たい順に記事を並べ替えることができ、回遊率アップやユーザビリティ向上につながります。ぜひ自分のテーマに合わせてカスタマイズしてみてください。