Twenty Fourteen の子テーマ作成例【右サイドバー仕様の 2 カラムレイアウト】- CSS、functions.php および java script 編

レイアウトのチューニングは時間がかかる。でも見た目のインパクトは小さくて少し悲しい・・・。

前回は、WordPress のテーマ Twenty Fourteen の子クラス Twenty Fourteen Child(2014 Child)の作成例のうち、レイアウトの概要とテンプレートについて説明した。今回は functions.php や CSS などのコード類について説明する。今回の作成例が一つのテストということもあって、CSS 以外のコードはあえて複雑にしている部分があるので、その点をあらかじめ頭の片隅に入れておいて頂きたい。

スポンサーリンク

2. Twenty Fourteen Child の CSS と java script

1)functions.php

2014 Child の functions.php は子テーマにしては中身が多い。
「ここでなければできない(ランク AA)」処理と「ここでやるべき(ランク A)処理、それに「無理してここでやらなくても良い(ランク C)」処理が入り混じっているからだ。実のところ処理として必須なのは CSS の登録だけで、他はテストの一環だと思って頂きたい。

functions.php の全コード:

<?php
/**
 * Twenty Fourteen Child functions
 * Based on WordPress Twenty Fourteen
 */

// 親テーマ Twenty Fourteen の style.css と自作のスタイルシートを登録。
function theme_enqueue_styles() {
    
    $stylesheet_Dir = get_stylesheet_directory_uri(); 
    // Twenty Fourteen の style.css      
	wp_enqueue_style( 'twentyfourteen-style', get_template_directory_uri() . 
		'/style.css', array( 'twentyfourteen-lato','genericons' ), null );    
    
    if( is_page_template( 'page-templates/full-width.php' ) || 
    	is_page_template( 'single_full-width.php' ) ) {
		
		// 2 カラムレイアウト表示用の CSS					
		wp_enqueue_style( 'fullwidth-custom-style', $stylesheet_Dir. 
			'/css/fullwidth-custom-style.css', 
			array( 'twentyfourteen-lato', 'genericons', 
			'twentyfourteen-style' ), null );
		
		// table 表示用の CSS 
		wp_enqueue_style( 'custom-style', $stylesheet_Dir. 
			'/css/custom-style.css', array( 'twentyfourteen-lato', 'genericons', 
			'twentyfourteen-style', 
			'fullwidth-custom-style' ), null );
		
		// ポジション固定ヘッダーの width 調整用スクリプト	
	    wp_enqueue_script( 'masthead-resize-script', $stylesheet_Dir. 
	    	'/js/masthead-resize.js', array(), null );
	    
	} 
}
// 関数をアクションフックに登録する。
add_action( 'wp_enqueue_scripts', 'theme_enqueue_styles' );

// body にクラスを追加登録する。
function child_fullwidth_class_name( $regClassNames ) {
	
	// テンプレートがロードされていれば新しいクラスセレクタを追加する。	
	if( is_page_template( 'page-templates/full-width.php' ) || 
		is_page_template( 'single_full-width.php' ) ) {
		// 追加セレクタは 1 個なので次のようにして追加する。
		$regClassNames[] = 'child-full-width';	
	} 
	return $regClassNames;
}

// 関数をフィルターフックに登録する。
add_filter( 'body_class', 'child_fullwidth_class_name' );

// 固定ページでは sidebar-1 内の「最近のコメント」を削除する。
// インデックスはこのテーマを適用するサイトの実際の値を入れる。
function disable_sidebar_widget( $regWidgets )
{
	if( is_page() ) {
		wp_unregister_sidebar_widget('recent-comments-2');
		// full-width.php 適用時には sidebar-1(secondary)内のアーカイブを削除する。
		// インデックスはこのテーマを適用するサイトの実際の値を入れる。
		if( is_page_template( 'page-templates/full-width.php' ) ) {
			wp_unregister_sidebar_widget( 'archives-2' );
		} 
	}  
	return $regWidgets;
}
// 関数をフィルターフックに登録する。
add_filter( 'sidebars_widgets', 'disable_sidebar_widget' );

関数の役割:

2014 Child の functions.php の各関数の役割は次の通りだ。

