WordPressのページナビ(ページャー)は、なんと言ってもWP-PageNaviが有名ですが、もっとシンプルでコントローラブルなものが出来ないかと思い自分で作ってみました。

出力されるHTMLのソースを見てもらえれば分かりますが、CSSのclassの変更がパラメータで出来たり、種類が豊富に指定されるため、多様なデザインをカバーできることも、喜んでもらえる点ではないでしょうか。
[2011.06.30追記]
プラグイン版を公開いたしました。一部機能追加と修正してありますので、こちらをご利用ください。
導入方法
- 使っているテーマのfunctions.phpにCODE 1を追記してください。あるいは、独自プラグインにしてしまってもいいです。(独自プラグインの作り方は、初心者でも10秒でできる WordPress プラグインの作り方やWordPress でスニペットを簡単に管理する方法あたりを参考に)
- テーマファイルのページナビを表示したい位置に
<?php page_navi(); ?>を追加してください。
これだけでも一応は、ページナビが表示されるようになりますが、いくつかのパラメータで表示方法を変更することができます。
指定可能なパラメータ
- items
- 表示する前後ナビゲーションの数。現状表示しているページを含むため、前後の表示数を揃えたい場合は奇数を指定してください。デフォルトは11
- show_adjacent
- 前後ページへのリンクを表示するかどうか。デフォルトはtrue(表示)
- prev_label
- 前ページリンクのリンクテキスト。デフォルトは、<(<)
- next_label
- 次ページリンクのリンクテキスト。デフォルトは、>(>)
- show_boundary
- 最初と最後のページへのリンクを表示するかどうか。デフォルトはtrue(表示)
- first_label
- 最初のページへのリンクテキスト。デフォルトは«(«)
- last_label
- 最後のページへのリンクテキスト。デフォルトは»(»)
- show_num
- 現ページナンバーと全ページ数の表示をするかどうか。デフォルトはfalse(非表示)
- num_position
- 現ページナンバーと全ページ数の表示位置。デフォルトはbefore(前)。後に表示したい場合はafterを指定
- num_format
- 現ページナンバーと全ページ数の表示フォーマット。デフォルトは、<span>%d/%d</span>(nn/mm)
- navi_element
- ページナビのラッパー要素。divかnavを指定可能。デフォルトは空(ラッパー要素なし)
- elm_class
- ラッパー要素、ラッパー要素がない場合は ulのclass属性。デフォルトはpage_navi
- elm_id
- ラッパー要素、ラッパー要素がない場合は ulのid属性。デフォルトは空(id要素なし)
- li_class
- ページナビの全liに付くclass属性。デフォルトは空(classなし)
- current_class
- 現ページのliに指定されるクラス名。デフォルトは current
- current_format
- 現ページの表示フォーマット。デフォルトは <span>%d</span>
- class_prefix
- classの接頭辞。ページナビで出力されるclass全てに追加される。デフォルトは空。(接頭辞なし)
- indent
- タブインデント数。デフォルトは0
- echo
- ページナビの出力を行うかどうか。デフォルトは true(出力する)。false または 0 を指定するとPHPの値として returnする
パラメータ指定サンプル

