【付録・CSS設計10】設計手法:PRECSSの紹介1【WPテーマ作成】

WordPressテーマ作成

本付録は、メインシリーズであるWordPressのテーマ作成に役立ちそうな情報を補足していくパートだ。

前々回、前回ではBEMを解説した。

かなり色々と厳格に決められている設計手法で、それだけ気を付けることも多い。

今やろうとしているものがどのBEMエンティティを使うべきものか、あるいはMixを使うべきかなどを細かく見ながら進めていくといいだろう。

以下がその記事だ。

さて、今回からまた別の設計手法、PRECSSというものを解説する。

これまで解説した三つの設計手法であるOOCSS、SMACSS、BEMに影響を受けているもので、それらを理解した上で見た方がよりわかりやすいと思う。

それらとの対比も交えながら進めていくので、どこが似ているか、何が違うかという観点で進めてみるのも面白いだろう。

進め方なのだが、今のところWordPressのテーマにもこのPRECSSを使うことを想定している。

そのため、これまでと違い、具体的なサンプルを実際に作りながら進めていく形にする。

今回はPRECSS自体の説明と基本的な事項、そして後述するグループのうちベース、レイアウト部分までをやってみよう。

なお、本付録は以下の本を参考にしている。

https://amzn.to/3vhFAqe

気になる方は、実際に本屋で中身を見てみたり、買ってみたりしよう。

スポンサーリンク

PRECSSの概要

PRECSS(読み:プレックス)とはprefixed CSSの略で、日本語だと接頭語付きのCSS。

その名の通り、クラス名の全てに役割に応じた2文字の接頭語をつけるのが大きな特徴だ。

公式サイトは以下。

PRECSS - Manage your CSS with prefixes.
PRECSS is a new modular architecture approach based on OOCSS, SMACSS and BEM.

BEMと違い日本語なのでかなり読みやすいだろう。

ちなみにだが、PRECSSは参考書の筆者が考えた手法のようだ。

さて、このPRECSSでは各要素を以下6つのグループに分解して考える。

  1. ベース
  2. レイアウト
  3. モジュール
    1. ブロックモジュール
    2. エレメントモジュール
    3. (モディファイア)
  4. ヘルパー
  5. ユニーク
  6. プログラム

このほか、要件によって独自の役割を作ることも可能だ。

この大きく全体を分けるのはSMACSSに似ていて、モジュールの中身はBEMに似ている。

モディファイアに括弧がついているのは…その時に解説する。

このそれぞれに入っていく前に、やはり全体での方針があるのでそれを見ていこう。

記法

記法とは、スペースやインデント、改行などの書き方を指している。

PRECSSではここにも触れられており、基本的には…

これらに則ることを推奨している。

これは、世界的にも一般的な規約を使うことで、他の人が見ても分かりやすくすることを目的としている。

…が、ここを深く見るとやはりそれだけで長くなってしまうので、本解説は基本的に公式や参考書の書き方を真似することにしよう。

もう一つ、HTMLにおいてdivの終了タグの直後には、どのクラスをつけたdivの終了かをコメントで追記することを推奨している。

例としては以下のような感じ。

<div class="hoge">
  <!-- 省略 -->
</div>
<!-- /.hoge -->

これをする理由は、あまりdivの中身が多くなるとどのdivの終了がどのクラスのものかが分かりづらくなるので、それを解消するためだ。

あるいは、何かしらの理由でインデントが崩れても分かりやすいというメリットもある。

命名規則

上で6つのグループに分けると書いたが、それぞれで決まった2文字の接頭語をつける

その後ろ、アンダースコアを一つ挟み、それ自体の名前をローワーキャメルケースでつけるというのが基本だ。

また、複数要素をネストするときは、それ一つのモジュールにおいて一番親にあたる名前のみを継承するのが原則。

この時も、その名前の後ろにはアンダースコア一つ。

例えば、以下のような感じ。

<div class="bl_halfMedia">
  <img class="bl_halfMedia_img" src="..." alt="...">
  <div class="bl_halfMedia_desc">
    <h3 class="bl_halfMedia_ttl">タイトル</h3>
    <p class="bl_halfMedia_txt">説明文</p>
  </div>
  <!-- /.bl_halfMedia_desc -->
</div>
<!-- /.bl_halfMedia -->

今、大きくbl_halfMediaというクラス名をつけたモジュールを定義している。

その中、画像や説明領域が入るクラス名はそのまま親のものを継承。

説明領域内のタイトルと説明文も、説明領域ではなく、大元であるbl_halfMediaの名前を継承する、ということだ。

