アイキャッチ画像: デスクの上でパソコンを使用している

今回は Drupal.org で提案されている「 CSS フォーマットガイドライン」を翻訳してお届けできればと思います。

この CSS のガイドラインは、 Drupal 開発における CSS コーディングの指針としてコミュニティメンバーによって提案されているものです。 これまでご紹介してきた PHPJavaScript の「コーディングスタンダード」に比べるとまだ未成熟で議論の余地が残っている感じではありますが、チームで Drupal 開発を行う上で参考になるポイントがたくさん含まれているので、ふだん Drupal 開発を行う方には一読の価値ありかと思います。

Drupal CSS formatting guidelines page

また、 HTML と CSS にある程度なじみのある方であればこのガイドラインを理解・把握することができるかと思いますので、そんな方にもぜひ一読してみていただけるとうれしいです。 「少し細かすぎるかな」とも思えるくらい細かいところまで配慮が行き届いている感じなので、 Drupal コミュニティの「しっかり感」のようなものを感じ取っていただけるかと思います。

Drupal コーディングスタンダードなどと同様、今回も日本語としてのわかりやすさを重視し、ところによっては直訳、ところによっては意訳としています。 正確な原文のニュアンスが知りたい方はぜひオリジナルの方にあたってみてください。

では、以下 Drupal.org で提案されている CSS フォーマットガイドラインの日本語訳です。 バージョンは 2014 年 02 月 07 日最終更新のものをもとにしています。

目次

用語

CSS の用語になじみの薄い方のために、スタンダードの中で使われる用語をかんたんにあげておきます。

selector {
  property: value;
}

ルールセットルールともいう)はセレクタとそれに続く宣言ブロックで構成されます。

