HTML
CSS

コーディングガイドライン草案

HTML

  • 拡張子は「.html」
  • 文字コードはUTF-8(BOM無し)
  • 改行コードはLF
  • インデントはタブスペース(半角4文字分)が好ましい。が、開発環境次第(Codekitだと半角スペース2つになってしまう)。
  • ファイル名は半角英数字。単語の区切りを「-」にするか「_」にするかは案件次第

CSS

ファイル構造

  • ファイル、ディレクトリ名は半角英数字と「_」
  • 読み込むファイル数は少なく。ツールを使って1つにすることも検討する。裏側でファイルが複数ファイルで管理されている分には全く問題ない。
/css/
/css/pc/
/css/pc/common.css
/css/sd/
/css/sd/common.css

※「SD = Smart Device」だが、会社や人によっては「SP = Smartphone」を使う場合もあるので適宜。

/css/
/css/pc_common.css
/css/sd_common.css

上記でも問題ない。
むしろGUIでドラッグしてアップロードするときに同名フィイルの上書きをすることがなくなるのでこちらの方が良いかもしれない。

好みの問題。

クラス名のルール

  • 後述する接頭辞を必ず付ける。
  • 単語と単語の区切りは「_」。「.pp_commonHeader」のようにはしない。「.pp_SNSList」など頭文字を連結して作られている単語が読みにくいから。こういうときは「.pp_common_header」「.pp_sns_list」のように「_」で区切る。

接頭辞(名前系)

「接頭辞(名前系)は<body><div><span>にしか付けることができない」というルールを採用するか検討中。無駄にDOMが深くなるだけならやらない。

.sn_xxxxx

「サービス名(Service Name)」を表します。サイト内に存在する全てのHTMLの<body>ないし<html>につける。

.sn_xxxx .cp_pager{}
.sn_xxxx .cp_heading{}

などはサイト内共通パーツを表します。

.cp_pager{}
.cp_heading{}

サイト内で共通のパーツなら上記のように、何もつけなければ良いとも思いますが、他とセレクタ数を揃える意図がある。

.pn_xxxxx

「ページ名(Page Name)」を表します。ページ名クラス。

<body class="pn_index">...</body>

原則<body>につけます。
そのページ内で最上位に位置する場所に記述します。

このページ名クラスは、サイト内でユニークになるようにします。
URLと合わせると自然とそうなるはずです。
GETパラメータ付きのURLの場合はよしなに。

これ自体にCSSを定義してはいけません。
適用範囲の絞り込みにのみ使います。

.pn_index .cn_main_visual .p_main_visual{}

上記はトップページのみで適用されるメインビジュアルを定義します。

.gn_xxxxx

「グループ名(Group Name)」を表します。グループ名クラス。
原則<body>に、ページ名クラスと一緒に付けます。

<body class="pn_news_top gn_news">...</body>

これは例えば

/news/
/news/list/
/news/detail/

上記のようなURL構造を持ったニュースというコンテンツがあるとき

<body class="gn_news pn_news_top">...</body>
<body class="gn_news pn_news_list">...</body>
<body class="gn_news pn_news_detail">...</body>

のようにつけることで、ニュースコンテンツに共通で適用するCSSを定義できるようになります。

これ自体にCSSを定義してはいけません。
適用範囲の絞り込みにのみ使います。

div[class^="pn_news_"]{}

のように、クラス名の前方一致を使えば、グループ名は不要ですが、前方一致はパフォーマンスが悪くなるといわれているので避けました。
気にする程の影響があるのかは調べてないので不明。

.gn_news .cp_heading{}

上記は/news/配下で共通の見出しを定義しています。

.cn_xxxxx

  • 「コンテント名(Content Name)」を表します。コンテント名クラス。
  • 「.cn_xxxxx」は<div>にしかつけられないこととします(後述)。
<div class="lo_stage pn_news_top .gn_news">
    <div class="lo_stage__header">
        <div class="lo_content cn_header_content">...</div>
   </div>
   <div class="lo_stage__body">
        <div class="lo_content cn_news_list">...</div>
        <div class="lo_content cn_news_ranking">...</div>
        <div class="lo_content cn_news_archive_nav">...</div>
   </div>
   <div class="lo_stage__footer">
        <div class="lo_content cn_footer_content">...</div>
    </div>
