🎉 お知らせ:サイト名が『webkore』から『模写修行 media』に変更になりました。6月以降にドメインも『moshashugyo.com/media/』へ変更する予定です。

HTML/CSS

【初心者向け】模写修行流CSS設計を紹介!

Author:Gaku(gaku92014091)

この記事の目次

現在、『模写修行』というコーディングの練習が出来るサービスを制作中です。そこで、模写修行のコンテンツを作る際に、どんなCSS設計を採用するか悩みました。

模写修行のターゲットは基礎をある程度学び終えたくらいの方なので、有名なCSS設計やそもそもCSS設計自体を知らなくても使えるようにしなければいけません。

OOCSS / SMACSS / BEM / … などの考え方を採用しつつ、webサイトからwebサービスまで、なるべく幅広く対応出来るように考えたつもりです。

どんなCSS設計を採用するかに正解は無いので、『模写修行流』ということで、1つのサンプルとして駆け出しエンジニアの方に参考になれば幸いです。

CSS設計についてまだ全く勉強したことがない方は、こちらの記事を読んでからだと内容が入りやすいかもしれません。

雛形コードのダウンロード

雛形コードを見ながらこの記事を読んだ方が、より理解できると思うので、ダウンロードできるようにしました。CSS版とSCSS版が入っています。

SCSS版は、style.scssを修正しないと環境によっては動かないと思います。

どこに何を書くかイメージがつくようにコメントなどを入れただけの、雛形です。

コーディングする際の基本ルール

ガチガチのルールを設けるわけではなく、最低限にとどめています。重要な点だけ抑えて、それ以外の細かい点は好みもあるので自分の中でルール化すれば良いです。

classの命名

css
.service-title{...}
.service-list{...}
.service-item{...}

.m-button {...}
.m-button--primary {...}
.m-button--secondary {...}
.m-button--accent {...}

class名は全てハイフン区切りにしています。

👇 BEMを勉強してない方はここ読み飛ばしてください

BEMのようにブロックとエレメントで分ける命名は、一目でそれがブロックなのかエレメントなのかがわかる点がメリットです。ただ、最初のうちはclassをつける際にこれはブロックか?エレメントか?で悩むことにもなります。全てハイフン区切りであれば、classをつける際のその悩みがなくなります。

ブロックなのかエレメントなのかは曖昧でも、迷わず先に進める方を優先しました。

カラーやサイズなどのバリエーションを実装するための、バリエーションクラス(Modifier)はハイフンを2つつけるルールにします。

html
<!-- 背景赤色のボタンになる -->
<button class="m-button m-button--accent">ボタン</button>
css
.m-button {
    /* 全ボタンに適応させたいスタイルを書く */
}

.m-button--primary {
    background-color: #000;
    color: #fff;
}

...

.m-button--accent {
    background-color: red;
    color: #fff;
}

👆 バリエーションクラス(Modifier)はこのように使います。

補足
  • class名の省略はなるべくしない
  • 連番が必要な場合は、1番目は番号は付けずに、2番目から付ける

シングルクラスの採用

種類 説明
シングルクラス 1つのタグに対して1つのclassがつくこと
マルチクラス 1つのタグに対して複数のclassがつくこと

シングルクラスとマルチクラスの定義はこのようにしています。基本的にはシングルクラスで書きますが、例外もあります。


例外(マルチクラスになる例)

html
<!-- OK -->
<h2 class="m-title m-title—-center">
  Modifierと一緒に使うケースはOK
</h2>

<!-- OK -->
<div class="service u-ptb-m">
  utilityと一緒に使うケースはOK
</div>

<!-- NG -->
<div class="service l-container">
  Modifier / utility 意外と一緒に使うケースはNG
</div>

<!-- OK -->
<h2 class="m-title m-title—-center js-page-title has-animation-title-fade-in is-title-fade-in-active">
  JavaScriptで操作する際にこのようになるケースもOK
</h2>

Modifierやutilityに関しては後半で説明します。意味が分からない場合は読み進めてから、最後に再度読むと理解できると思います。

  • Modifierを使用する
  • utilityを使用する
  • JavaScriptのフックを使用する
  • アニメーションを使用する
  • 状態によってJavaScriptで追加削除される

これらのケースではマルチクラスになっても良しとします。


使用例(シングルクラスでの書き方)

html
<!-- NG -->
<button class="m-button contact-submit-button"></button>

<!-- OK -->
<div class="contact-submit-button">
  <button class=“m-button></button>
