HTML
CSS
bem
CSS設計

HTML/CSS初心者から中級者への一歩を踏み出す練習課題 その1

本記事は、筆者がチームに新人きた際に作ったHTML/CSSの練習課題の改訂版です。

狙い

課題は以下の3つを目標に作成しました。

  • BEM記法に慣れてもらう。
  • パーツ同士が疎結合なクラス設計を意識できるようになる。
  • 保守性を大事にするマインドを身につけてもらう。

対象

HTMLとCSSがとりあえず書ける初心者から中級者への一歩目を踏み出したい人

やくそく

  • HTMLタグは正しく使う(brタグ連打で間隔を調整したり、なんでもdivタグで済まさない)。
  • レスポンシブに作る(PC用とSP用にそれぞれHTMLを書いて画面幅によってdisplay: none;するのは禁止)。
  • クラス名はBEMに従う。
  • 装飾にidは使わない。
  • タグに直接にスタイルを指定しない(ただし例外もある)。
  • !importantは絶対に使わない。
  • Javascriptで高さや幅を制御するのは禁止。
  • 今回はモダンブラウザ(chrome/Firefox/safari/Edge)+IE11をサポート対象とする。

準備

HTML/CSSの基礎は知っている前提です。
BEMがどんなものかについては解説しないので、各々勉強してください。
BEM を使うべき5つの理由
Web制作者のためのCSS設計の教科書 モダンWeb開発に欠かせない「修正しやすいCSS」の設計手法

課題

ページ内に次のような要素を作って欲しいと依頼されました。再現してみてください。

PC時(画面幅768px以上)

pc.png
① アイコン画像は正方形、width:80px, height: 80pxで表示する。
② ボールド、中央揃え、サイズ20px
③ サイズ16px
④ サイズ14px
⑤ パネルは3つとも高さをそろえる。
⑥ パネルは3つとも同じ幅。
⑦ パネルとパネルの間隔は20px
⑧ 間隔10px
⑨ 間隔20px
⑩ 間隔20px
⑪ パネル内の余白は20px
⑫ パネルの上下は30px
⑬ パネルを3つ並べたときの幅は960px、画面中央寄せ

依頼する人はパワポやエクセルで指示書を作るのが大好き。
だからこういった図から要求や数値を読み取る訓練も必要です。

SP時(画面幅768px未満)

sp.png
① アイコン画像はwidth:60px, height: 60pxで表示する。
② アイコンとタイトルの間隔は30px
③ アイコンとタイトルは横並び、高さ方向中央揃え
④ 画面端との左右の間隔は15px
⑤ パネルとパネルの間隔は20px

PC時に横並びになっていたパネルが縦積みになりました。

実習

まずは以下のテンプレートを使ってパネルを1つ作ってみましょう。
テンプレート

できたらChrome等のモダンブラウザで表示を確認します。

パネルを作ろう

パネルをひと塊のパーツとして捉えて、BEMでクラスを設計していきます。
まずは作るパーツを細かい要素に分解していきます。
筆者がよくやるのはこんな感じ。

  • 大枠(.panel)
  • ヘッダー(.panel__header)
  • コンテンツ(.panel__content)
  • フッター(.panel__footer)

クラス設計は慣れてくると自分なりのパターンができてきます。
さらにヘッダーの中身もこんなふうに分解します。

  • アイコン(.panel__header__icon)
  • テキスト(.panel__header__text)

実際にスタイルを当ててみて不要だったクラスはあとから削ればいいです。

背景色のクラスを作る。

いいクラス名かはわからないけれど、帯(.belt)としておきます。

  • 灰色の領域は画面幅いっぱいに広がる。
  • ページ要素は画面の中央揃え
  • ページ要素の幅は960px
  • ページ要素内は上下30px余白がある。
  • ページ要素内は左右20px余白がある。

以上の条件を踏まえて.belt__contentというクラスも用意します。

できましたか?

以下は筆者だったらこう作る例です。

index.html
<div class="belt">
    <div class="belt__content">
        <div class="panel">
            <div class="panel__header">
                <div class="panel__header__icon"><img src="dummy.png" alt="ダミー"></div>
                <div class="panel__header__text">パネルタイトル</div>
            </div>
            <div class="panel__content">
                テキストテキストテキストテキストテキストテキストテキストテキストテキストテキスト
            </div>
            <div class="panel__footer">
                <ul>
                    <li>補足補足補足補足</li>
                    <li>補足補足補足</li>
                </ul>
            </div>
        </div>
    </div>
</div>
style.css
.panel {
    background-color: #fff;
    border: solid 1px #cecece;
    border-radius: 8px;
    padding: 20px;
}

.panel__header {
    margin-bottom: 20px;
}

.panel__header__icon {
    text-align: center;
    margin-bottom: 10px;
}

.panel__header__text {
    text-align: center;
    font-weight: bold;
    font-size: 20px;
}

.panel__header__icon > img {
    width: 80px;
}

.panel__content {
    margin-bottom: 20px;
    font-size: 16px;
}

.panel__footer {
    font-size: 14px;
}

.belt {
    min-width: 960px;
    background-color: #eee;
}

.belt__content {
    width: 960px;
    padding: 30px 0;
    margin-left: auto;
    margin-right: auto;
}

.panel__header__iconにおいて、子要素のimgタグに対して直接スタイルをあてています。
これは「タグに直接にスタイルを指定しない」という約束に抵触しますが、

  • imgタグ(親の要素に子要素が画像だとわかるようなクラス名をつけることができるとき)
  • liタグ(親のul直下にはliしか存在しないはずだから)

は今回のようにタグに直接スタイルを指定してしまうことがあります。

やるにしても>で直下の要素に対象を絞るようにしましょう。
またdivタグやspanタグに対してスタイルを指定するのは避けましょう。
最低限これらを守らなければ半年後、数年後の修正作業時に地獄を見ます。

ともあれ、タグに直接にスタイルを指定するのは極力さけましょう(vue.jsやreact.jsのようなHTML/CSS/JSが一体となったコンポーネントを作れるフレームワークを使うときはまた別)。

コード例
次はパネルのSP時の装飾を作っていきます。
その2へ続く。