</div>

コンテントとは、コンテンツ部分に、ある程度独立して定義できるブロックです。
上記は例としてニュースコンテンツのトップページを定義。
メインコンテンツに新着記事リスト(.cn_news_list)、記事ランキング(.cn_news_ranking)、記事アーカイブへの導線(.cn_news_archive_nav)をコンテントとして定義しています。

<ul class="cn_xxxxx">
    <li><a href="#">A</a></li>
    <li><a href="#">B</a></li>
</ul>

たとえ、コンテントの中身がリストだけだったとしても

<div class="cn_xxxxx">
    <ul>
        <li><a href="#">A</a></li>
        <li><a href="#">B</a></li>
    </ul>
</div>

必ず<div>ないし<section>でラップし、それにコンテント名クラスを付けます。

これ自体にCSSを定義してはいけません。
適用範囲の絞り込みにのみ使います。

接頭辞(レイアウト系)

.fr_xxxxx

「frame」の略で、サイトの基本骨格となるレイアウトを表すクラス名です。

.fr_stage

.fr_stageは、原則変わることのないサイトの骨格に使います。

<div class="fr_stage">
    <div class="fr_stage__header">
        <div class="fr_stage__header_inner">
                        (ヘッダー)
            <div class="fr_stage__section">コンテント</div>
        </div>
   </div>
   <div class="fr_stage__body">
                (ボディ=コンテンツ部)
        <div class="fr_stage__body_inner">
            <div class="fr_stage__body_main">
                (メインカラム)
                <div class="fr_stage__section">コンテント</div>
                <div class="fr_stage__section">コンテント</div>
                <div class="fr_stage__section">コンテント</div>
            </div>
            <div class="fr_stage__body_sub">
                                 (サイドバー)
                <div class="fr_stage__section">コンテント</div>
                <div class="fr_stage__section">コンテント</div>
                <div class="fr_stage__section">コンテント</div>
                <div class="fr_stage__section">コンテント</div>
            </div>
                </div>
   </div>
   <div class="fr_stage__footer">
        <div class="fr_stage__footer_inner">
                       (フッター)
            <div class="fr_stage__section">コンテント</div>
        </div>
    </div>
</div>

上記はPC版を想定、ヘッダー、コンテンツ部、フッターで、コンテンツ部はメインコンテンツとサイドバーを持ちます。

<div class="fr_stage">
    <div class="__header">
        <div class="__inner">ヘッダー</div>
   </div>
   <div class="__body">
        <div class="__inner">
            <div class="__main">メインコンテンツ</div>
            <div class="__sub">サイドバー</div>
                </div>
   </div>
   <div class="__footer">
        <div class="__inner">フッター</div>
    </div>
</div>

上記のように記述しても問題ないです。
上記のように書いた方がHTML的には見やすいし、ファイルサイズも小さくなります。
が、

.fr_stage{}
.fr_stage__header{}
.fr_stage__header_inner{}
.fr_stage__body{}
.fr_stage__body_inner{}
.fr_stage__body_main{}
.fr_stage__body_sub{}
.fr_stage__footer{}
.fr_stage__footer_inner{}

前者のHTMLに対するCSSが上記で、

.fr_stage{}
.fr_stage > .__header{}
.fr_stage > .__header > .__inner{}
.fr_stage > .__body{}
.fr_stage > .__body > .__inner{}
.fr_stage > .__body > .__inner > .__main{}
.fr_stage > .__body > .__inner > .__sub{}
.fr_stage > .__footer{}
.fr_stage > .__footer_inner{}

後者のHTMLに対するCSSが上記になります。
個人の趣向で前者にします。

.fr_stageの構成要素
.fr_stage
.fr_stage__header
.fr_stage__header_inner
.fr_stage__body
.fr_stage__body_inner
.fr_stage__body_main
.fr_stage__body_main_inner
.fr_stage__body_sub
.fr_stage__body_sub_inner
.fr_stage__footer
.fr_stage__footer_inner

※「 inner 」は必要に応じて。
※「 main 」「 sub 」は必要に応じて。(mainは1カラムのときでも書いておいた方が良いとは思う)

