WordPress ギャラリーをカスタマイズしてカラム数を自動調整

ギャラリーのカスタマイズ

ギャラリーの表示カラム数は、1-9まで指定できるようになっていますが、レスポンシブテーマでスマートフォン等で見るとあまりカラム数が多いとギャラリーの画像表示は豆粒のようになってしまいます

そこで、ギャラリーを表示しているデフォルトのコードを元に少し修正を加えて、スマートフォン、タブレット、デスクトップ別に自動的に見やすいようにカラム数を調整して表示するようにしてみました

ステップ1 CSS変更

デフォルトスタイルをブラウザの全幅で表示するとこんな感じです

galleryデフォルト

CSSの変更

デフォルトのギャラリースタイルを使わないようにして、CSSを変更します

Twenty Fourteen のギャラリースタイルがかっけーので、これのギャラリー部分のCSSを使わせていただきます (^^)

font-size と max-height は、ちょっと修正してあります

/**
 * Gallery (Twenty Fourteen)
 */
.gallery {
    margin-bottom: 20px;
}

.gallery-item {
    float: left; 
    margin: 0 4px 4px 0;
    overflow: hidden;
    position: relative;
}

.gallery-columns-1 .gallery-item {
    max-width: 100%;
}

.gallery-columns-2 .gallery-item {
    max-width: 48%;
    max-width: -webkit-calc(50% - 4px);
    max-width:         calc(50% - 4px);
}

.gallery-columns-3 .gallery-item {
    max-width: 32%;
    max-width: -webkit-calc(33.3% - 4px);
    max-width:         calc(33.3% - 4px);
}

.gallery-columns-4 .gallery-item {
    max-width: 23%;
    max-width: -webkit-calc(25% - 4px);
    max-width:         calc(25% - 4px);
}

.gallery-columns-5 .gallery-item {
    max-width: 19%;
    max-width: -webkit-calc(20% - 4px);
    max-width:         calc(20% - 4px);
}

.gallery-columns-6 .gallery-item {
    max-width: 15%;
    max-width: -webkit-calc(16.7% - 4px);
    max-width:         calc(16.7% - 4px);
}

.gallery-columns-7 .gallery-item {
    max-width: 13%;
    max-width: -webkit-calc(14.28% - 4px);
    max-width:         calc(14.28% - 4px);
}

.gallery-columns-8 .gallery-item {
    max-width: 11%;
    max-width: -webkit-calc(12.5% - 4px);
    max-width:         calc(12.5% - 4px);
}

.gallery-columns-9 .gallery-item {
    max-width: 9%;
    max-width: -webkit-calc(11.1% - 4px);
    max-width:         calc(11.1% - 4px);
}

.gallery-columns-1 .gallery-item:nth-of-type(1n),
.gallery-columns-2 .gallery-item:nth-of-type(2n),
.gallery-columns-3 .gallery-item:nth-of-type(3n),
.gallery-columns-4 .gallery-item:nth-of-type(4n),
.gallery-columns-5 .gallery-item:nth-of-type(5n),
.gallery-columns-6 .gallery-item:nth-of-type(6n),
.gallery-columns-7 .gallery-item:nth-of-type(7n),
.gallery-columns-8 .gallery-item:nth-of-type(8n),
.gallery-columns-9 .gallery-item:nth-of-type(9n) {
    margin-right: 0;
}

.gallery-caption {
    background-color: rgba(0, 0, 0, 0.7);
    -webkit-box-sizing: border-box;
    -moz-box-sizing:    border-box;
    box-sizing:         border-box;
    color: #fff;
    /* font-size: 12px; */
    font-size: 80%;
    line-height: 1.5;
    margin: 0;
    max-height: 60%;
    opacity: 0;
    padding: 6px 8px;
    position: absolute;
    bottom: 0;
    left: 0;
    text-align: left;
    width: 100%;
}

.ie7 .gallery-caption,
.ie8 .gallery-caption {
    background: #000;
    filter: alpha(opacity=0);
}

.gallery-caption:before {
    content: "";
    height: 100%;
    min-height: 49px;
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
}

.gallery-item:hover .gallery-caption {
    opacity: 1;
}

.ie7 .gallery-item:hover .gallery-caption,
.ie8 .gallery-item:hover .gallery-caption {
    filter: alpha(opacity=70);
}

.gallery-columns-7 .gallery-caption,
.gallery-columns-8 .gallery-caption,
.gallery-columns-9 .gallery-caption {
    display: none;
}
 デフォルトギャラリースタイルを止める