ただし、例えば…

  • 親子関係を何かしらの理由で明示したい
  • モジュールが大きく、子要素のクラス名重複を避けたい

といった理由があれば、直近の親要素を継承することも認められている。

その場合は、やはりアンダースコア一つで挟んで継承する。

つまり、PRECSSの命名規則において、アンダースコアは階層を深くすることを意味することになる。

上の例をこのパターンで直してみると…

<div class="bl_halfMedia">
  <img class="bl_halfMedia_img" src="..." alt="...">
  <div class="bl_halfMedia_desc">
    <h3 class="bl_halfMedia_desc_ttl">タイトル</h3>
    <p class="bl_halfMedia_desc_txt">説明文</p>
  </div>
  <!-- /.bl_halfMedia_desc -->
</div>
<!-- /.bl_halfMedia -->

こんな感じだ。

汎用的に使える単語

以下5つの単語は、上で挙げた6つのグループそれぞれで使える。

  • _wrapper
  • _inner
  • _header
  • _body
  • _footer

これだけ書いてもあまり意味が分からないと思うが、具体的に一つだけ例を見てみる。

例えば、ある要素について、何かしらの理由でそれを囲むdiv要素が欲しいとなったとき、以下のように書くことができる。

<div class="bl_halfMedia_wrapper">
  <div class="bl_halfMedia">
    <!-- 省略 -->
  </div>
  <!-- /.bl_halfMedia -->
</div>
<!-- /.bl_halfMedia_wrapper -->

この詳細については、使う時にもう一度説明しよう。

単語の省略

ここまでの説明の時点で、BEMと同じように状況によってはクラス名がかなりの長さになることが予想できる。

そこで、PRECSS独自の規則はないが、単語を略称にする場合はやはりGoogle HTML/CSS Style Guideに則ることを推奨している。

幾つか具体例が公式サイトにも載っているので、一度目を通しておくといいだろう。

シリーズを形成する場合

シリーズとは何ぞやと思うかもしれないが、これは似たモジュールを複数作る場合のお話だ。

基本的にはモジュールのクラス名には意味や目的の挙動を持たせることを推奨しているが、どうしても似たような名前になってしまうこともあるだろう。

そこで、PRECSSでは同じ名前を連番で複数管理することが許容されている

ただし、その時の書き方にも注意がある。

一つ目のみ連番を付けず、二つ目以降には2から数字をつける、というものだ。

<div class="bl_halfMedia">...</div>
<div class="bl_halfMedia2">...</div>
<div class="bl_halfMedia3">...</div>

この理由は、一つ目にまで連番をつけてしまうと、他のものが不要になった時や逆に新しく必要になったときに一つ目の修正も必要になるから。

それを見越して一つのみであろうと必ず最後に1をつけるという手もあるにはあるが、それだとわずかではあるものの不必要にクラス名を長くしてしまうので、やはり避けるべきだろう。

以上で、基本事項は終了だ。

まだ実感が湧かない箇所もあるとは思うが、具体的なグループの解説の中で見てもらえればいいだろう。

今回作成するサンプル

具体的なグループの内容に入る前に、同時並行で作るサンプルの前提を決めておこう。

サンプルで作るもの

まず、そもそも作るものがないといけない。

今回は、以前jQueryのところで出したブログトップページっぽいサンプルを、PRECSSを使って作り直してみる。

ただ、少しだけ見た目もその時のものから変えてみる。

何かというと、ヘッダー領域は背景画像を貼るのではなく、シンプルにブログタイトルをテキストで、その下に各種メニューを貼るという形だ。

…というのも、あの後実際に色々なサイトを見てみたのだが、個人的に変更した後の形の方がしっくり来た。

その他は、基本的には変更せず作っていくつもりだ。

リセットCSSはcss-wipe

次に、リセットCSSはcss-wipeを用いる。

理由は、参考書がcss-wipeを使って説明しているから。

…本当はこんな理由ではいけないのだが、今回の目的の一つが実際に使って慣れることであり、そのためには参考書と近づけた方がいいと判断した。

なお、参考書の公式サンプルではNormalize.cssを使ったタイプも用意されている。

一応参考書を買ってなくても使っていいと書かれていたが、直接リンクを貼るのは避けておこう。

Googleで「CSS設計完全ガイド サンプル」で調べてもらえば一発で出てくるので、気になる方は参照してほしい。

また、今回作るサンプルはそこのサンプルと形がだいぶ変わっており、詳細が見たい方は参考書を購入しよう。

最低限決めなければいけないことは以上だろう。

ベースグループ