関数名 役割り ランク 処理の重要度
theme_enqueue_styles CSS  ファイルと java script ファイルを登録する。 A
child_fullwidth_class_name body のclass 属性にクラスセレクタを登録する。 C
disable_sidebar_widget 固定ページ表示時にウィジェットを削除する。 AA

style.css の登録は子テーマとして必須で、fullwidth-custom-style.css の登録は 2014 Child として必須だ。
body の class 属性へのクラスセレクタ登録は、header.php の 33 行目を  <body <?php body_class(‘child-full-width’); ?>> と書き換えて登録する方が簡単だ。

条件分岐(参考):

is_page_template、is_page などの条件分岐タグを functions.php の中で直接使うことはできない
必ずユーザー関数の中に記入して、アクションフックやフィルターフックの中で有効にする必要がある。

  • theme_enqueue_styles の条件分岐の意味

CSS、スクリプトなどの登録内容を、現在の投稿/固定ページが使用するテンプレートの種類で切り替えるテストとして使っている。CSS については、通常レイアウトでページを表示した時に style.css と fullwidth-custom-style.css が同居するのを回避している

  • child_fullwidth_class_name の条件分岐の意味

body 要素へクラスセレクタを登録するテストとして使っている。
これは、2 カラムレイアウトで表示した時に 、style.css と fullwidth-custom-style.css が競合(コンフリクト)するのを防止するための処理だ。詳細は CSS のところで説明する。

ウィジェットの登録/削除処理(参考):

一度ウィジェットを登録した後で、別途ウィジェットの登録/削除を実行することはできない。
登録/削除を実行するためには、処理を functions.php の中で sidebars_widgets フィルターに事前登録しておく必要がある。

これはウィジェット登録/削除のテストだ。2014 Child では固定ページ表示時にコメントとアーカイブのウィジェットを削除している。

recent-comments-2 、archives-2 などのインデックスは私のプロジェクトに固有の値なので、他のプロジェクトでこのコードをテストする場合は、サイト上に表示される実際の値 ―― つまり content-sidebar 内の該当する aside の ID を指定する必要がある。【検証】や他のブラウザの開発ツールを使えば簡単に調べられるが、素(す)のソースコードだとちょっと大変かも知れない。

2)CSS目次へ戻る

styles.css:

2014 Child の style.css は次のようなコメントだけで成り立っている。
必須項目は Theme Name と Template だけだが、オープンライセンスの部分は親テーマの内容を全部残してある。

/*
Theme Name: Twenty Fourteen Child
Theme URI: https://ys.moon-sky.net/themes/twentyfourteen-child/
Author: Bonkure
Author URI: https://ys.moon-sky.net/
Template: twentyfourteen
License: GNU General Public License v2 or later
License URI: http://www.gnu.org/licenses/gpl-2.0.html
This theme is licensed under the GPL.
*/

 

fullwidth-custom-style.css:

これは 2 カラム右サイドバー仕様のレイアウトを実現する CSS だ(以下 fullwidth CSS)。
このレイアウトを PC で見ると、記事表示部分(entory-content)の width が padding 込みで 907px、右サイドバー(content-sidebar)が、やはり padding 込みで 353px で表示されるはずだ(ズーム率 100% )。

  • fullwidth-custom-style.css 全コード
/**
 * Twenty Fourteen Child CSS
 * Based on WordPress Twenty Fourteen Styles
 */

.child-full-width {
	background-color: #f5f5f5;
}

.child-full-width .site {
	max-width:1260px;
}

/*	デフォルトでは secondary 配置用のスペースを確保している。	
 *	182px(min-width: 1008px)、222px(min-width: 1080px)	*/
.child-full-width .site:before {
	width: 0px;
}

/*	ズーム 125% 時の 1px の空白をキャンセルする。	
	この現象は Chrome のみに発生する。	*/
.child-full-width #site-header img {
	vertical-align: bottom;
}

.child-full-width .site-header {
	max-width: 1260px;
	width: inherit;
	background-color: transparent;
}	

.child-full-width .header-main {
	background-color: #000000;
}

/*	header 関連終わり。	*/

.child-full-width .site-content .entry-header,
.child-full-width .site-content .entry-content,
.child-full-width .site-content .entry-summary,
.child-full-width .site-content .entry-meta,
.child-full-width .page-content {
	margin: 0 auto;
	max-width: 900px;
	line-height:1.64;
}

.child-full-width .hentry {
	max-width: 100%;
}