次に、function.php にデフォルトスタイルを使用しないよう記述します

//デフォルトのギャラリースタイルを止める
add_filter( 'use_default_gallery_style', '__return_false' );

 これだけで、Twenty Fourteen と同じ結構いい感じになります

gallery2014

但し、カラム数が3と設定してあると右に余白が空いてしまいます

ここで単純にカラム数の指定を増やせばこの画面では、きれいに表示させることは出来るのですが、レスポンシブデザインを使用しているとスマートフォンでは、カラム数が多すぎ豆粒のような画像となってしまいます

ステップ2 プログラム変更

自動的にカラム数を調整するには WordPress 内でギャラリーを処理している部分のプログラムを変更する必要があります

WordPress内のコードを直接変更するのはまずいので、フック処理を行います

ギャラリーの処理は、WordPressの wp-includes/media.phpgallery_shortcode($attr) 関数で実行されています

その関数中の apply_filters(‘post_gallery’, ”, $attr) という処理をフックするためのフックポイントが設けてありますので、post_gallery にフックする関数を作成します

今回は、このデフォルトの gallery_shortcode() 関数コードをベースとして、新たに設けるオプションで、元の動作とカラム数を自動調整する動作を選択できるようにします

修正は、gallery_shortcode() 関数をコピーして、前半部にカラム数を自動調整するコードを付け足しただけです

/**
 * ギャラリー表示フォーマット作成
 * 基本的には media.php gallery_shortcode() と同じだが、デバイスにより表示カラム数を自動調整出来るよう追加
 */