ではPRECSSの各グループの説明へ、まずはこのベースグループだ。

これはSMACSSのベースグループとほぼ同じで、リセットCSSの適用や各要素のデフォルト設定を行う

直接要素を指定するので、もちろん独自の命名規則はなしだ。

ただし、SMACSSとは異なる点が一つある。

それは、PRECSSでは特定の部品に入っている要素のデフォルトを定義することもできる、ということ。

具体的には、hogeクラスの要素内のaタグのデフォルトを定義する、といったことが可能だ。

.hoge a {
  /* hogeクラス内のa要素のデフォルト設定 */
}

ただし、これは詳細度を上げてしまい上書きが複雑になるので、必要最小限に留めるようにしよう。

サンプル側では、上述の通りリセットCSSとしてcss-wipeを使うのと、追加で以下の設定のみを行っておく。

body {
  background-color: #fff;
  font-family: 'Meiryo';
  color: #222;
}

それぞれの意図を書いておくと、一つ目の背景色はSMACSSで推奨していたのでそれを参考に設定している。

二つ目は、ベースとなるフォントを設定。

三つ目で文字色を設定しているが、一つ目で背景色を設定しているのでセットで指定しているのと、真っ黒でないのはそうした方がいいというのを見かけたからだ。

どうやら、真っ白背景に真っ黒文字といった色の指定だと明暗差が激しすぎて目に負担がかかり、見ていて疲れやすいそうだ。

この他は必要があれば随時追加していくこととしよう。

レイアウトグループ

これもSMACSSのレイアウトに似ている

ページにおけるヘッダー、ボディ、その中のメインコンテンツやサイドコンテンツ、下のフッターなど、大きな領域の要素に使用するものだ。

接頭語はly_、これには基本的にwidthmarginpaddingfloatなどのレイアウトに関するスタイリングのみを行う。

ただし、ヘッダー領域は背景色を黒にする、というように粒度が一致している場合のみ、その設定を行うことも許容している

サンプルでは、以下のレイアウトを作成する。

  • ヘッダー領域
  • コンテンツ領域
    • メインコンテンツ領域
    • サイドコンテンツ領域
  • フッター領域

HTMLのタグについては、ヘッダー領域、フッター領域はそのままheaderfooterを使おう。

コンテンツ領域はdivタグを使い、その中のメイン、サイドはそれぞれmainasideを用いる。

クラス名はもちろんそれぞれ先頭にly_をつけ、メインとサイドはコンテンツ領域の子要素なので継承する。

これで構造を書いてみよう。

<body>
  <header class="ly_header">
    ヘッダー領域
  </header>
  <div class="ly_cont">
    <main class="ly_cont_main">
      メインコンテンツ領域
    </main>
    <aside class="ly_cont_side">
      サイドコンテンツ領域
    </aside>
  </div>
  <!-- /.ly_cont -->
  <footer class="ly_footer">
    フッター領域
  </footer>
</body>

中に入れているテキストは確認用なのであまり気にしなくていい。

次にCSS側、上に書いた通りレイアウトに関する指定のみを原則とするが、一旦確認用で背景色をそれぞれ変えておこう。

また、それぞれの領域内は次回以降のモジュール実装時に調整したいので、今回は外側に対するレイアウトに着目して実装していく。

それぞれの詳細を見ていこう。

ヘッダー、フッター領域

これらは一旦共通の設定を行う。

横幅はPC、タブレット、スマホそれぞれの幅に関わらず100%。

その他は中身を作る時に追加していく。

背景色も変えて、CSSは以下のように設定しておこう。

.ly_header {
  width: 100%;

  background-color: #ddd; /* 配置確認用 */
}

.ly_footer {
  width: 100%;

  background-color: #ddf; /* 配置確認用 */
}

コンテンツ、メイン、サイド領域

次にここだ。

サンプルの元ではレスポンシブデザインを考えていなかったが、折角なのでそこも考えてみよう。

やりたいこととしては、PCやタブレットの幅では2カラムでメインを左、サイドを右に配置する。

スマホ幅の場合は1カラムで、メインの下にサイドを配置する、というイメージだ。

PCとタブレットについても、ある大きさまでは画面いっぱいになるよう配置し、それ以上の場合は外側の左右に余白を均等に配置して中央揃えで実装したい。

図にすると以下のような感じだ。

レイアウトイメージ図

一つだけ補足で、余白に2つの色をつけている。

これは、薄い赤のところはメインコンテンツのmarginで設定することを意図している。

決して適当に色付けしているわけではないので、そこだけ注意だ。

