bodyとpostクラスに所属カテゴリのスラッグを付与したい。

だいぶ前に「投稿が所属するカテゴリの先祖や子孫を取得するあれこれ。」という記事を書きましたがそこそこアクセスがあったので、実用レベルでよく使うアレンジも紹介しておきます。functions.phpに入れるだけで動きます。正確には、使用テーマのテンプレートでbody_classとpost_classを使用していれば動きます。

実際の出力例は以下のような感じです。

アーカイブページを表示中の場合

<body class=”archive category category-child category-99 logged-in admin-bar no-customize-support category-ancestor category-parent“>

投稿ページを表示中の場合

<body class=”single single-post postid-999 single-format-standard logged-in admin-bar no-customize-support category-child category-ancestor category-parent taxonomy-term“>

category-childが表示中のカテゴリだとすると、category-ancestor(先祖カテゴリ)やcategory-parent(親カテゴリ)も付与してくれるのがミソです。すべてのタクソノミに対応するようにしています。cssによるカスタマイズがしやすくなるのではないでしょうか。もちろんカスタムタクソノミにも対応です。

※ちなみに以下の関数はpage slugにも対応していますが、不要な場合は削除してください。すでに同じ機能の関数を設置している場合はそっちを削除するか、こっちに変更を加えてください。

CODE


/////////////////////// 投稿及びカテゴリページで所属カテゴリ・親カテゴリクラスを付与 ///////////////////////

function add_term_name_to_body_and_post_class( $classes ) {

if ( is_admin() ) return $classes; //管理画面を除く

if ( is_singular() ){ //シングル投稿タイプ

global $post;
$capability = get_post_type_object( $post->post_type )->capability_type;

if ( $capability == 'page' ){ // 固定ページ及びカスタム固定ページ // ページスラッグ付与が不要なら以下の分岐を削除

  $classes[] = $post->post_type.'-' . $post->post_name;
  if ($post->post_parent) $classes[] = $post->post_type.'-' . get_page_uri($post->post_parent) . '-child';

} elseif ( $capability == 'post' ){ // 投稿及びカスタム投稿タイプ

  $taxes = get_object_taxonomies( $post->post_type, 'names' );
  if ($taxes) : unset( $taxes['post_format'] );
  foreach ( $taxes as $taxname ) :
    $tax = get_taxonomy( $taxname );
    if ( !$tax || !$tax->hierarchical ) continue;
    $terms = get_the_terms( $post->ID, $taxname );
    if ( $terms ): foreach ( $terms as $term ) :
      $classes[] = $taxname. '-' .$term->slug;
      $parent = get_term_parent_slug_by_slug( $term->slug, $taxname );
      while( $parent ){ //loop
        $classes[] = $taxname. '-' .$parent;
        $parent = get_term_parent_slug_by_slug( $parent, $taxname );
      }
    endforeach; endif;
  endforeach; endif;

}

} elseif ( is_archive() ) {

  $term_slug = $taxname = '';
  if ( get_query_var( 'category_name' ) ){

    $term_slug = get_query_var( 'category_name' );
    $taxname = 'category';

  } elseif ( get_query_var( 'taxonomy' ) && get_query_var( 'term' ) ) {

    $term_slug = get_query_var( 'term' );
    $taxname = get_query_var( 'taxonomy' );

  }

  if ( $term_slug && $taxname ){

    $parent = get_term_parent_slug_by_slug( $term_slug, $taxname );
    while( $parent ){ //loop
    $classes[] = $taxname. '-' .$parent;
    $parent = get_term_parent_slug_by_slug( $parent, $taxname );
  }

}

}
return $classes;

}
add_filter( 'post_class', 'add_term_name_to_body_and_post_class' );
add_filter( 'body_class', 'add_term_name_to_body_and_post_class' );

 

画像を背景指定せずにCSSだけで正方形に切り抜く。

CMS案件だと、必然的に縦横比が異なる画像を扱うことが多い。wordpressの場合サムネイルがあるからあまり必要ないのだが、レスポンシブデザインで中サイズの画像を無理やり四角く切り抜きたいことがある。WP4.4からのsrcsetの画像切り替えも普通は比率が異なるものには適用されない。必要とする条件はこんな感じか。

・画像のサイズは不明
・縦横比はバラバラ
・背景画像に指定できない
・htmlはなるべく自然に