.child-full-width .content-area {
	padding-top: 64px;
	padding-left: 0;
	padding-right: 0;
	margin: 0;
}

.child-full-width .content-sidebar {
	padding-top: 64px;
	width: 100%;
	margin: 0 10px;
}

/*	Media Queries	*/
@media screen and (min-width: 673px) {

    .child-full-width .site-content {
    	margin-right: 0;
    }

    .child-full-width .content-sidebar {			
			margin: 0 auto;
    }
}

@media screen and (min-width: 710px) {
	
	.child-full-width .site {		
		margin: 10px;
	}	

	.child-full-width #site-header {
		margin-left: 10px;
		margin-right: 10px;
	}
	
	.child-full-width .site-header {
		margin: 0 10px;
	}			
}

@media screen and (min-width: 783px) {
	
	.child-full-width .site {		
		margin: 20px;
	}	

	.child-full-width #site-header {
		margin-left: 20px;
		margin-right: 20px;
	}
	
	.child-full-width .site-header {
		margin: 0 20px;
	}		
}

@media screen and (min-width: 910px) {
	
	.full-width .main-content {
		float: left;
	}
   
	.child-full-width .site-content {
		margin-right: 33%;
		margin-left: 0;      
	}  

	.child-full-width .content-sidebar	 {
		margin-left: -33%;
		width: 33%;
		float:right;
	}	
}

@media screen and (min-width: 1008px) {
   
	.child-full-width .site-content {
	    margin-right: 31%;
	    margin-left: 0;
	}   

	.child-full-width .content-sidebar {
		margin-left: -31%;
		width: 31%;
	}

	.search-box-wrapper,
	.featured-content {
		padding-left: 0;
	}
}

@media screen and (min-width: 1080px) {
	
	.child-full-width .site-content {
		margin-right: 28%;
		margin-left: 0;
	}
	
	.child-full-width .content-sidebar {
		margin-left: -28%;
		width: 28%;
	}
	
	.child-full-width .site {		
		margin: 30px;
	}

	.child-full-width #site-header {
		margin-left: 30px;
		margin-right: 30px;
	}	
	
	.child-full-width .site-header {
		margin: 0 30px;
	}			
}
  • 2 カラムレイアウトを実現するクラス型スタイル(クラス)と :before 疑似要素型スタイルの設定

下の表で Child 設定値が 0(ゼロ)に変更されている部分が、キャンセルされた左サイドバー表示領域だ。
スタート用テンプレートの single_full-width.php と full-width.php では、この領域に配置されるコンテナ要素 secondary そのものが削除されているので、これでレイアウトが完全な 2 カラムになる。

セレクタ property  既定値 Child 設定値
.site:before 16 width 182-222px 0
.search-box-wrapper 136 padding-left 182-222 px 0
 .site-content 113 margin-left 182-222 px 0
 .site-content 112 margin-right 29.047-33.33%:Val1 28-33%:Val2
 .content-sidebar 118 width Val1 Val2
 .content-sidebar 117 margin-left Val1(※) Val2

Val はマイナス値のマージン。

  • その他の修正

次にその他の修正を挙げる。
Chrome のデベロッパーツール【検証】でこれを変更しても、通常の表示では違いが見えない部分なので、コードを見ただけでは何のために入っているのか分りづらい部分だ。プロパティ値はコード例で確認して頂きたい。

セレクタ property 修正理由
#site-header img 23 vertical-align ズーム率 125% で発生する 1px の空白補正
.site-header 28 width java script による width 補正前の初期値
.main-content 108 float Media Queries の条件変更による修正(固定ページのみ)
  • fullwidth CSS の適用範囲(スコープ)を制限する

スコープを制限する目的:

  • (1)fullwidth CSS の中でオーバーライドされたデフォルトスタイルのプロパティを、他の CSS に継承させない。
  • (2)fullwidth CSS の作成および改編を容易にする。

最初のが当初の目的だ。
2014 Child のダウンロード用サンプルを作ると決めた時に、最初に思い浮かんだのがこれ。CSS の登録順で他の CSS に影響を与えるようなものは作れないということだ。

下のは後付けの理屈だ。
スコープを制限したら実際に作成スピードと精度が上がったので、付け加えることにした。