で、これをどう実現するかなのだが、スマホ幅のパターンをベースにして、モディファイアを使ってタブレット幅、PC幅のパターンを指定する。

つまり、1カラムをベースに、2カラムを拡張パターンとして実装するイメージだ。

モディファイアの説明はモジュールの所で解説するので、一旦組んでみよう。

まずスマホ幅、これがベースなので各クラスに直接レイアウトを指定する。

.ly_cont {
  width: 100%;
  padding-top: 2em;
  padding-bottom: 2em;

  background-color: #eee; /* 配置確認用 */
}

.ly_cont_main {
  margin-bottom: 1.5rem;

  background-color: #fdd; /* 配置確認用 */
}

.ly_cont_side {
  background-color: #dfd; /* 配置確認用 */
}

ly_contpaddingly_cont_mainmargin-bottomの数字は仮で入れているだけなので、中身実装後に調整し直す。

これで表示すると、スマホ幅のような表示になるはずだ。

次に、これを拡張する形でタブレット幅を実装していこう。

準備として、HTML側でコンテンツ領域にly_cont__colというモディファイアクラスを付与。

<div class="ly_cont ly_cont__col">
  <main class="ly_cont_main">
    メインコンテンツ領域
  </main>
  <aside class="ly_cont_side">
    サイドコンテンツ領域
  </aside>
</div>
<!-- /.ly_cont -->

これで、今追加したly_cont__colに対してレスポンシブの設定を行う。

スマホ幅からの変更点としては以下のような感じだろう。

  • コンテンツのレイアウトをフレックスボックスに変更
  • メインコンテンツ下の余白を無しに
  • メインコンテンツ、サイドコンテンツの横幅を割合で指定

フレックスボックスは、display: flex;のことだ。

また、同時にメイン、サイドは上端を揃えたいのでalign-items: flex-start;を、これらは左右の余白なしで配置したいのでjustify-content: space-between;を指定する。

さらに、メイン、サイドの横幅はwidthではなくflex-basisで調整しよう。

以上を踏まえ、タブレット幅は以下のように実装する。

/* タブレット幅 */
@media screen and (min-width: 768px) and (max-width: 1024px){
  .ly_cont.ly_cont__col {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
  }

  .ly_cont__col > .ly_cont_main {
    margin-bottom: 0;
    flex-basis: 70%;
  }

  .ly_cont__col > .ly_cont_side {
    flex-basis: 25%;
  }
}

最後にPC幅のことを考える。

やはりベースとなるのはスマホ幅で、今度は以下のような変更を加えたい。

  • コンテンツのレイアウトをフレックスボックスに変更
  • メインコンテンツ下の余白を無しに
  • メインコンテンツ、サイドコンテンツの横幅を固定値で指定
  • メインコンテンツの右に余白を固定値で指定

また、今度は左右に余白を均等に配置するため、justify-contentプロパティはcenterに変更だ。

その間はメインコンテンツに対するmargin-rightで指定。

これを実装したものが以下。

/* PC幅 */
@media screen and (min-width: 1024px){
  .ly_cont.ly_cont__col {
    display: flex;
    align-items: flex-start;
    justify-content: center;
  }

  .ly_cont__col > .ly_cont_main {
    flex-basis: 716.8px;
    margin-right: 51.2px;
    margin-bottom: 0;
  }

  .ly_cont__col > .ly_cont_side {
    flex-basis: 256px;
  }
}

固定値については、PC幅とタブレット幅の境界である1024px時点でのタブレット側のサイズを計算し、それを直接指定している。

これで、だんだん画面を広げた時にも見た目ががらっと変わることはない。

さて、これで実装はできたのだが、タブレット幅とPC幅で共通の設定がいくつか存在する。

これは括りだして、一か所で定義しよう。

以上を踏まえると、この領域のCSSは最終的に以下のようになる。

.ly_cont {
  width: 100%;
  padding-top: 2em;
  padding-bottom: 2em;

  background-color: #eee; /* 配置確認用 */
}

.ly_cont_main {
  margin-bottom: 1.5rem;

  background-color: #fdd; /* 配置確認用 */
}

.ly_cont_side {
  background-color: #dfd; /* 配置確認用 */
}

/* タブレット幅以上の共通設定 */
@media screen and (min-width: 768px){
  .ly_cont.ly_cont__col {
    display: flex;
    align-items: flex-start;
  }

  .ly_cont__col > .ly_cont_main {
    margin-bottom: 0;
  }
}