他所を調べてみてみると、これがまたいろんなやり方のバリエーションがあって面白いのだが、意外にもこれらの前提をクリアする選択肢がない印象。画像のサイズがわからないとダメだったり、画像の向きが指定できないとダメだったりする。(これとか、これとか)

その中で目からウロコだったのはline-heightとtext-alignを使用した方法で、完璧なセンタリングが可能になっている。でも画像をラップする要素が増えるので、ケースによっては使いづらそうだ。

で、今日打ち合わせの帰り道、ふと思いついたので、やってみたのが以下。シンプルな作りになったのでそれなりに使い出があるかも。

 

写真をdivの中央からカバーするサイズで配置する。

まずは写真の一般的な比率3:2を前提して考えてみる。
横向きの画像を中央で正方形にくりぬこうとすると、こんな感じになる。

crop_1

画像を中央に配置するには中央の正方形のDIVにoverflow:hiddenとposition:relativeを与えて、そこから外に対してtop,left,right,bottomを絶対指定し、画像のマージンをautoにする。こんな感じ。

crop_2

写真をdivに対して中央いっぱいに配置できればあとはoverflow:hiddenでクロップするだけ。

div { 
  width:160px;
  height:160px;
  overflow:hidden;
  position:relative;
}
div img { 
  max-width:140%;
  min-width:100%;
  width:auto;
  min-height:100%;
  max-height:140%;
  height:auto;
  position:absolute;
  top:-40%;
  right:-40%;
  bottom:-40%;
  left:-40%;
  margin:auto;
}

本当は上の説明通りmax幅は133.3333%ですが、表記の簡便さと余裕をみて140%にしてあります。マイナスポジションは50%とかある程度大きければナンボでもいいです。ここではなんとなく-40%。divの幅をパーセンテージ指定したい場合は、heightをautoにして、before要素を設定してwidth:100%とpadding-top:100%を指定してくださいね。

DEMO

実際にやってみるとこうなります。

crop_item1

crop_item2

縦画像だとこんな感じになります。ついでにradiusも効かせてみるともっとリアルになります。ついでにあり得るケースとしてクロップする正方形は元画像よりも大きくしてみました。(画像の横幅は200pxに対してdivは240px。)

crop_item2

crop_item2

上手く引き延ばされていますね。chromeとfirefoxとsafariでは。・・・件のブラウザは確かめてません。嫌な予感しかしませんね。
残念ながら、元画像が正方形の場合、無駄に大きく余白を取る形でクロップされてしまいます。まあ、応急処置的なcssということですね。

crop_item2

crop_item2
拙ウェブサイト内の画像をつかった装飾箇所をcss3とかwebfontとかに置き換えていたところ、表題の件に行き当たりました。今更画像を使うのも嫌なので擬似的な手段ですがcssで処理。ボーダーを引きたい要素に直接ボーダーを充ててもよいのですが、そうするとその要素のposition:relativeの位置がボーダーの内側になりますので、そのぶん修正が必要になります。親要素にrelativeを指定して、before疑似要素でボーダーを引き、その上にafter疑似要素で背景色と同じグラデーションを載せています。

 

参考にここで充てているCSSをそのまま書いておきます。

/*左横線*/
.bordered-left { 
    padding:0 0 0 40px;
    position:relative; 
    background:#fff
}
.bordered-left:before, .bordered-left:after {
    position:absolute; 
    left:0; 
    top:0; 
    bottom:0; 
    display:block; 
    content:' '; 
    width:2px;
}
.bordered-left:before { 
    border-left:2px dotted #000; 
}
.bordered-left:after { 
    background:-webkit-linear-gradient( top, white, rgba(255, 255, 255, 0)); 
    background:linear-gradient( to bottom, white, rgba(255, 255, 255, 0));
}

/*下線*/
.bordered-bottom { 
    padding:0 0 20px;
    position:relative; 
    background:#fff
}
.bordered-bottom:before, .bordered-bottom:after {
    position:absolute; 
    left:0; 
    right:0; 
    bottom:0; 
    display:block; 
    content:' '; 
    height:1px;
}
.bordered-bottom:before { 
    border-bottom:1px dashed #000; 
}
.bordered-bottom:after { 
    background:-webkit-linear-gradient( left, white, rgba(255, 255, 255, 0)); 
    background:linear-gradient( to right, white, rgba(255, 255, 255, 0));
}

IEでもフィルターかければ実現できると思うのですが、グラデーション系の設定は面倒くさかった記憶があるので無視する方向で。