スコープを制限する方法:

  • (1)2 カラムレイアウト用テンプレートを使用する時に、body 要素の class 属性に.child-full-width クラス型スタイル(以下「クラス」)を設定する。
  • (2)fullwidth CSS の中で、すべてのクラスをこの .child-full-width の下位クラスに指定する(ID 型スタイル #site-header  も含む)。

最初の手順は functions.php の中で実施している。
functions.php では fullwidth CSS の登録制御も実施しているので、同じ目的の処理が重なっていることが分かる。だからテストなのだ。

次の手順は fullwidth CSS で行っている。
セレクタが【.child-full-width セレクタ】となっている部分がそうだ。ほとんどすべてのクラスがそうなっているが、.main-content のみ .full-width の下位クラスになっている。

custom-style.css:

これは table 要素の overflow 分をスクロールする CSS だ。
2 カラムレイアウトとは直接関係はないが、4 列以上のテーブルを iPhone エミュレータで表示した時の表示がかんばしくないので、とりあえずその対策の一つとして入れておいた。

この CSS を利用するためには table 要素の中に thead 要素を置く必要がある。
table 開始タグの直下に thead 要素を置き、tbody の先頭の tr 要素を丸ごと切り取ってその中に配置すれば良い。それで列見出しが全部 thead の中に配置される。

この CSS はほとんど下の参考リンクから頂いたものなので、詳細はそちらを参考にして頂きたい。

  • custom-style.css 全コード
.entry-content table {
	font-size: 15px;
}

.table, .table-2nd {	
	border: solid 1px gray;
	border-radius: 3px;
}

thead{
	background-color: #f2f2ee;
}

@media only screen and (max-width: 490px) {
	
	/*	table-layout の設定がないと tbody が site-content の幅を超えて
	 *	はみだす。*/
	.table {
		width: 100%;
		table-layout: fixed;
		border-radius: unset;
	}	
	
	.table thead{
		display: block;
		float: left;
	}	
 
	.table tbody{
		display: block;		
		overflow-x: scroll;
		white-space: nowrap;
	}
	
	.table tr{
		display: inline-block;
		vertical-align: top;
	}
	
	.table th, .table td{
		display: block;
	}
	    
    .table::after{ 
    	content:"";     
        clear: both;
        height: 0;
    }
    
    .table-2nd {
		border-radius: unset;
	}
 }

3)java script目次へ戻る

これは、スクロールダウン時に固定位置で表示(position:fixed)されるマスタヘッダー(masthead)の width を調整するための、java script のイベントハンドラだ。
DOMContentLoaded イベントと resize イベントに同じイベントハンドラを指定しているので、分かり易いと言えばそうなのだが、少しイレギュラーな構成かも知れない。

イベントハンドラ:

イベントハンドラ width 基準要素 ヘッダー画像
reSizeMastHead site-header
reSizeMastHead_2nd page

reSizeMastHead はヘッダーに画像がある場合のみ有効なイベントハンドラで、reSizeMastHead_2nd は制限なしのバージョンだ。これらは元々一つのイベントハンドラだったが、今はあえて二つに分割してある。私にはその方がデバッグしやすかったからだ。

  • 全ソースコード
window.onresize = function() {
	reSizeMastHead();
}

window.addEventListener("DOMContentLoaded", function() {
	reSizeMastHead();
});

function reSizeMastHead() {
    
	var	elemReference = document.getElementById( 'site-header' );
	
	if( elemReference == null ) {	
		reSizeMastHead_2nd();
		return; 
	}
	
	var	elemTarget = document.getElementById( 'masthead' );
	var referenceWidth = elemReference.getBoundingClientRect().width.toFixed(3);  
	/*	ターゲット要素の width を設定する。	*/									
	elemTarget.style.width = referenceWidth + 'px';    
}