.fr_content

.fr_contentは.fr_stageのコンテンツとして収まるブロックです。
 <section>に近いものになります。
.fr_contentは必ず

DOMの深さは最小限に

CSSのセレクタは定義の右側から探される。

<div class="fr_stage pn_news_top">
    <div class="fr_stage__header">
        <div class="fr_content cn_header_content">...</div>
   </div>
   <div class="fr_stage__body">
        <div class="fr_content cn_news_list">...</div>
        <div class="fr_content cn_news_ranking">...</div>
        <div class="fr_content cn_news_archive_nav">...</div>
   </div>
   <div class="fr_stage__footer">
        <div class="fr_content cn_footer_content">...</div>
    </div>
</div>

コンテンツ部で各コンテントを定義するのに使う他、ヘッダーやフッターの中身も1つのコンテントとして扱うのが良いと思います。

.fr_stage__header .pp_site_name
.fr_stage__header .pp_site_description

のようにヘッダーの中身をヘッダーという構造物の1部として定義するのに違和感があります。

.fr_stage__header .cn_site_header .pp_site_name
.fr_stage__header .cn_site_header .pp_site_description

のように.cn_site_headerの子要素としてまとめます。

「.fr_stage」は棚で、「.fr_content」は棚に置くものです。
キャビネットの中に小物入れやファイルを置くイメージです。

.fr_content{}

.fr_content__header,
.fr_content > .__header{}

.fr_content__body,
.fr_content > .__body{}

.fr_contentは直接の子要素に.fr_content_header,.fr_contentbodyを持つことが可能です。
.fr_content
header,.fr_content_bodyのいずれも使わないという選択も可能です。

接頭辞(パーツ系)

.pp_xxxxx

「Private Part」あるいは「Personal Part」で固有パーツを表すクラスに使います。

<p class="pp_description"></p>
<ul class="pp_list">
<li>
<a href="#">aaaaaaaa</a>
</li>
<li>
<a href="#">aaaaaaaa</a>
</li>
<li>
<a href="#">aaaaaaaa</a>
</li>
</ul>
.cn_xxxx .pp_xxxx{}
.ppn_xxxxx .cn_xxxxx .pp_xxxx{}

CSSで定義する場合には、必ず「.cn_xxxx」の子要素として定義します。
これにより、少なくとも他の「.cn_xxxx」配下のパーツに影響が及ばなくなります。
意図しない継承や競合が起きにくくなります。

.cn_xxxx .pp_section_heading{
  font-size: 2.0rem;
  font-weight: bold;
  text-align: center;
}
.cn_yyyy .pp_section_heading{
  font-size: 2.0rem;
  font-weight: bold;
  text-align: center;
}

仮に上記の「.cn_xxxx」と「.cn_yyyy」の「.pp_setion_heading」が全く同じものであっても、それぞれ個別に定義します。
この辺りはSassを使ってカバーします。

.cp_xxxxx

「Common Part(共通パーツ)」を表します。
3箇所以上で使うことが想定されるパーツはこれで定義します。

.sn_xxxx .cp_pager{}
.sn_xxxx .cp_breadcrumb_nav{}
.sn_xxxx .cp_share_btn{}

上記はサイト全体の共通パーツになります。
.sn_xxxx は全ての<body>ないし<html>タグに付いています。

.gn_news .cp_heading{}
.gn_news .cp_pager{}
.gn_news .cp_breadcrumb_nav{}
.gn_news .cp_share_btn{}

上記は/news/配下の共通パーツになります。

.gn_news .cp_heading{
    border-bottom: solid 2px blue;
}
.gn_products .cp_heading{
    border-bottom: solid 2px red;
}

上記は/news/配下の見出しは青下線、/products/配下の見出しは赤下線といった使い方をすることが可能です。

.cn_news .cp_pager{}

のように定義した場合は、共通パーツをオーバーライドすることになります。

( .sn_xxxx > .gn_xxxx > .cn_xxxx > ( .pn_xxxx ) の順番で定義されるので )

.pp_pager{}

という定義は禁止です。
必ず「.xn__(sn,gn,cn,pn)」の子要素として定義します。

.u_xxxxxx