<?php page_navi( 'items=7&prev_label=前へ&next_label=次へ&first_label=最初&last_label=最後&show_num=1&num_position=after' ); ?>
- ナビ表示数は7
- 前ページのリンクラベルは「前へ」
- 次ページのリンクラベルは「次へ」
- 最初のページのリンクラベルは「最初」
- 最後のページのリンクラベルは「最後」
- ページ数の表示を行い、位置は後
CODE 1
function page_navi( $args = '' ) {
global $wp_query;
if ( ! ( is_archive() || is_home() || is_search() ) ) { return; }
$default = array(
'items' => 11,
'show_adjacent' => true,
'prev_label' => '<',
'next_label' => '>',
'show_boundary' => true,
'first_label' => '«',
'last_label' => '»',
'show_num' => false,
'num_position' => 'before',
'num_format' => '<span>%d/%d</span>',
'echo' => true,
'navi_element' => '',
'elm_class' => 'page_navi',
'elm_id' => '',
'li_class' => '',
'current_class' => 'current',
'current_format' => '<span>%d</span>',
'class_prefix' => '',
'indent' => 0
);
$default = apply_filters( 'page_navi_default', $default );
$args = wp_parse_args( $args, $default );
$max_page_num = $wp_query->max_num_pages;
$current_page_num = get_query_var( 'paged' ) ? get_query_var( 'paged' ) : 1;
$elm = in_array( $args['navi_element'], array( 'nav', 'div', '' ) ) ? $args['navi_element'] : 'div';
$args['items'] = absint( $args['items'] ) ? absint( $args['items'] ) : $default['items'];
$args['elm_id'] = is_array( $args['elm_id'] ) ? $default['elm_id'] : $args['elm_id'];
$args['elm_id'] = preg_replace( '/[^\w_-]+/', '', $args['elm_id'] );
$args['elm_id'] = preg_replace( '/^[\d_-]+/', '', $args['elm_id'] );
$args['class_prefix'] = is_array( $args['class_prefix'] ) ? $default['class_prefix'] : $args['class_prefix'];
$args['class_prefix'] = preg_replace( '/[^\w_-]+/', '', $args['class_prefix'] );
$args['class_prefix'] = preg_replace( '/^[\d_-]+/', '', $args['class_prefix'] );
$args['elm_class'] = sanitize_attr_classes( $args['elm_class'], $args['class_prefix'] );
$args['li_class'] = sanitize_attr_classes( $args['li_class'], $args['class_prefix'] );
$args['current_class'] = sanitize_attr_classes( $args['current_class'], $args['class_prefix'] );
$args['current_class'] = $args['current_class'] ? $args['current_class'] : $default['current_class'];
$tabs = str_repeat( "\t", (int)$args['indent'] );
$elm_tabs = '';
$befores = $current_page_num - floor( ( $args['items'] - 1 ) / 2 );
$afters = $current_page_num + ceil( ( $args['items'] - 1 ) / 2 );
if ( $max_page_num <= $args['items'] ) {
$start = 1;
$end = $max_page_num;
} elseif ( $befores <= 1 ) {
$start = 1;
$end = $args['items'];
} elseif ( $afters >= $max_page_num ) {
$start = $max_page_num - $args['items'] + 1;
$end = $max_page_num;
} else {
$start = $befores;
$end = $afters;
}
$elm_attrs = '';
if ( $args['elm_id'] ) {
$elm_attrs = ' id="' . $args['elm_id'] . '"';
}
if ( $args['elm_class'] ) {
$elm_attrs .= ' class="' . $args['elm_class'] . '"';
}
$num_list_item = '';
if ( $args['show_num'] ) {
$num_list_item = '<li class="page_nums';
if ( $args['li_class'] ) {
$num_list_item .= ' ' . $args['li_class'];
}
$num_list_item .= '">' . sprintf( $args['num_format'], $current_page_num, $max_page_num ) . "</li>\n";
}
$page_navi = '';
if ( $elm ) {
$elm_tabs = "\t";
$page_navi = $tabs . '<' . $elm;
if ( $elm_attrs ) {
$page_navi .= $elm_attrs . ">\n";
}
}
$page_navi .= $elm_tabs . $tabs . '<ul';
if ( ! $elm && $elm_attrs ) {
$page_navi .= $elm_attrs;
}
$page_navi .= ">\n";
if ($args['num_position'] != 'after' && $num_list_item ) {
$page_navi .= "\t" . $elm_tabs . $tabs . $num_list_item;
}
if ( $args['show_boundary'] ) {
$page_navi .= "\t" . $elm_tabs . $tabs . '<li class="' . $args['class_prefix'] . 'first';
if ( $args['li_class'] ) {
$page_navi .= ' ' . $args['li_class'];
}
$page_navi .= '"><a href="' . get_pagenum_link() . '">' . esc_html( $args['first_label'] ) . '</a></li>' . "\n";
}
if ( $args['show_adjacent'] ) {
$previous_num = max( 1, $current_page_num - 1 );
$page_navi .= "\t" . $elm_tabs . $tabs . '<li class="' . $args['class_prefix'] . 'previous';
if ( $args['li_class'] ) {
$page_navi .= ' ' . $args['li_class'];
}
$page_navi .= '"><a href="' . get_pagenum_link( $previous_num ) . '">' . esc_html( $args['prev_label'] ) . '</a></li>' . "\n";
}
for ( $i = $start; $i <= $end; $i++ ) {
$page_navi .= "\t" . $elm_tabs . $tabs . '<li class="';
if ( $i == $current_page_num ) {
$page_navi .= $args['current_class'];
if ( $args['li_class'] ) {
$page_navi .= ' ' . $args['li_class'];
}
$page_navi .= '">' . sprintf( $args['current_format'], $i ) . "</li>\n";
} else {
$delta = absint( $i - $current_page_num );
$b_f = $i < $current_page_num ? 'before' : 'after';
$page_navi .= $args['class_prefix'] . $b_f . ' ' . $args['class_prefix'] . 'delta-' . $delta;
if ( $i == $start ) {
$page_navi .= ' ' . $args['class_prefix'] . 'head';
} elseif ( $i == $end ) {
$page_navi .= ' ' . $args['class_prefix'] . 'tail';
}
if ( $args['li_class'] ) {
$page_navi .= ' ' . $args['li_class'] . '"';
}
$page_navi .= '"><a href="' . get_pagenum_link( $i ) . '">' . $i . "</a></li>\n";
}
}
if ( $args['show_adjacent'] ) {
$next_num = min( $max_page_num, $current_page_num + 1 );
$page_navi .= "\t" . $elm_tabs . $tabs . '<li class="' . $args['class_prefix'] . 'next';
if ( $args['li_class'] ) {
$page_navi .= ' ' . $args['li_class'];
}
$page_navi .= '"><a href="' . get_pagenum_link( $next_num ) . '">' . esc_html( $args['next_label'] ) . '</a></li>' . "\n";
}
if ( $args['show_boundary'] ) {
$page_navi .= "\t" . $elm_tabs . $tabs . '<li class="' . $args['class_prefix'] . 'last';
if ( $args['li_class'] ) {
$page_navi .= ' ' . $args['li_class'];
}
$page_navi .= '"><a href="' . get_pagenum_link( $max_page_num ) . '">' . esc_html( $args['last_label'] ) . '</a></li>' . "\n";
}
if ($args['num_position'] == 'after' && $num_list_item ) {
$page_navi .= "\t" . $elm_tabs . $tabs . $num_list_item;
}
$page_navi .= $elm_tabs . $tabs . "</ul>\n";
if ( $elm ) {
$page_navi .= $tabs . '</' . $elm . ">\n";
}
$page_navi = apply_filters( 'page_navi', $page_navi );
if ( $args['echo'] ) {
echo $page_navi;
} else {
return $page_navi;
}
}
function sanitize_attr_classes( $classes, $prefix = '' ) {
if ( ! is_array( $classes ) ) {
$classes = preg_replace( '/[^\s\w_-]+/', '', $classes );
$classes = preg_split( '/[\s]+/', $classes );
}
foreach ( $classes as $key => $class ) {
if ( is_array( $class ) ) {
unset( $classes[$key] );
} else {
$class = preg_replace( '/[^\w_-]+/', '', $class );
$class = preg_replace( '/^[\d_-]+/', '', $class );
if ( $class ) {
$classes[$key] = $prefix . $class;
}
}
}
$classes = implode( ' ', $classes );
return $classes;
}
ページナビで出力されるHTMLソース
パラメータの指定なしで出力されるHTMLのソース例です。
<ul class="page_navi"> <li class="first"><a href="http://www.example.com/date/2011/04/">«</a></li> <li class="previous"><a href="http://www.example.com/date/2011/04/page/6/"><</a></li> <li class="before delta-5 head"><a href="http://www.example.com/date/2011/04/page/2/">2</a></li> <li class="before delta-4"><a href="http://www.example.com/date/2011/04/page/3/">3</a></li> <li class="before delta-3"><a href="http://www.example.com/date/2011/04/page/4/">4</a></li> <li class="before delta-2"><a href="http://www.example.com/date/2011/04/page/5/">5</a></li> <li class="before delta-1"><a href="http://www.example.com/date/2011/04/page/6/">6</a></li> <li class="current"><span>7</span></li> <li class="after delta-1"><a href="http://www.example.com/date/2011/04/page/8/">8</a></li> <li class="after delta-2"><a href="http://www.example.com/date/2011/04/page/9/">9</a></li> <li class="after delta-3"><a href="http://www.example.com/date/2011/04/page/10/">10</a></li> <li class="after delta-4"><a href="http://www.example.com/date/2011/04/page/11/">11</a></li> <li class="after delta-5 tail"><a href="http://www.example.com/date/2011/04/page/12/">12</a></li> <li class="next"><a href="http://www.example.com/date/2011/04/page/8/">></a></li> <li class="last"><a href="http://www.example.com/date/2011/04/page/13/">»</a></li> </ul>
CSS例
本コードの他に、CSSの指定がないと当然ながらきれいに表示されません。
下記は、とりあえずのCSSサンプルです。あとは、好みのデザインを組み合わせてステキなページナビを作り上げて下さいね。
.page_navi {
text-align: center;
}
.page_navi li {
display: inline;
list-style: none;
}
.page_navi li.current span {
color: #000;
font-weight: bold;
display: inline-block;
padding: 3px 7px;
background: #fee;
border: solid 1px #fcc;
}
.page_navi li a {
color: #333;
padding: 3px 7px;
background: #eee;
display: inline-block;
border: solid 1px #999;
text-decoration: none;
}
.page_navi li a:hover {
color: #f00;
}
.page_navi li.page_nums span {
color: #fff;
padding: 3px 7px;
background: #666;
display: inline-block;
border: solid 1px #333;
}
「パラメータでカスタマイズしやすいWordPressのページナビを作ってみた」への3件のフィードバック