レイアウトのチューニングは時間がかかる。でも見た目のインパクトは小さくて少し悲しい・・・。
前回は、WordPress のテーマ Twenty Fourteen の子クラス Twenty Fourteen Child(2014 Child)の作成例のうち、レイアウトの概要とテンプレートについて説明した。今回は functions.php や CSS などのコード類について説明する。今回の作成例が一つのテストということもあって、CSS 以外のコードはあえて複雑にしている部分があるので、その点をあらかじめ頭の片隅に入れておいて頂きたい。
- 1. Twenty Fourteen Child のレイアウトとテンプレート(前の記事)
- 2. Twenty Fourteen Child の CSS と java script
- 1)functions.php
- 2)CSS
- 3)java script
- 4)おわりに
2. Twenty Fourteen Child の CSS と java script
1)functions.php
2014 Child の functions.php は子テーマにしては中身が多い。
「ここでなければできない(ランク AA)」処理と「ここでやるべき(ランク A)」処理、それに「無理してここでやらなくても良い(ランク C)」処理が入り混じっているからだ。実のところ処理として必須なのは CSS の登録だけで、他はテストの一環だと思って頂きたい。
functions.php の全コード:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
<?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 全コード
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 |
/** * 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 はほとんど下の参考リンクから頂いたものなので、詳細はそちらを参考にして頂きたい。
参考リンク:【Design Spice】レスポンシブWebデザインでテーブルを使う時の小技
- custom-style.css 全コード
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
.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 は制限なしのバージョンだ。これらは元々一つのイベントハンドラだったが、今はあえて二つに分割してある。私にはその方がデバッグしやすかったからだ。
- 全ソースコード
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
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 を設定しない場合は、それらの計算部分は不要になる。
私は 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 を作ったのではなくて、子テーマ作成の敷居(しきい)が想像していたよりもずっと低かったので、次のステップを踏み出す気になれたということだ。
そして既存のテンプレートをカスタマイズして、それを固定ページと投稿記事に適用することも、想像していたよりずっと簡単だった。本当はこの記事でそのことをお伝えしたかったのだが、自分のための備忘録を兼ねて書いているので、そういう雰囲気はうまく書き切れなかったように思う。
話が少し長くなったが、この記事を終えるにあたり、上の二点はだけはどうしても強調しておきたかった。