function celtisone_gallery_colums($output, $attr) {
    if ( ! empty( $output ) ) // 既に post_gallery がフックされて上書きされていたら実行しない
    return $output;  

    global $celtisone_options;
    global $post;

    static $instance = 0;
    $instance++;

    //自動的にカラム数を調整(デバイス、サイドバーによる)
    if((int)$celtisone_options['gallery-colum'] !== 0){
        $size = (empty($attr['size']))? 'thumbnail' : $attr['size'];
        $opsize = CeltisoneLib::get_thumbnail_optionsetsize($size);
        if($opsize['width'] === 0) 
            $attr['columns'] = 1;
        else {
            if(wp_is_mobile()){
                if(celtisone_is_smartphone()){
                    if($opsize['width'] <= 160) 
                        $attr['columns'] = 3;
                    else if($opsize['width'] < 250) 
                        $attr['columns'] = 2;
                    else
                        $attr['columns'] = 1;
                }
                else {
                    if(!empty($celtisone_options['gallery-sidebar']))
                        $attr['columns'] =  round(780 / $opsize['width']);
                    else
                        $attr['columns'] =  round(520 / $opsize['width']);
                }
            }
            else {
                if(!empty($celtisone_options['gallery-sidebar']))
                    $attr['columns'] =  round(960 / $opsize['width']);
                else
                    $attr['columns'] =  round(620 / $opsize['width']);
            }
            if( $attr['columns'] > 9)
                $attr['columns'] = 9;
            if( $attr['columns'] === 0)
                $attr['columns'] = 1;
        }
    }

    if ( ! empty( $attr['ids'] ) ) {
        // 'ids' is explicitly ordered, unless you specify otherwise.
        if ( empty( $attr['orderby'] ) )
            $attr['orderby'] = 'post__in';
        $attr['include'] = $attr['ids'];
    }

    // We're trusting author input, so let's at least make sure it looks like a valid orderby statement
    if ( isset( $attr['orderby'] ) ) {
        $attr['orderby'] = sanitize_sql_orderby( $attr['orderby'] );
        if ( !$attr['orderby'] )
            unset( $attr['orderby'] );
    }

    extract(shortcode_atts(array(
        'order'      => 'ASC',
        'orderby'    => 'menu_order ID',
        'id'         => $post ? $post->ID : 0,
        'itemtag'    => 'dl',
        'icontag'    => 'dt',
        'captiontag' => 'dd',
        'columns'    => 3,
        'size'       => 'thumbnail',
        'include'    => '',
        'exclude'    => '',
        'link'       => ''
    ), $attr, 'gallery'));

    $id = intval($id);
    if ( 'RAND' == $order )
        $orderby = 'none';

    if ( !empty($include) ) {
        $_attachments = get_posts( array('include' => $include, 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => 'image', 'order' => $order, 'orderby' => $orderby) );

        $attachments = array();
        foreach ( $_attachments as $key => $val ) {
            $attachments[$val->ID] = $_attachments[$key];
        }
    } elseif ( !empty($exclude) ) {
        $attachments = get_children( array('post_parent' => $id, 'exclude' => $exclude, 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => 'image', 'order' => $order, 'orderby' => $orderby) );
    } else {
        $attachments = get_children( array('post_parent' => $id, 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => 'image', 'order' => $order, 'orderby' => $orderby) );
    }

    if ( empty($attachments) )
        return '';

    if ( is_feed() ) {
        $output = "\n";
        foreach ( $attachments as $att_id => $attachment )
            $output .= wp_get_attachment_link($att_id, $size, true) . "\n";
        return $output;
    }

    $itemtag = tag_escape($itemtag);
    $captiontag = tag_escape($captiontag);
    $icontag = tag_escape($icontag);
    $valid_tags = wp_kses_allowed_html( 'post' );
    if ( ! isset( $valid_tags[ $itemtag ] ) )
        $itemtag = 'dl';
    if ( ! isset( $valid_tags[ $captiontag ] ) )
        $captiontag = 'dd';
    if ( ! isset( $valid_tags[ $icontag ] ) )
        $icontag = 'dt';

    $columns = intval($columns);
    $itemwidth = $columns > 0 ? floor(100/$columns) : 100;
    $float = is_rtl() ? 'right' : 'left';

    $selector = "gallery-{$instance}";

    $gallery_style = $gallery_div = '';
    if ( apply_filters( 'use_default_gallery_style', true ) )
        $gallery_style = "
        <style type='text/css'>
            #{$selector} {
                margin: auto;
            }
            #{$selector} .gallery-item {
                float: {$float};
                margin-top: 10px;
                text-align: center;
                width: {$itemwidth}%;
            }
            #{$selector} img {
                border: 2px solid #cfcfcf;
            }
            #{$selector} .gallery-caption {
                margin-left: 0;
            }
            /* see gallery_shortcode() in wp-includes/media.php */
        </style>";
    $size_class = sanitize_html_class( $size );
    $gallery_div = "<div id='$selector' class='gallery galleryid-{$id} gallery-columns-{$columns} gallery-size-{$size_class}'>";
    $output = apply_filters( 'gallery_style', $gallery_style . "\n\t\t" . $gallery_div );

    $i = 0;
    foreach ( $attachments as $id => $attachment ) {
        if ( ! empty( $link ) && 'file' === $link )
            $image_output = wp_get_attachment_link( $id, $size, false, false );
        elseif ( ! empty( $link ) && 'none' === $link )
            $image_output = wp_get_attachment_image( $id, $size, false );
        else
            $image_output = wp_get_attachment_link( $id, $size, true, false );

        $image_meta  = wp_get_attachment_metadata( $id );

        $orientation = '';
        if ( isset( $image_meta['height'], $image_meta['width'] ) )
            $orientation = ( $image_meta['height'] > $image_meta['width'] ) ? 'portrait' : 'landscape';

        $output .= "<{$itemtag} class='gallery-item'>";
        $output .= "
            <{$icontag} class='gallery-icon {$orientation}'>
                $image_output
            </{$icontag}>";
        if ( $captiontag && trim($attachment->post_excerpt) ) {
            $output .= "
                <{$captiontag} class='wp-caption-text gallery-caption'>
                " . wptexturize($attachment->post_excerpt) . "
                </{$captiontag}>";
        }
        $output .= "</{$itemtag}>";
        if ( $columns > 0 && ++$i % $columns == 0 )
            $output .= '<br style="clear: both" />';
    }

    $output .= "
            <br style='clear: both;' />
        </div>\n";

    return $output;
}
//デフォルトのギャラリースタイルを止める
add_filter( 'use_default_gallery_style', '__return_false' );
//post_gallery のフックは jetpack tiled gallery より優先度を下げないと tiled gallery が実行できない
add_filter( 'post_gallery', 'celtisone_gallery_colums', 2000, 2 );
 ポイント1.フック時の優先度に気をつける

導入しているプラグインによっては、既に post_gallery をフックして処理している場合があるので、競合しないよう優先度には気をつけます

JetPack に Tiled ギャラリーという機能があり、使用している方も多いと思いますが、この機能も同様に post_gallery をフックしています

そこで、今回新たに post_gallery をフックするのですが、Tiled ギャラリーは優先度 1000-1002 ぐらいで使用しているので、共存できるように優先度の数値を大きくして 2000 としてあります