</div>
css
.contact-submit-button{
  margin-top: 40px;
}

例えばボタンの上に40pxの余白を開けたい場合は、このように書きます。.m-buttonが色々なところで使い回すパーツ(モジュール)です。

NGの例は悪い書き方というわけではありません。今回はそのような書き方をしないルールにしただけです。どのclassに書いたスタイルが適応されているか分かりやすいようにシングルクラス(OKの例のような形)にしました。


サイトによってはマルチクラスでの運用の方がスッキリ書けて、ページや要素の追加も楽かもしれません。しかし、マルチクラスは複雑なデザインの場合、煩雑になり、破綻を招きます。従って、シングルクラスでの運用にします。

ディレクトリ構成

ディレクトリ構成は雛形をダウンロードしてもらえると分かりやすいと思います。

小中規模なサイトを制作する想定なので、CSSは1ファイルにコメントで区切りながら書きます。SCSSの場合は、後述する役割ごとにディレクトリを切って、その中でブロックごとに分割しています。

ブロックとはそのサイトやページの中でのパーツや塊だと思ってもらえればOKです。

その他

基本的にスタイリングする際はclassを付与して、単体のclassセレクタに書きます。

css
/* NG */
.hoge h2{
  margin-top: 40px;
}

/* OK */
.hoge-title{
  margin-top: 40px;
}

/* 例外でOK */
.m-posts--col3 > .m-posts-item{
    ...
}

例外に関しては模写修行のコンテンツの中で解説します。その他細かい注意点もコンテンツの中で解説します。

classのカテゴリ分類とその詳細

classのカテゴリ
  • animation
  • foundation
  • layout
  • mixin(SCSSでのみ使用)
  • module
  • page
  • setting(SCSSでのみ使用)
  • utility

スタイルをこれらの8つのカテゴリに分類します。順番は前後しますが、どんな役割のスタイルか解説します。

settingカテゴリ(SCSSでのみ使用)

settingカテゴリ

SCSSの変数やCSSのカスタムプロパティを定義するためのカテゴリ

  • ブレークポイント
  • カラー
  • コンテンツ幅
  • フォント

例えばこのような値を変数にしておきます。上記の4つがあれば、settingディレクトリの中にSCSSのファイルが4つ存在することになります。


SCSSでの使用例

scss
$primaryColor: #000;
$secondaryColor: #fff;
$accentColor: #eee;

例えばcolor.scssはこのようになります。

foundationカテゴリ

foundationカテゴリ

リセットCSSや全体の共通設定に関するスタイルをまとめるカテゴリ

foundationカテゴリ内はresetとbaseに分類します。

分類 詳細
reset プロジェクトによって変化しないスタイル
base プロジェクトによって変化するスタイル

分類の基準はこのようにしています。


CSSでの使用例

css
/* reset */
html {
    color: #000;
    background: #fff;
}

body,
div,
dl,
dt,
dd,
ul,
ol,
li,
h1,
h2,
h3,
h4,
h5,
h6,
pre,
code,
form,
fieldset,
legend,
input,
textarea,
p,
blockquote,
th,
td {
    margin: 0;
    padding: 0;
}

table {
    border-collapse: collapse;
    border-spacing: 0;
}

fieldset,
img {
    border: 0;
}

address,
caption,
cite,
code,
dfn,
em,
strong,
th,
var {
    font-style: normal;
    font-weight: normal;
}

ol,
ul {
    list-style: none;
}

caption,
th {
    text-align: left;
}

h1,
h2,
h3,
h4,
h5,
h6 {
    font-size: 100%;
    font-weight: normal;
}

q:before,
q:after {
    content: "";
}

abbr,
acronym {
    border: 0;
    font-variant: normal;
}

sup {
    vertical-align: text-top;
}

sub {
    vertical-align: text-bottom;
}

input,
textarea,
select,
button {
    font-family: inherit;
    font-size: inherit;
    font-weight: inherit;
    line-height: inherit;
    *font-size: 100%;
}

legend {
    color: #000;
}

main{
    display: block;
}

* {
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    box-sizing: border-box;
}

*::before,
*::after {
    box-sizing: border-box;
}

/* base */
body {
    font-family: "Helvetica Neue", Arial, "Hiragino Kaku Gothic ProN", "Hiragino Sans", Meiryo, sans-serif;
    line-height: 1.8;
    font-size: 16px;
}

a {
    text-decoration: none;
    color: inherit;
}

img {
    width: 100%;
    height: auto;
    vertical-align: bottom;
}