function reSizeMastHead_2nd() {
    
	/*	基準(reference)の要素とターゲット要素を取得する。	*/
	var	elemReference = document.getElementById( 'page' );
	var	elemTarget = document.getElementById( 'masthead' );	
	
	/*	基準要素の style のプロパティを取得する。	*/
	var referStyle = window.getComputedStyle( elemReference, null );
	
	/*	getComputedStyle が値を返さない場合は処理を中止する。
	 *	firefox と Edge、および IE Ver11 は正常動作を確認した。	*/
	if ( referStyle == null ) {		
		elemTarget.style.width = '100%';
		return;
	}
	
	/*	ターゲット要素の style のプロパティを取得する。	*/
	var targetStyle = window.getComputedStyle( elemTarget, null );
	
	/*	基準値となる width を小数点以下 3 桁まで取得する。	
	 *	getBoundingClientRect().width を使用した時とほぼ同じ値
	 *	が返される。parseFloat に注意!!	*/	
	var referenceWidth = parseFloat( referStyle.width ).toFixed(3);
	
	/*	reference の padding を取得する。	*/	
	var _paddingRight = parseInt( referStyle.paddingRight );
	var _paddingLeft = parseInt( referStyle.paddingLeft );

	/*	基準値の width から padding を差し引く。	*/
	referenceWidth = referenceWidth - _paddingLeft - _paddingRight;
	    
	/*	ターゲット要素の margin の処理。今は padding を考慮しない。	*/
	var _marginRight = parseInt( targetStyle.marginRight );
	var _marginLeft = parseInt( targetStyle.marginLeft );
	
	/*	margin を考慮したターゲット要素の width を設定する。	*/
	elemTarget.style.width = referenceWidth - _marginLeft - _marginRight + 'px';
}

2nd の処理が多いのは、基準要素 page の左右の padding と、ターゲット要素 masthead の 左右の margin の設定を補正するためだ(※1)。padding や margin を設定しない場合は、それらの計算部分は不要になる。

Chrome のデベロッパーツール【検証】で masthead の左右の margin を設定すると、left が設定値分だけずれて表示される。これは、何らかのかたちで resize イベントを発生させると、正常位置に戻ってくれる。

私は jQuery のことは何も知らないので、ここではそのことには触れない。

また、【検証】で java script をデバッグするのも初めてだったので、あまり分かったようなことも言えない。いま言えるのは、変数や制御コードを追加 / 削除しながらスクリプトをデバッグするのは大変だったが、とりあえず何とかすることはできた(※2) ―― ということだけだ。
これについては、きちんとオーソライズされた方法を見つけたら、何かを書くことがあるかも知れない。

  • ※1)masthead に左右の margin を設定する場合は、site-header も同じだけ margin を設定する必要がある。
  • ※2)Event listeners タブの resize イベントから msthead-resize.js を削除する。js ファイルの中身を全部コピーして、Chrome の【検証】の Console に貼りつけ Return キーを押す ―― というようなことをやってみた。

おわりに:目次へ戻る

日常的にキーボードに向かっていればそれほど気にならないテーマの更新も、長期間ブログを休んでいた時にはかなり億劫(おっくう)に感じられ、つい実行が遅れがちになってしまった。

ファイルの書き換えやコピペで更新を乗り切る、というアドホックなやり方には少し嫌気がさしていたので、もっと楽な ―― というか筋道の通った方法を探したら、WordPress の Codex 日本語版で次のような子テーマの説明を見つけた。

Codex 日本語版「子テーマ」より引用:

  • テーマを直接変更した場合、そのテーマがアップデートされると変更が失われるかもしれません。子テーマを使用すればテーマの変更は確実に保持されます。
  • 子テーマを使用することで開発時間を短縮できます。
  • 子テーマの使用することでWordPressのテーマの開発を良い形で学べます。

これに励まされて、その時使っていたテーマ anjirai に変更・追加ファイルを移動したら、確かにテーマの更新がとても楽になった。今頃何言ってんだ?・・・と呆れられそうだが、私が子テーマ関連のドキュメントを真面目に読んだのは、実はこれが初めてという情けなさなのだ。

その余勢を駆って、テンプレート込みの新しい子テーマ 2014 Child を作ってみたワケだ。
自作テンプレートを使いたくて 2014 Child を作ったのではなくて、子テーマ作成の敷居(しきい)が想像していたよりもずっと低かったので、次のステップを踏み出す気になれたということだ。

そして既存のテンプレートをカスタマイズして、それを固定ページと投稿記事に適用することも、想像していたよりずっと簡単だった。本当はこの記事でそのことをお伝えしたかったのだが、自分のための備忘録を兼ねて書いているので、そういう雰囲気はうまく書き切れなかったように思う。
話が少し長くなったが、この記事を終えるにあたり、上の二点はだけはどうしても強調しておきたかった。

スポンサーリンク

スポンサーリンク

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です