ユニットを表します。
複数のパーツから構成されるパーツです。

<div class="u_pager">
    <div><a href="" class="cp_pager__prev"></a></div>
    <div>
        <ul class="cp_page_numbers">
            <li><a href=""></a></li>
            <li><a href=""></a></li>
            <li><a href=""></a></li>
        </ul>
    </div>
    <div><a href="" class="cp_pager__next"></a></div>
</div>

例えばページャーです。
ページャーの最低構成要素は「前へ」「次へ」のリンクだと思います。
「1|2|3|4|5」のようなナビゲーションはオプションと考え、別のパーツとして定義します。
「前へ」「1|2|3|4|5」「次へ」のような構造のパーツの場合も十分にあるので、
この場合は「.u_pager」という複合パーツとして定義します。

.cp_pager{}
.cp_page_numbers{}

.u_pager .cp_pager{}
.u_pager .cp_page_numbers{}

「.cp_pager」と「.cp_page_numbers」はそれぞれ、独立して使える形で定義しておいて、
「.u_pager」で拡張します。

.cu_xxxxxx

共通ユニットを表します。
(必要か検討中)

.js_xxxxx

<a href="javascript:void(0)" class="js_toggle_menu">MENU</a>

JSで使うクラス名です。

<ul class="p_tab js_switch_tab">
  <li class="_is_current"><a href="javascript:void(0)">A</a></li>
  <li><a href="javascript:void(0)">B</a></li>
  <li><a href="javascript:void(0)">C</a></li>
<ul>
$(".js_switch_tab a").click(function(){
});

タブ切り替えのロジックなどで使う「._is_current」のようなクラス名は「.js_is_current」とする必要はありません。

.ga_xxxxx

.ga_global_nav__top{}
.ga_global_nav__news{}

Google Analyticsのクリックカウント用のクラス名です。

.ga_[URL]__[任意の名前]

が良いかと思います。

<a href="#" class="ga_news_detail__more_btn">もっと読む</a>

といった具合です。
ものすごく冗長に…。

HTML/CSS記述の原則

  • idはCSSのセレクタとしては使わない。使うのは<input id="a"><label for="a">くらいでしょう。
  • 画像のパスは絶対パス
<img src="/img/pc/logo.png" alt="">
.fr_stage{
    background-image: url("/img/pc/bg_1.png");
}

CSSの記述ルール

BEM的な定義をすると、どうしてもクラス名が冗長になるので、単語の省略を積極的に行います。

//agr = agreement
.cn_agr .pp_agr{}

//ntf = notification
.cn_ntf .pp_ntf_list{}
.cn_ntf .pp_ntf{}

のようにコメントで省略前の単語も記述しておくと、別の人が見たときに親切。

.cn_news_list
    .cp_news
        &__header
        &__body
            margin-top: 10px
        &__title
            font-weight: bold
        &__timestamp
            font-size: 1.2rem  

このとき、.cp_news__headerには何も定義していませんがSass上は、使っていなくても記述しておきます。
どんなクラス名が付いているかを網羅しておきます。
コンパイル時にスキップされるので問題ありません。

.cn_news_list{}
.cn_news_list .pp_news_list{}
.cn_news_list .pp_news_list_item{}
.cn_news_list .pp_news_list_item__img{}
.cn_news_list .pp_news_list_item__txt{}

.cn_news_ranking{}
.cn_news_ranking .pp_ranking{}
.cn_news_ranking .pp_ranking_item__img{}
.cn_news_ranking .pp_ranking_item__txt{}

CSSは、原則コンテントレベルで定義します。
これを徹底することで、意図しない継承が起きなくなります。

.pn_news_top .cn_news_list{}
.pn_news_top .cn_news_list .pp_news_list{}
.pn_news_top .cn_news_list .pp_news_list_item{}
.pn_news_top .cn_news_list .pp_news_list_item__img{}
.pn_news_top .cn_news_list .pp_news_list_item__txt{}
.pn_news_top .cn_news_archive .pp_news_archive_list{}
.pn_news_top .cn_news_archive .pp_news_archive_list_item{}

特定のページだけに適用させたいCSSがある場合は
「.pn_xxxxx」と「.cn_xxxxx」を組み合わせて使います。