/* タブレット幅 */
@media screen and (min-width: 768px) and (max-width: 1024px){
  .ly_cont.ly_cont__col {
    justify-content: space-between;
  }

  .ly_cont__col > .ly_cont_main {
    flex-basis: 70%;
  }

  .ly_cont__col > .ly_cont_side {
    flex-basis: 25%;
  }
}

/* PC幅 */
@media screen and (min-width: 1024px){
  .ly_cont.ly_cont__col {
    justify-content: center;
  }

  .ly_cont__col > .ly_cont_main {
    flex-basis: 716.8px;
    margin-right: 51.2px;
  }

  .ly_cont__col > .ly_cont_side {
    flex-basis: 256px;
  }
}

以上で、レイアウトの実装が完了だ。

現時点でのサンプル全体

ここまでの内容で、サンプルページを提示しておこう。

リンクはこちら、各ソースは以下の通りだ。

<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8">
    <title>ブログタイトル</title>

    <!-- レスポンシブデザイン対応 -->
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <!-- css-wipe読み込み -->
    <link rel="stylesheet" type="text/css" href="./css/css-wipe.css">

    <!-- 自作CSS読み込み -->
    <link rel="stylesheet" type="text/css" href="./css/style.css">
  </head>
  <body>
    <header class="ly_header">
      ヘッダー領域
    </header>
    <div class="ly_cont ly_cont__col">
      <main class="ly_cont_main">
        メインコンテンツ領域
      </main>
      <aside class="ly_cont_side">
        サイドコンテンツ領域
      </aside>
    </div>
    <!-- /.ly_cont -->
    <footer class="ly_footer">
      フッター領域
    </footer>
  </body>
</html>
@charset "UTF-8";

/*
*****************************
* Base                      *
*****************************
*/

body {
  background-color: #fff;
  font-family: 'Meiryo';
  color: #222;
}

/*
*****************************
* Layout                    *
*****************************
*/

.ly_header {
  width: 100%;

  background-color: #ddd; /* 配置確認用 */
}

.ly_footer {
  width: 100%;

  background-color: #ddf; /* 配置確認用 */
}

.ly_cont {
  width: 100%;
  padding-top: 2em;
  padding-bottom: 2em;

  background-color: #eee; /* 配置確認用 */
}

.ly_cont_main {
  margin-bottom: 1.5rem;

  background-color: #fdd; /* 配置確認用 */
}

.ly_cont_side {
  background-color: #dfd; /* 配置確認用 */
}

/* タブレット幅以上の共通設定 */
@media screen and (min-width: 768px){
  .ly_cont.ly_cont__col {
    display: flex;
    align-items: flex-start;
  }

  .ly_cont__col > .ly_cont_main {
    margin-bottom: 0;
  }
}

/* タブレット幅 */
@media screen and (min-width: 768px) and (max-width: 1024px){
  .ly_cont.ly_cont__col {
    justify-content: space-between;
  }

  .ly_cont__col > .ly_cont_main {
    flex-basis: 70%;
  }

  .ly_cont__col > .ly_cont_side {
    flex-basis: 25%;
  }
}

/* PC幅 */
@media screen and (min-width: 1024px){
  .ly_cont.ly_cont__col {
    justify-content: center;
  }

  .ly_cont__col > .ly_cont_main {
    flex-basis: 716.8px;
    margin-right: 51.2px;
  }

  .ly_cont__col > .ly_cont_side {
    flex-basis: 256px;
  }
}

実際に画面幅を変えて、意図したように配置が変わることも確認しておこう。

また、スマホやお持ちの方はタブレットでもアクセスしてみるといいだろう。

おわりに

今回はPRECSSに入り、同時にサンプルも作り始めた。

一旦はベースレイアウトの二つについて理解しておいてもらえればOKだ。

ベース基本となる内容を、直接要素に対して付与する

レイアウトページ上の大きな領域を作り、それぞれ配置に関する指定のみを行うことが原則だ。

このレイアウトの中に次回以降解説するモジュールを入れていくことになる。

ということで、次回はそのモジュールを解説していこう。

また、今回出したモディファイアもその中で補足していく。

サンプルについては、一度に全て作ろうとすると記事がとんでもない長さになることが予想できるので、一旦ヘッダー内だけ実装しようと思う。

私が書いているサンプルをなぞるでもいいが、よかったら別で何か作りながら進めてみて欲しい。

2021/4/3追記

次回の内容、PRECSSのモジュールを解説した。

他の設計手法と似ている点、異なる点が入り混じっているので、しっかり区別をつけながら進めていこう。

また、このモジュールがページの大部分を占めることになり、一番重要になる。

実際に作る時はしっかり頭を使いながら設計していきたい。

コメント

タイトルとURLをコピーしました