セレクタは最初の開きかっこ( { )の前までのすべてです。

宣言ブロックは開きかっこ( { )で始まり、それと対をなす閉じかっこで終わります。 その間に 0 個以上のセミコロン( ; )で分けられた宣言のリストがあります。

宣言プロパティ名とそれに続くコロン( : )ととで構成されます。

空白

インデント

多くのテキストエディタと(ウェブブラウザのような)ほとんどのテキストビューワには「タブサイズ」の設定がないため、インデントとしてのタブの使用はソースコードの見た目の不一致をもたらします。

インデントを必要とする行には、インデントのレベルごとに 2 つの空白を使いましょう。 これは Drupal の PHP コードと JavaScript コードのスタンダードと同じです。

  • 宣言(プロパティと値のペア)はそのセレクタに対してインデントをひとつ下げましょう。
  • メディアブロックやメディアクエリの中のルールセットはメディア文に対してインデントをひとつ下げましょう。
  • コメントは説明対象となる宣言やルールセットと同じインデントにしましょう。

    @media print { /* この行は空白 2 つでインデントされています。 空白 2 つ x 1 レベル。 / .example { / この行は空白 4 つでインデントされています。 空白 2 つ x 2 レベル。 */ padding: 0; } }

空行

  • 一般的に、各ルールセットを空行で分けることはよしましょう。
  • もしルールセットに Doxygen スタイルや 1 行スタイルコメントがつけらているなら、コメントの前に空行をひとつ置きましょう。
  • ふたつのルールセットが間に空行を持たないなら、それらは論理的に関係しているものであるべきです。もしルールセットが互いに論理的に関係しているのでなければ、空行またはふたつめのルールセットを説明するコメントを追加しましょう。

    /* ルールセットを説明するコメント。 */ .selector-1, .selector-2, .selector-3[type="text"] { -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; display: block; margin: 0; font-family: Times, "Times New Roman", sans-serif; color: #333; background: #fff; background: linear-gradient(#fff, rgba(0, 0, 0, 0.8)); } /**

    • このルールセットを説明するもっと長いコメント。
    • docblock の上の空行に着目してください。 / .selector-4, .selector-5 { padding: 10px; } / このルールセットの論理的なグループの間に空行はありません。 / .profile { margin: 1em 0; } .profile__picture { float: right; / LTR */ }

行末

行末には空白(スペースやタブ)を置いてはいけません。 これは空行にはスペースやタブを含んではいけないということも意味しています。 一貫性のない末尾の空白は diff / patch に行を追加し変更に気づきづらくしてしまうことがあります。

すべてのテキストファイルは改行ひとつで終えるようにしましょう。 これは git のコミットを読みやすくしてくれます。 なぜなら、ファイルの末尾に行が追加されたときの変更がより明確ですし、 patch における \ No newline at end of file 警告を回避してくれるからです。

ファイルは Unix の行末スタイル(改行文字 \n または LF )でフォーマットしましょう。 これは Mac OS X のデフォルトでもあります。 Windows の行末スタイル(キャリッジリターンと改行 \r\n もしくは CRLF )は使わないようにしましょう。

ヒント:あなたのエディタで「不可視文字を表示する」の設定をオンにしましょう。 これは行末の空白を削除し、意図しない空行の空白や汚染コミットを防ぐ手助けになるでしょう。

Drupal 8 では、これらの空白に関する規約への対応をサポートするためにルートディレクトリEditorConfig ファイルが入っています。

コメント

コードにきちんとコメントをつけることは非常に大切です。 コンポーネントについて、それがどう動作するのかとか、その限界、どのようなやり方でくみ上げられているのかといったことを説明する時間を割いてください。 一般的でなかったり明瞭でなかったりするコードのために他の人に推定をさせるのはやめましょう。

Drupal コードベースのその他の部分との一貫性を取るために、 Doxygen や PHP ファイルのコメントフォーマット規約から CSS のコメントスタイルを拝借しています。

ファイルコメント

各ファイルはそのファイルが行っていることを説明するコメントで始めましょう。 たとえば:

/**
 * @file
 * ファイルの短い説明。
 *
 * 長い説明の最初の 1 文はここから始まり、
 * パラグラフの終わりのところに達するまでこのように続いていきます。
 */

@file ドキュメントブロックの後には空行があることに注意しましょう。 可能なときは、 1 行の長さを 80 文字までとしましょう。 もっと多くの情報が見たい場合は PHP ファイルコメントスタンダードを参照してください。

複数行コメント

ひとつあるいはひとまとまりのルールセットを説明するときには、( 80 文字で折り返して) 2 行以上になるコメントはすべて Doxygen コメントスタイル(「 docblock 」ともいいます)に従うようにしましょう。

/**
 * Doxygen スタイルのコメントフォーマットを使った短い説明。
 *
 * 長い説明の最初の 1 文はここから始まり、
 * パラグラフの終わりのところに達するまでこのように続いていきます。
 *
 * 長い説明にはより詳しい説明とドキュメントがあると理想的です。
 * HTML や URL の例や、必要もしくは有用と思われるその他情報を含めてもよいでしょう。
 */
.example-rule {
}

ルールセットの直前の行にそれを説明するコメントを置きましょう。 docblock コメントの前には空行を置きましょう。 もっと多くの情報が見たい場合は Doxygen やコメントフォーマット規約をご覧ください。

1 行コメント

プロパティやルールセットを説明する際、 80 文字以内に収まるコメントについてはシンプルな CSS コメントスタイルを使うことができます。

.example {
  /* デフォルトのマージンをオーバーライドする。 */
  margin: 0;
}
/* これは .example コンポーネントの変異形です */
.example--item {
  display: inline;
}

プロパティやルールセットの直前の行にそれを説明するコメントを置きましょう。 コメントは説明対象のプロパティやルールセットと同じだけインデントしましょう。

コメントがルールセットを説明する場合は、コメントの前に空行を開けましょう。

右から左に読む言語のためのスタイル

RTL 言語(右から左に読む言語)のウェブサイトでは、左右を反転させたデザインにすることが一般的です。 方向に関するプロパティ/値については、 /* LTR */ コメントを同じ行に空白 1 つをはさんでからつけましょう。 Drupal 6 と Drupal 7 では、別個の RTL スタイルシートの読み込みが自動化されています。 Drupal 8 では、反対になるプロパティ/値を含むルールセットを、アトリビュートセレクタ [dir="rtl"] を先頭につけた形で追加しましょう。

Drupal 6 と Drupal 7 のルールセット例

[example.css]
.example-rule {
  float: left; /* LTR */
  margin-right: 1.5em; /* LTR */
  padding: 0 0.25em;
}
[example-rtl.css]
.example-rule {
  float: right;
  margin-left: 1.5em;
  margin-right: 0;
}

Drupal 8 のルールセット例

[example.css]
.example-rule {
  float: left; /* LTR */
  margin-right: 1.5em; /* LTR */
  padding: 0 0.25em;
}
[dir="rtl"] .example-rule {
  float: right;
  margin-left: 1.5em;
  margin-right: 0;
}
  • left 」や「 right 」などのキーワード、たとえば float: left; を使うとき
  • marginpaddingborder がボックスの左右で異なるところ、たとえば margin-left: 1em;padding: 0 0 0 2em;
  • 言語の方向を指定するとき、たとえば direction: ltr;

フォーマット

この CSS フォーマットスタイルは、コードを読みやすく、コメントしやすし、エラーを入れ込んでしまう事故の可能性を減らし、結果として git diff や git blame が有用になります。

ルールセット

  • ルールセットがコンマで分かれたセレクタのグループを持つ場合は、 1 つのセレクタにつき 1 行を使いましょう。
  • ルールセットの宣言ブロックの開きかっこ( { )はセレクタと同じ行(セレクタがグループの場合は最後のセレクタの行)に置きましょう。開きかっこの前には空白を 1 ついれましょう。
  • ルールセットの閉じかっこ( } )はルールセットのセレクタの最初の文字と同じ列に置きましょう。
  • 宣言ブロックの中では行ごとに 1 つの宣言を含めましょう。
  • 各宣言はそのセレクタに対してインデントを 1 レベル下げましょう。

ルールセットの例

.selector-alpha,
.selector-beta {
  counter-reset: section;
  text-transform: small-caps;
}

プロパティ

  • 宣言においては、プロパティ名の直後にコロンを置き、その後に空白をひとつ、そしてプロパティの値を書きましょう。
  • すべての宣言の後にはセミコロンを含めましょう。これには宣言ブロックの最後の宣言も含みます。
  • 色に対して 16 進数の値を使うときは小文字を使いましょう。可能なら短縮形、たとえば #aaa を使いましょう。色は CSS として正しいものであればどのような値でもかまいません。 16 進数値、色キーワード、 rgb()rgba() などです。 IE8 はすべてのカラーシンタックスをサポートしておらず、フォールバック値を必要とすることに注意してください。
  • 引用符を必要とするプロパティ値にはシングルクオートではなくダブルクオートを使いましょう。たとえば font-family: "Arial Black", Arial, sans-erif;content: " "; などです。
  • セレクタのクオートアトリビュート値には引用符をつけましょう。たとえば input[type="checkbox"]
  • それが許される場所では 0 という値に対して単位を指定するのはやめましょう。たとえば margin: 0px; ではなく margin: 0; を使いましょう。
  • コンマで分かれたプロパティや関数値では、各コンマの後に空白を 1 つ置きましょう。
  • 関数のかっこの周囲には空白を使わないようにしましょう。たとえば color: rgba(0, 0, 0, 0.8);

プロパティの例

display: block; 基本的なシンタックス

color: #fff 16 進数の色は可能な場合は短縮形を使いましょう

color: #df7dcf 必ず小文字を使いましょう

font-family: "Frutiger Ultra" シングルクオート( '' )ではなくダブルクオート( "" )を使いましょう

text-shadow: 0 0 2px #ddd 0 という値には単位をつけないようにしましょう

color: rgba(0, 136, 18, 0.8) プロパティや関数の値のコンマの後には必ず空白をつけなくてはいけません

宣言の並び順

ルールセットの宣言は、宣言ブロックの目的がもっとも明確になるように並べましょう。 明瞭さはガイドの原則です。 構造的に重要なプロパティを他のものよりも前に置くことがこのゴールを達成する手助けになるでしょう。まずポジショニング、ボックスモデルを記述し、それからその他のプロパティを記述します。

  1. ポジショニングのプロパティ: position float clear top right bottom left direction z-index
  2. ボックスモデルのプロパティ: display [(max|min)-]height [(max|min)-]width margin padding border 、それとこれらの長い形式( margin-top など)と box-sizing です。
  3. その他の宣言。

上記の各グループの中だと、プロパティはアルファベット順でまとめてもお互いに意味の近いものをまとめてもかまいません。 意味の近いものをまとめるというのはたとえば、フォントとテキストのプロパティを隣同士にするということです。 ( 2013 年現在)このポイントについてコンセンサスは得られていないため、このあたりの Drupal のコーディングスタンダードは意図的にあいまいにしてあります。 ただ、お互いの能力と好みを尊重するようにしています。

ベンダープレフィックスのプロパティはプレフィックスのないバージョンの直前に置きましょう。 こうすることで、公式のプロパティが実装された後は公式のプロパティがベンダープレフィックスのバージョンにあるばらつきをすべて上書きしてくれるようになります。 ブラウザのバグやクロスブラウザの問題のためにこの並び順を変える必要が出てきたときはドキュメントで明確に説明しましょう。

繰り返しになりますが、このプロパティの並び順はルールセットの目的を強調するためのものです。 ですので、プロパティの並び順について懸念するよりも、ルールセットにコメントをつけることの方が断然大切です

.selector {
  /* Positioning declarations */
  position: absolute;
  top: 0;
  left: 0;
  z-index: 10;
  /* Box model declarations */
  display: inline-block;
  width: 100px;
  padding: 10px;
  border: 1px solid #333;
  /* Other declarations */
  background: #000;
  color: #fff;
  font-family: sans-serif;
  font-size: 1.1em;
}

CSScomb のようなツールがプロパティの並び順の処理を自動化するのに役立つかもしれません。

例外とわずかに異なるパターン

単一宣言のブロックが大きな場合には、わずかに例外的な 1 行フォーマットを使ってもかまいません。 この場合は、開きかっこの後と閉じかっこの前に空白を置きましょう。

.selector-1 { width: 10%; }
.selector-2 { width: 20%; }
.selector-3 { width: 30%; }

コンマで分かれた長いプロパティ値ーー gradientshadow のコレクションのようなものーーについては、読みやすさを向上し、より有用な diff を生成するために複数行にわたって書いてもかまいません。

.selector {
  background-image:
    linear-gradient(#fff, #ccc),
    linear-gradient(#f3c, #4ec);
  box-shadow:
    1px 1px 1px #000,
    2px 2px 1px 1px #ccc inset;
}

メディアクエリ

メディアクエリはルールセットと同じスタイルで書きましょう。 その中に入るルールセットはすべて空白 2 つでインデントしましょう。

メディアフィーチャと値の間には空白を 1 つ入れます。 そうすることが不適切でないかぎりすべての値は em で書きましょう。 コメントにおけるピクセルの値は開きかっこの直後に追加しましょう。

@media screen and (min-width: 28.125em) { /* 450px */
  #page {
    margin-left: 1.25em;
    margin-right: 1.25em;
  }
}

その他もろもろ

@charset 文

文字セット文( @charset "UTF-8" のようなもの)は、 CSS の最上部にある場合のみ有効です。 Drupal の CSS アグリゲータは複数の CSS ファイルをひとつのファイルにまとめ、まとめたファイルが正しい CSS となるよう Drupal は @charset 文をすべて取り除きます。

これは CSS ファイルが @charset 文を一切含んではならないことを意味しています。 デフォルトの CSS ファイルのエンコーディングは UTF-8 です。 CSS コメントやコンテンツプロパティの値は UTF-8 でエンコードしなければいけません。

実践的な例

さまざまな規約をおさえた例になります。

/**
 * @file
 * このテーマのレイアウト。
 */
/**
 * 水平スクロールのカラムレイアウト。
 *
 * これは最大高さでラッピングのないカラムの単一行を作ります。
 * この行は親要素の中で水平に閲覧することができます。
 *
 * HTML の例:
 *
 * <div class="grid">
 *   <div class="cell cell-3"></div>
 *   <div class="cell cell-3"></div>
 *   <div class="cell cell-3"></div>
 * </div>
 */
/**
 * グリッドコンテナ
 *
 * 「 .cell 」要素のみを子供に取ります。
 */
.grid {
  height: 100%;
  /* 内部のセルの空白を取り除く */
  font-size: 0;
  /* inline-block セルのラッピングを防ぐ */
  white-space: nowrap;
}
/**
 * グリッドセル
 *
 * デフォルトでは明示的な width はない。
 * 「 .cell-n 」クラスで上書きする。
 */
.cell {
  position: relative;
  display: inline-block;
  overflow: hidden;
  box-sizing: border-box;
  height: 100%;
  /* 内部のセルのスペースを設定 */
  padding: 0 10px;
  border: 2px solid #333;
  vertical-align: top;
  /* 空白をリセット */
  white-space: normal;
  /* フォントサイズをリセット */
  font-size: 16px;
}
/* セルの状態 */
.cell.is-animating {
  background-color: #fffdec;
}
/* セルの次元 */
.cell-1 { width: 10%; }
.cell-2 { width: 20%; }
.cell-3 { width: 30%; }
.cell-4 { width: 40%; }
.cell-5 { width: 50%; }
/* セルの修正子 */
.cell--detail,
.cell--important {
  border-width: 4px;
}

このガイドラインのテキストは Nicolas Gallagher の writing, consistent, idiomatic CSS の原則に基づいています。

・・・以上です。

いかがだったでしょうか? あまり CSS になじみのない方にも、すでにたくさん CSS を書いている方にも何らかの参考になるポイントがあったのではないでしょうか。

これまでにも以下のような Drupal.org 上で提案されたコーディングスタンダードを翻訳しました。 こちらもよろしければあわせてご覧ください。