.fr_content .pp_header

のように「.fr_xxxxx」起点で定義をしてはいけません。

.cn_article.fr_content
.cn_article > .fr_content__header
.cn_article .pp_header

のように、必ず「.cn_xxx」を起点とします。

.cn_news
    .pn_news_top &
        .p_heading{}

の出力結果は

.pn_news_top .cn_news .p_heading{}

のようになります。

.pn_xxxxを使っての定義は.pn_xxxxx起点より.cn_xxxxにまとめて記述した方が良いかもしれません。

オーバーライド

「.cp_xxxxx」「.cu_xxxxx」は共通パーツ、共通ユニットなので

.cp_pager{}

のように定義します。

 .cn_xxxxx .cp_pager{}

上記のように定義すると、共通パーツのオーバーライドになります。
パーツの内容自体は原則変えませんが、周りの余白などはこの形で調整します。

※そもそも「.cp_xxxxx」を作らず、Sassのミックスインで定義、必要な「.cn_xxxxx」内だけで呼び出すという手もあります。が、それをすると、デブツールで「ちょっとこのパーツ当ててみよう」とかができなくなります。

親子関係の定義

<div class="fr_stage">
    <div class="fr_stage__header">
        <div class="fr_stage__header_inner">
        </div>
   </div>
   <div class="fr_stage__body">
        <div class="fr_stage__body_inner">
            <div class="fr_stage__body_main"></div>
            <div class="fr_stage__body_sub"></div>
                </div>
   </div>
   <div class="fr_stage__footer">
        <div class="fr_stage__footer_inner">
                </div>
    </div>
</div>

親子要素であることを明示するために親要素と子要素を「__」で連結します。
上記は.fr_stageです。

.fr_stage{}
.fr_stage__header{}
.fr_stage__header_inner{}
.fr_stage__body{}
.fr_stage__body_inner{}
.fr_stage__body_main{}
.fr_stage__body_sub{}
.fr_stage__footer{}
.fr_stage__footer_inner{}

CSSを書くとしたら上記のようになります。
「.fr_stage」 + 「__」 + 「子要素」の形です。

この時「.fr_stage__footer_inner」のように子要素と孫要素などは「__(アンスコ2つ)」ではなく「_(アンスコ1つ)」で連結します。
個人的に、その方が見やすいと感じたためです。

親子関係を省略して記述

<div class="fr_stage">
    <div class="__header">
        <div class="__inner">
        </div>
   </div>
   <div class="__body">
        <div class="__inner">
            <div class="__main"></div>
            <div class="__sub"></div>
                </div>
   </div>
   <div class="__footer">
        <div class="__inner">
                </div>
    </div>
</div>

「.fr_xxxx」など共通部分を何度も書くのが面倒だと思うかもしれません。
DOM構造上、直接の子要素に対しては省略をしても良いと思います。

.fr_stage{}
.fr_stage > .__header{}
.fr_stage > .__body{}
.fr_stage > .__footer{}

ただし省略形を使う場合、CSSは必ず「>」で適用範囲を限定します。

.fr_stage > .__header > .__inner > .___main{}

こういう定義も可能です。
でも美しくないです。

状態を表すクラス名

「選択された状態」など状態の変化を表したい時があります。

._has_no_result
._is_first
._is_last
._is_public
._is_private
._is_for_guests
._is_for_members
._is_current
._is_available
._is_disabled

その場合、クラス名は上記のように「_」から始まるクラス名を併記します。

.pp_switch_item._is_current{}

使うときはのように、クラス名併記の形を取ります。
パフォーマンスが悪い記述と言われていますが

<li class="p_switch_item p_switch_item__is_current">
    <a href="#">A</a>
</li>

のようにクラス名を2つ定義するのは冗長過ぎます。

._current

ちなみに、ただ「._current」などとするのは止めたほうが良いかと。

要素型セレクタは原則使わない

.cn_news h1{}
.cn_news p{}

のように要素型セレクタを使った定義は原則禁止です。

ul{}
ul > li{}
ul > li > a,
ul > li > span{}
dl{}
dl > dt{}
dl > dd{}

ただし、上記のように子要素が限られている場合、
クラス名を付けたほうが上長になる場合は「>」を使って限定することを条件に定義可能。