優先値の小さいほうが先にフックされるので、処理の先頭で $output が空かどうか確認して、空でなければ既に Tiled ギャラリー等で先にフックされて出力データが作成済みですので、実行しないようにします

これで共存できるようになります

ポイント2.表示エリアとサムネイルサイズ

ギャラリーを表示する幅は、デバイスの違い(スマートフォン、タブレット、デスクトップ)、サイドバー表示の有無によるコンテンツエリア幅等により大きく変化します

また、画像の幅もサムネイル、中、大サイズのどれが指定されているかにより大きく変わります

初めに gallery ショートコードで指定されている画像サイズを取得します

thumbnail / medium / large のいずれかの指定が取得出来るのですが、何も指定されていなければ、 thumbnail サイズで扱います

$size = (empty($attr['size']))? 'thumbnail' : $attr['size'];

次に、このサイズのメディア設定の画像サイズを取得します

get_thumbnail_optionsetsize($size) という部分です

/**
 * サムネイル用に設定されている画像サイズの設定値を取得
 * 
 * $size メディア設定の画像サイズ選択:文字列のみ thumbnail / medium / large / small(my define)
 */
public static function get_thumbnail_optionsetsize($size) {
    global $_wp_additional_image_sizes;

    $opsize = array('width' => 0, 'height' => 0);
    if($size == 'thumb' || $size == 'thumbnail' || $size == 'medium' || $size == 'large'){
        $opsize['width'] = intval(get_option( $size . '_size_w'));
        $opsize['height'] = intval(get_option( $size . '_size_h'));
        $opsize['crop'] = get_option( "{$size}_crop" );
    }
    else if ( !empty( $_wp_additional_image_sizes[$size] ) ) {
        $opsize['width'] = intval( $_wp_additional_image_sizes[$size]['width'] );
        $opsize['height'] = intval( $_wp_additional_image_sizes[$size]['height'] );
        $opsize['crop'] = intval( $_wp_additional_image_sizes[$size]['crop'] );
    }
    return $opsize;
}

取得したのは、指定サイズの幅と高さの上限値ですので、縦長の画像や横長の画像が混在していると正確には計算出来ないのですが、ここでは幅が一定の画像が並んでいることを想定して計算します (^^)

最近は様々な表示エリアのデバイスが増えていますが、簡易的にスマートフォン、タブレット、デスクトップサイズの3種類に分けてカラム数を自動的に決めていきます

一応デバイスの判断は WordPress に wp_is_mobile()という関数があるのですが、スマートフォンとタブレットが区別出来ないので、WordPressでスマホとそれ以外を切り替える方法 を参考にスマートフォンの判断をしています

カラム数の調整判断概要

(1)スマートフォン

  • 画像幅 160 以下 : 3カラム
  • 画像幅 250 未満 : 2カラム
  • 画像幅 250 以上 : 1カラム

smart3column

(2)タブレット

  • サイドバー有り 基準幅 520
  • サイドバー無し 基準幅 780

基準幅を画像幅で割って四捨五入してカラム数計算

※基準幅は、使用しているテーマによりまちまちなので適当に修正して下さい

tablet5column

(2)デスクトップ

  • サイドバー有り 基準幅 620
  • サイドバー無し 基準幅 960

基準幅を画像幅で割って四捨五入してカラム数計算

desktop6column

gallery ショートコードで size=”medium” を指定した場合はこんな感じ

desktop3medium

ちなみに、JetPack Tiled ギャラリーを有効にしてあると表示タイプが選択出来るようになっていますが、サムネイルグリッドタイプの場合の動作となります

ここでは Celtis-one テーマの設定値 $celtisone_options[‘gallery-colum’] で指定カラム数で表示するか、自動的にカラム数を調整するかを切り替えているので、常に自動調整にしたければ、この判断部分を取り除いて下さい

表示例のようにデバイスと画像のサイズからカラム数を自動的に調整して見やすく表示出来ることが確認出来ました (^^)

2014/11/18 追記

この機能は celtis-one テーマ ver1.5 まで実装していましたが、現在はサポートしていません

ギャラリーのカスタマイズの参考プログラムということで記事は残してあります

代わりにギャラリースライダー機能を celtispack プラグインへ実装していますので、こちらも参照してみてください (^^)

WordPress ギャラリーを印象的に見せるレスポンシブスライダー(複数設置対応)プラグイン

 

 


まとめ記事紹介

search star user home refresh tag chevron-left chevron-right exclamation-triangle calendar comment folder thumb-tack navicon angle-double-up angle-double-down angle-up angle-down quote-left googleplus facebook instagram twitter rss