CSSではコメントで区切っていますが、SCSSではreset.scssとbase.scssで2つのファイルに分割します。

mixinカテゴリ(SCSSでのみ使用)

mixinカテゴリ

mixinを定義するためのカテゴリ

好みや方針にもよりますが、mixinは使いずぎると煩雑になるので、必要最低限にします。


SCSSでの使用例

scss
/*
アスペクト比計算
ex)
<div class="youtube">
    <iframe ...></iframe>
</div>
.youtube{
    @include aspectRatio(560,315);
}
*/
@mixin aspectRatio($width: 16, $height: 9) {
    position: relative;
    padding-top: percentage($height / $width);

    > * {
        position: absolute;
        top: 0;
        left: 0;
        width: 100% !important;
        height: 100% !important;
    }
}

アスペクト比の計算をしてくれるmixinの例です。分かりにくいものはコメントで使用例を載せています。

moduleカテゴリ

moduleカテゴリ

ページを跨いで使い回すスタイルをまとめるカテゴリ

必ずm-プレフィックスを付けるようにします。

m-が付いていれば、他の箇所でも使っていることを念頭に置きながら作業できます。これで思わぬところにも影響してしまうようなリスクも減らせます。


CSSでの使用例

css
/* button base */
.m-button {
    display: inline-block;
    border: none;
    border-radius: 4px;
    background-color: #333;
    color: #fff;
    font-weight: bold;
    appearance: none;
    -webkit-appearance: none;
    -moz-appearance: none;
    cursor: pointer;
    border: 2px solid transparent;
    padding: 8px 24px;
}

/* button color primary */
.m-button--primary {
    background-color: #1a1a1a;
    color: #fff;
}

/* button color secondary */
.m-button--secondary {
    background-color: #fff;
    color: #1a1a1a;
}

/* button color accent */
.m-button--accent {
    background-color: #bd2424;
    color: #fff;
}

/* button size large */
.m-button--size-large {
    width: 100%;
}

/* title base */
.m-title {
    font-size: 32px;
    font-weight: bold;
}

/* title center */
.m-title--center {
    text-align: center;
}

CSSではコメントで区切っていますが、SCSSではファイル分割します。上記の例だと、button.scssとtitle.scssで2つのファイルに分割します。

使いまわせるパーツが多いようなデザインでは、moduleに属するスタイルがたくさん存在します。

utilityカテゴリ

utilityカテゴリ

moduleにするほどでもないちょっとした使い回すスタイルをまとめるカテゴリ

  • 余白関連
  • sp / pcでの表示非表示
  • 隠しコンテンツ

例えばこれらなど、必要最低限にします。

moduleと同じように、u-プレフィックスを付けるようにします。


CSSでの使用例

css
.u-ptb-s {
    padding: 40px 0 !important;
}

.u-ptb-m {
    padding: 64px 0 !important;
}

.u-ptb-l {
    padding: 80px 0 !important;
}

余白関連の例です。

utilityカテゴリは最優先で効いて欲しいので!importantを付けます。

!importantをさらに上書きする必要があるケースは、そもそもutility classを使うべきでない箇所なので、上書きに上書きを重ねることはありません。

layoutカテゴリ

layoutカテゴリ

レイアウトを作るためのスタイルをまとめるカテゴリ

  • header
  • footer
  • container
  • sidebar

例えばこれらがレイアウトを作るためのスタイルです。

header / footer / sidebar はレイアウトと分りやすいので、プレフィックスは付けませんが、それ以外には基本的にl-プレフィックスを付けます。


CSSでの使用例

css
/* header */
.header {...}
.header-logo {...}

/* footer */
.footer {...}
.footer-logo {...}

/* container */
.l-container {
    width: 90%;
    margin: 0 auto;
}

CSSではコメントで区切っていますが、SCSSではファイル分割します。上記の例だと、header.scssとfooter.scssとcontainer.scssで少なくとも3つのファイルに分割します。

header / footer はコード量が多くなるので、その中でもブロック(パーツや塊)ごとにさらに分割するケースがほとんどです。

pageカテゴリ

layoutカテゴリ

そのページでしか使わないスタイルをまとめるカテゴリ

各ページの名前をプレフィックスにします。

example.com/service/ の場合

css
service-title{}
service-text{}
service-button{}

example.com/about/ の場合

css
about-title{}
about-text{}
about-button{}

各ページの名前をプレフィックスにしておけば、他のページとclass名が被ることもありません。