<div class="cn_list">
    <ul class="p_list">
        <li><a href="#" class="p_list_item"></a></li>
        <li><a href="#" class="p_list_item"></a></li>
    </ul>
</div>
.cn_list .pp_list{}
.cn_list .pp_list > li{}
.cn_list .pp_list_item{}

でも

<div class="cn_list">
    <ul class="p_list">
        <li><a href="#"></a></li>
        <li><a href="#"></a></li>
    </ul>
</div>
.cn_list .pp_list{}
.cn_list .pp_list > li{}
.cn_list .pp_list > li > a{}

でもよしとする。

コーディング時の心がけ

バリデータを通す

納品物はバリデータをかけてエラーをなくしましょう。

PC版のは:hoverとかある

デザインに無かったら戻せばよい話。

画像を圧縮する

tinypngなどを使って画像サイズを小さくするとユーザーに優しいです。

リストページはN件時と0件時がある

検索結果など、結果をリストで表示するページでありがちなのが「0件時の表示」の存在です。

まず起こり得ない文字長のパターンで作る

デザイナーから納品されたデザインは「良い感じ」に収まっているものが少なくありません。
でも実際はそんなきれいに収まらないことが多く、その場合でも崩れないで表示できるHTML&CSSを作る必要があります。

英文対応

だいたいword-break: break-allで解消します。

レギュレーションを設定する

文字サイズ、文字色、罫線の色、余白など、サイト内で共通のルールを設定しておこう。

GA用のクラス名を付ける

GAクリックカウント用のクラス名を付ける癖をつけておくと幸せです。

画像

ディレクトリ

/img/
/img/common/
/img/pc/
/img/pc/news/
/img/sd/
/img/sd/news/

画像は「pc」「sd(smart device)」に分け、それ以下の構造はURLに準ずる。

ファイル名

  • ファイル、ディレクトリ名に利用できるのは半角英数字と「_」のみ
  • 半角英字は小文字のみ。単語と単語の区切りは「_」でどうぞ。
logo_01.png
icon_home_01.png
icon_back_01.png

とか接頭辞のように「.icon_」とか付けるのは…どうなんだろうか。要検討。現状していない。

JS

Pug

//- var root = "/"
- var root = "/test/"

a(href=root+”/”)

のように記述しておくと、環境が変わっても対応し易い。

よく使うクラス名と、その省略形

クラス名を短くすることはHTMLのファイルサイズを小さくすることと同義。
積極的に行なっていきます。
一見してわからない短縮は不便なので、極力実績のある省略形を心がけること。
既存でメジャーなフレームワークなどを参考にすると捗る。

例えばattributeは
jQueryでattr() と省略されている実績があるのでattrを使う。

また使用頻度が少なくて省略形が認知されていない場合は

//agr = agreement
.pp_agr{}

のように、定義の直前に省略形をコメントで書いておくと親切

.figと.txt

ニュース記事一覧など、右に(あるいは上に)サムネイル、左に(あるいは下に)テキストといった形の要素を作る機会が多い。その場合

.article
    .article__left
    .article__right

のようにすると、レスポンシブで上下になったときにおかしなことになる。

.article
    .article__main
    .article__sub

メインとサブはこれまで使ってきたが、画像がサブなんだっけ?といつも疑問に思っていた。

.article
    .article__fig
        img.article__img(src="")
    .article__txt
        .article__heading 見出し
        .article__ts 20xx/xx/xx xx:xx

とりあえず、今後はサムネイルが入る方はfig(=figure)、テキストが入る方はtxt(=text)という形で行こうと思う。

  • attribute = attr
  • header
  • heading = 見出し
  • description = desc = 概要など
  • title = ttl = タイトル(省略不要かも)
  • label

  • button = btn = ボタン

  • switch = スイッチ = タブなどでコンテンツを切り替えるもの

  • body

  • inner

  • outer

  • footer

  • article = 記事(postの方が短くて良いかも)

  • list = ls = リスト

  • list_item = ls_item

  • list_link = ls_link

  • agreement = agr = 同意文

  • notification = ntf = 通知

  • image = img

  • visual

  • txt

  • similar = 関連記事とか