ページを跨いで使える共通パーツ(モジュール)が少なく、pageカテゴリのスタイルが1番多くなることも少なくありません。

animationカテゴリ

layoutカテゴリ

演出目的のアニメーションに使うためのスタイルをまとめるカテゴリ

演出目的とは、例えばスクロールに連動してフェードインさせるようなアニメーションなどのことです。

  • タブメニュー
  • モーダル
  • ハンバーガーメニュー

このような演出目的ではなく、機能目的のUIを実装する際は、animationカテゴリに入れません。


アニメーションでの使用例

html
<h2 class="service-title js-page-title has-animation-title-fade-in">
  サービス
</h2>
css
/* SCSSで書く場合のディレクトリは、 */
/* page > service > service.scss */
/* ----------------------------- */
.service-title{
  ...
}

/* SCSSで書く場合のディレクトリは、 */
/* animation > title-animation.scss */
/* ----------------------------- */
.has-animation-title-fade-in{
    opacity: 0;
    transition: opacity .3s;
}

.is-animation-title-fade-in-active{
    opacity: 1;
}

タイトルが表示領域に入ると、透明度を0から1にアニメーションをするためのサンプルです。見た目のスタイルとアニメーションのためのスタイルは分離した方が分かりやすいので、このようにしています。

.js-hogeはJavaScriptのフックに使うもので、このclassに対してスタイリングしてはいけません。


ハンバーガーメニューでの使用例(animationカテゴリに属さない)

html
<div class="header-menu js-header-menu">
  ...
</div>
css
/* SCSSで書く場合のディレクトリは、 */
/* layout > header-menu.scss */
/* ----------------------------- */
.header-menu{
  ...
  display: none;
}

/* ハンバーガーメニューactive時に付与するclass */
.is-header-menu-active{
    display: block;
}

このような場合、animationカテゴリには属さず、.header-menuが書いてあるファイルにコメントをつけて記載します。

その他とまとめ

JavaScriptで操作され、状態を表すclassにはis-を付けます。animationカテゴリの解説で出てきたのがそのケースに当たります。

最後に全てのカテゴリを表でまとめておきます。

カテゴリ TH
animation 演出目的のアニメーションに使うためのスタイル
foundation リセットCSSなどサイト全体のスタイル
layout headerなどレイアウトを構成する要素のスタイル
mixin(※) SCSSのmixinをまとめる
module ページを跨いで使い回すスタイル
page 各ページでしか使わないスタイル
setting(※) 変数の定義やサイト全体の設定
utility moduleにするほどでもない使い回すスタイル

(※)がついているものはSCSSでのみ使用。

【宣伝】模写修行はどんなサービス?

この記事では独自のCSS設計について具体的に解説しました。

とはいえ、実際使ってみようと思っても迷いが生じる箇所は多くあるはずです。僕もCSS設計を勉強したばかりの頃は、本で勉強して実際に使ってみたものの、『このケースはどうなるんだ?』と思うことが多々ありました。

模写修行では1から実践的なサイトを作ることで、より理解が深まるようにしています。

具体的にどんな手順で勉強できるの?

  1. 500~2000円のコンテンツを購入(単発購入のみ)
  2. XDのデザインデータをダウンロード
  3. 自分でコーディングをしてみる
  4. コードサンプルと解説を見て学習

このような流れで学習できるようになっています。デザインデータだけでなく、コードサンプルと解説も購入した時点ですぐダウンロードできますが、『自分でコーディングをしてみる』にたくさん時間を使っていただきたいです。

模写修行のコンテンツが向いている人向いてない人

模写修行は『教科書ではなく問題集』をテーマにしてるので、1から学ぶようなコンテンツではありません。ある程度基礎の勉強を終えた方に役立つようなサービスになっています。

🙆‍♂️ 向いている人
  • コーダーやフロントエンドエンジニアを目指している
  • コーディングの基礎はある程度学んだ
  • webサイトやwebサービスのコーディングの練習がしたい
  • 超実践的な練習がしたい方
🙅‍♂️ 向いていない人
  • バックエンドエンジニアを目指している
  • まだコーディングの基礎を勉強していない
  • ツール系の管理画面などのコーディングの練習がしたい

勉強に使えそうだと思った方は、ローンチしたら是非覗いてみてください。(2021年6月ローンチ予定)

お知らせや告知はTwitter(@moshamusha2010)でするので良ければフォローもお願いします。技術系のツイートもしています。

駆け出しエンジニアのためのコーディング練習教材

Coming Soon
© 2021 模写修行 media.