チーム作業をするための最適なCSS規約、Sassについて考えた

こんにちは、エンジニアの尾形です。

前回のブログではHTML/CSSコーディングを行なうにあたっての事前準備についてお伝えしました。
今回はCSS規約やSassによるコーディングの実例について、ごく一部ではありますが、ご紹介します。

FLOCSSをベースとした構成について

前回のブログで少し触れましたが、CSSコーディングを行なうにあたり、FLOCSSをベースとしたCSS規約を作成しました。
数あるCSS方法論の中でFLOCSSを採用した理由は以下の通りです。

  • コンポーネントの概念がエンジニアにとって馴染みやすい。
  • 候補のひとつであったBEMの概念が含まれている。命名しやすい。Sassとの相性が良い。
  • 再利用性や拡張性が高く、機能追加や仕様変更に柔軟に対応できそう。
  • 情報量が比較的多くわかりやすい。

FLOCSS本家サイト
hiloki/flocss: CSS organization methodology.

FLOCSSのカスタマイズ事例も公開されていましたので、こちらをベースとしました。
styleguide/css-coding-rule.md at master · manabuyasuda/styleguide

ファイル・ディレクトリ構成は以下の通りとしました。なお、Sassを使用しています。

(root)
|-- foundation/
|   |-- base/
|   |-- function/
|   |-- keyframes/
|   |-- mixin/
|   |-- variable/
|   |-- vendor/
|   `-- vendor-extension/
|-- layout/
`-- object/
    |-- component/
    |-- project/
    |-- scope/
    `-- utility/

FLOCSSは次の3つのレイヤーと、Objectレイヤーの子レイヤーで構成されます。

1. Foundation - プロジェクトにおける基本的なスタイル
2. Layout - ページを構成するコンテナーブロックのスタイル
3. Object - プロジェクトにおけるビジュアルパターン
  3.1 Component - 小さな単位のモジュール
  3.2 Project - プロジェクト固有のパターン
  3.3 Utility - 便利クラス、汎用クラスなど

今回のプロジェクトでは、前述した構成にあるようにFoundationレイヤーに子レイヤーを追加しました。レイヤーというよりはグループに近いです。グループ化して構成をすっきりさせるのが狙いです。

  1.1 Base - 要素セレクタと属性セレクタのデフォルトスタイル
  1.2 Function - プロジェクト全体で使用される@function
  1.3 Keyframes - プロジェクト全体で使用される@keyframes
  1.4 Mixin - プロジェクト全体で使用される@mixin
  1.5 Valiable - プロジェクト全体で使用される変数
  1.6 Vendor - 外部のライブラリやフレームワーク
  1.7 Vendor-Extension - Vendorレイヤーの上書き

また、Objectレイヤーにも子レイヤーを追加しました。ここではComponentやProjectのコンポーネント単位ではなく、それより大きな括りでのスタイルを定義します。ページ固有のスタイルもここで定義しました。

  3.4 Scope - ページ内のスコープでのスタイル

カスケーディングについても少し触れたいと思います。カスケーディングはCSSの大きな特徴のひとつです。カスケーディングとは、ある要素のあるプロパティに対する宣言が複数あるときに、ひとつの宣言だけが有効になるようにする仕組みのことです。カスケーディングの管理が煩雑だとCSSが破綻していきます。FLOCSSにおいては、後ろのレイヤーになるほど抽象的なスタイルから具体的なスタイルになり、カスケーディングにおいて強いルールにする必要があります。
上記を踏まえ、レイヤーの読み込み順序は以下のようになっています。

@import "foundation/variable/";
@import "foundation/vendor/";
@import "foundation/vendor-extension/";
@import "foundation/base/";
@import "foundation/function/";
@import "foundation/mixin/";
@import "foundation/keyframes/";
@import "layout/";
@import "object/component/";
@import "object/project/";
@import "object/scope/";
@import "object/utility/";

命名規則について

命名規則はFLOCSSの規約に従って、BEMをベースにしたMindBEMding を採用しました。BEMは、Block、Element、Modifierという3つの概念で構成されます。BEMを使用すると、命名ルールが統一され、HTMLを見ただけでBlockの範囲をとらえることが容易になります。また、再利用性、拡張性も向上し、開発のしやすさ、メンテナンスのしやすさにもつながります。

Objectレイヤーのモジュールに対しては、役割の明確化と名前の重複を避けるために以下の接頭辞を付与しました。

  • Component – `.c-*`
  • Project – `.p-*`
  • Scope – `.s-*`
  • Utility – `u-*`

FLOCSSではマルチクラスパターンを基本としていますが、今回の開発ではシングルクラスを基本としました。マルチクラスとシングルクラスの違いを簡潔に言うと、部品の組み合わせをHTML側で行なうかCSS側で行なうかの違いです。シングルクラスを採用した理由は、開発メンバーはオブジェクト指向でのプログラム開発に慣れており、Sassの@extendを使用したシングルクラスの方が馴染みやすくコーディングしやすかったためです。

シングルクラスの例を挙げると以下のようになります。

.button {
  display: inline-block;
  cursor: pointer;
}
.button--primary {
  @extend .button;
  background-color: #CCAA00;
}
.button--secondary {
  @extend .button;
  background-color: #FFCC00;
}

BEMを使用すると、子要素が多い場合にElementが複数になることがあり、マークアップの仕方にバラつきが出ることがあります。
今回はバラつきを避けるために以下のようなルールを追加してマークアップしました。

<ul class="nav">
  <li class="nav__item">
    <ul class="nav__item-items">
      <!-- 3単語で区切る場合 -->
      <li class="nav__item-items-item">
          <!-- ここから子孫として新Blockにします。 -->      
          <a href="#" class="link"></a>
      </li>
      <li class="nav__item-items-item">
          <a href="#" class="link"></a>
      </li>
    </ul>
  </li>

  <li class="nav__item">
    <!-- 2単語で区切る場合 -->
    <ul class="nav__item-items">
      <!-- ここから子孫として新Blockにします。 -->      
      <li class="item">
          <!-- 新Blockに対してBEMでElementを追加します。 -->      
          <a href="#" class="item__link"></a>
      </li>
      <li class="item">
          <a href="#" class="item__link"></a>
      </li>
    </ul>
  </li>

</ul>
  • .nav__itemの子要素は.nav__item-items、.nav__item-items-itemのようにBlock__Elementの後に-を区切りとしてElementを追加していきます。
  • Element名自体に-が含まれる場合も、Element区切りの-との区別は設けません。
  • ElementはBlockのスコープから飛び出してはいけません。
  • Element名は3単語までとします。それ以上の入れ子となる場合は、ブロックをリセットして子孫とします。
  • 3単語で区切る際に3単語目がBlockになってしまう場合は2単語でBlockをリセットします。

Sassは以下のようになります。

// 3単語で区切る場合
.nav {
    &__item {
    }
    &__item-items {
    }
    &__item-items-item {
        // ここで親Blockをスペース区切りで指定して、子孫として新Blockにします。
        // 子Block名は親Block内でユニークであれば任意の値で問題ありません。
        & .link {
        }
    }
}

// 2単語で区切る場合
.nav {
    &__item {
    }
    &__item-items {
        // ここで親Blockをスペース区切りで指定して、子孫として新Blockにします。
        // 子Block名は親Block内でユニークであれば任意の値で問題ありません。
        & .item {
            // 新Blockに対してBEMでElementを追加します。
            &__link {
            }
        }
    }
}

上記の場合、CSSは以下のようになります。

// 3単語で区切る場合
.nav {}
  .nav__item {}
  .nav__item-items {}
  .nav__item-items-item .link {}

// 2単語で区切る場合
.nav {}
  .nav__item {}
  .nav__item-items {}
    .nav__item-items .item {}
      .nav__item-items .item__link {}

プロパティの宣言順

CSSのルールセット内のプロパティの宣言は、機能ごとにまとめて記述することでCSSの可読性が上がると思います。例えば、表示方法に関するプロパティ(display, visibility など)、位置に関するプロパティ(position, z-index など)、フォントに関するプロパティ(font-size, line-height など)などのことです。
ただ、これらの宣言順序を各開発メンバーが意識しながらコーディングするのでは効率が悪いので、CSSのプロパティを自動で並べ替えしてくれる CSScomb というツールを使用して、開発メンバー間で同じような記述となるようにしました。

開発メンバーが使用していたエディター(IDE)は、Atom、PhpStorm、NetBeans、VisualStudioCodeとバラバラでしたが、どのエディターにもCSScombのプラグインは提供されていました。蛇足ですが、私は Eclipse -> NetBeans -> VisualStudioCode とエディターを乗り換えて今に至りますが、キーバインディングはEclipseのものをずっと使用しています。操作感を特に変えずにエディターを変更できるのは良いですよね。

いま現在は、VisualStudioCodeを利用しているメンバーが多くなってきています。その理由は、TypeScript言語での開発をメインで行っており、その点においてほかのエディターと比べて秀でていると感じたためです。(感想には個人差があります)

エンジニアとデザイナーの思考の違い

本筋から外れますが、今回SPAの開発を行なうにあたり、デザイナー(非エンジニア)とエンジニアが協働してデザイン・UI/UXを作り上げ、ともにHTML/CSSコーディングを行ないました。その際に感じた点を少しお伝えしたいと思います。

我々エンジニアは「ボタン」や「入力ボックス」などの最小単位の部品(オブジェクト指向で言うオブジェクト)から考える傾向にあります。それとは逆にデザイナーは全体のレイアウトを考えてから内部の部品を考える方が多いのではないでしょうか。

そのため、エンジニアがコーディングを行なう際に「あの画面とこの画面で微妙にデザインが違う!同じにして!」というのはよくあると思います。もちろん明確な理由があってデザインを変えているケースはあると思いますが、エンジニアにとってはできるだけ共通の部品を使用してコード量を減らしたいですよね。

この思考に違いについては、デザイナーにもFLOCSSでHTML/CSSコーディングを行なってもらいオブジェクト指向の考え方を理解してもらうことで、隔たりを埋められたと思っています。念のためお断りしておくと、一方的にエンジニアの思考を押し付けたわけではありません。我々エンジニアも類似サービスの調査等を通してUI/UX設計について理解を深める努力をしました。デザインに関して疑問が生じた際は、そのようにした理由・経緯をデザイナーから説明してもらいエンジニアが納得したうえで進めるようにしました。お互いの思考を理解しあって歩み寄ることも必要だと思います。

まとめと予告

今回はCSS規約やSassによるコーディングの実例について、ごく一部ではありますが、書かせていただきました。
次回はSassコーディングを行なう上で必要となる各種自動化の話について紹介させていただきたいと思います。

引用元・出典
hiloki/flocss: CSS organization methodology.
styleguide/css-styleguide.md at master · manabuyasuda/styleguide
styleguide/css-coding-rule.md at master · manabuyasuda/styleguide

第3回
Sassコーディングを行なう上で必要となる各種自動化の話
– タスクランナーgulp(概要説明)
– Sassコンパイル(変更を検知して自動コンパイル、ベンダープレフィックス、minify)
– ブラウザへの反映(browser-syncの話)

フロントエンドエンジニアへの道

1- HTML/CSSコーディングはじめるぞ〜HTML/CSSコーディングを行なうにあたっての事前準備
2- チーム作業をするための最適なCSS規約、Sassについて考えた
3- Sassコーディングを行なう上で必要となる各種自動化の話
4- Angular1によるSPA開発 – 基本編
5- Angular1によるSPA開発 – 設計編
6- Angular1によるSPA開発 – Tips編

HTML/CSSコーディングはじめるぞ〜HTML/CSSコーディングを行なうにあたっての事前準備

はじめまして。エンジニアの尾形です。

いま現在、HTML5/CSS3/Angular1を使ったシングルページアプリケーション(SPA)の開発を行なっています(自社サービスとして近日中にローンチ予定です)。

私はプレーイングマネージャーとして、このSPA開発に携わっており、開発環境・インフラ周りも担当しています。
もちろん、コーディングも行ないます。

開発チームは私を含めて4人体制ですが、チーム発足当初、我々にはフロントエンドエンジニアとしてのスキルが不足していました。そこで、フロントエンドエンジニアとなるべく奮闘が始まったのですが、開発の過程で感じたこと、苦労した点などを、今回から数回にわたって紹介していきたいと思います。

まず、フロントエンドエンジニアとは?何をする人たちなのか

フロントエンドエンジニアとは?と聞かれたあなたはどう答えるでしょうか。

フロントエンジニアの定義は各社によって異なると思いますが、当社では「HTML/CSS/JavaScriptのコーディングだけでなく、UI/UXの設計、フレームワークやライブラリの選定、API等のサーバーサイドのプログラミングも含めて、WEBサイトの制作ができる人」と定義しています。

このような考え方の会社さんが多いのではないでしょうか。

開発チームでは、これまでにWEBサイトの制作をいくつも行なってきましたが、モダンなサイトにしたい場合は、デザイン(見た目)とHTML/CSSのコーディングを外部業者に委託していました。
しかし、今回自社サービスを立ち上げるにあたり「デザインもコーディングもすべて自社でやろう!フロントエンドエンジニアになろう!」というミッションのもと、開発を進めることになったのです。

デザイン/CSSを外注していたことから、我々開発チームにはデザイン/CSSの知識が不足していました。
また、SPAの開発を行なう上では、ブラウザー側でのコンポーネントの管理やルーティングなどの処理も必要となるため、JavaScriptの知識もこれまで以上に必要となります。

各メンバーにはjQuery/Ajaxでの開発経験がありましたので、jQueryでSPAを実装するのも一案でしたが、かなりの労力がかかることが想定されたため(もちろんjQueryで事足りるケースもあると思います)、SPAフレームワークも導入することにしました。

このような状況では「私たちはフロントエンドエンジニアです」とはとても言えません。 ここからフロントエンドエンジニアへの道のりが始まります。

HTML5/CSS3の基礎知識を身につける〜すぐにできたことはこれだ!

これまでにもWEBサイトの制作は行なっていましたので、HTMLは書くことができますし、CSSもある程度は読み書きすることができました。
しかし、HTMLの知識はHTML4がベースとなっており、HTML5/CSS3についてはきちんと学習したことがなかったため、オンラインの学習サービスと書籍を併用し、HTML5/CSS3の学習を行ないました。学習期間は3日程度でした。

書籍は以下を利用しました。参考までに。

これらの学習が終わったら「習うより慣れろ! 実際にコーディングを始めよう!」・・・とはいきません。

CSSの規約の策定が必要でした。

CSS規約をつくるために考えたこと

CSSのコーディングを始める前に、最低限以下の事項(項目)を決定する必要があります。

– マルチクラスにするかシングルクラスにするか?
– クラスの命名規則をどうするか?

これらは、CSSの設計方法(方法論)として各種提唱されており、OOCSS、BEM、SMACSS、FLOCSS、ITCSS などが有名かと思います。わかりやすさ(初心者にとっての開発しやすさ)が重要だったり、メンテナンス性が重要だったりと、ケースによって重視するポイントは異なってくると思いますので、どれが正解でなにが優れていると、一概に言えるものではありません。

サイトやチームの特性を考慮したうえで、それに適した方法論を採用することになると思います。
我々のチームでは、FLOCSSをベースとして一部をカスタマイズする形式をとりました。その内容については、次回ご紹介したいと思います。

hiloki/flocss: CSS organization methodology.

– CSSプリプロセッサー(Sass や Less)を導入するか? 導入するとコーディングの効率化、簡略化が見込めます。

我々のチームでは、導入以外の選択肢はありませんでした。

全員エンジニアなので導入の敷居が低かったこともありますが、エンジニアは少しでも楽をしたいと常日頃思っていますからね。

実際にCSSコーディングを行ない、CSS規約をブラッシュアップする

CSS規約ができたら、実際に規約に従ってサンプルページのコーディングを行なってみました。

実際にコーディングを行なってみると、改善すべき点や追加すべき規約も浮き彫りになってきますので、規約をブラッシュアップしていくことになります。

テキストボックスやボタンなど、共通的に使用可能なスタイルは部品化する。
さらに、部品化したスタイルについて、使い方やマークアップ例をスタイルガイドにまとめます。

今回は「sc5-styleguide」というスタイルガイドジェネレーターを使用しました。
CSSファイルに所定の形式でコメントを記述すると、自動でスタイルガイドを生成してくれるので、重宝しました。


SC5/sc5-styleguide: Styleguide generator is a handy little tool that helps you generate good looking styleguides from stylesheets using KSS notation

また、CSSの規約だけではなく、HTMLに関する規約も追加する必要が出てくることがあります。
たとえば、

・フォームのボタンには<button>タグもしくは<input type=”button” />タグを使用します。
・<a>タグは不可(disabledが効かないため)。

などです。

今回はCSSコーディングを行なうにあたっての事前準備について書かせていただきました。

次回はCSS規約の実例について紹介させていただきたいと思います。

第2回
CSS規約(FLOCSS+α)、Sassについて
– FLOCSSをベースとした構成 (ディレクトリ、ファイル構成)
– 命名規約 (BEMを拡張した話、シングルクラス)
– プロパティの宣言順 (csscombでルールを定義して自動で並べ替え・フォーマットする話)
– 蛇足でエディタの話 atom, vscode, webstorm, netbeans
– エンジニアとデザイナーの思考の違い (少し脱線するが、非エンジニアにFLOCSSのオブジェクト指向(プログラム寄り)を理解してもらい、コーディングしてもらう話)

フロントエンドエンジニアへの道

1- HTML/CSSコーディングはじめるぞ〜HTML/CSSコーディングを行なうにあたっての事前準備
2- チーム作業をするための最適なCSS規約、Sassについて考えた
3- Sassコーディングを行なう上で必要となる各種自動化の話
4- Angular1によるSPA開発 – 基本編
5- Angular1によるSPA開発 – 設計編
6- Angular1によるSPA開発 – Tips編

今後の連載予定について〜予告!

フロントエンドエンジニアへの道:完結しました。

第2回
CSS規約(FLOCSS+α)、Sassについて
– FLOCSSをベースとした構成 (ディレクトリ、ファイル構成)
– 命名規約 (BEMを拡張した話、シングルクラス)
– プロパティの宣言順 (csscombでルールを定義して自動で並べ替え・フォーマットする話)
– 蛇足でエディタの話 atom, vscode, webstorm, netbeans
– エンジニアとデザイナーの思考の違い (少し脱線するが、非エンジニアにFLOCSSのオブジェクト指向(プログラム寄り)を理解してもらい、コーディングしてもらう話)
第2回は 6/26 (月) に公開予定です。ご期待ください。

第3回
Sassコーディングを行なう上で必要となる各種自動化の話
– タスクランナーgulp(概要説明)
– Sassコンパイル(変更を検知して自動コンパイル、ベンダープレフィックス、minify)
– ブラウザへの反映(browser-syncの話)
第3回は 7/10 (月) に公開予定です。ご期待ください。

第4回
Angular1 基本編
– はじめに(Angular2, Angular4がリリースされたのにAngular1を使っている経緯。Angular2への移行を見送った話)
– TypeScriptでコーディングする(静的型付けの重要性)
– TypeScriptの型定義ファイルについて(@typesパッケージを使用。@typeで提供されていないモジュールや自作した型定義についてはtypingsを使用)
– ライブラリーについて(jQueryとの共存)(基本はnpmリポジトリを使用。npmに存在せずbowerにのみ存在する場合のみbowerを使用)
– ディレクトリー構成(サンプル紹介)
– 自動コンパイルについて(gulpタスクの紹介)
– minify対策について(対策しないとエラーになる話)

第5回
Angular1 設計編
– コンポーネント指向設計について(Angular1からAngular2への移行を視野に入れコンポーネントを使っている話)
– ライブラリーの機能はwrapして使うべし($httpのカプセル化、$scope.$broadcast()のカプセル化など)
– 環境固有の設定について(サンプル紹介)
– バリデーション(入力チェック)について(サンプル紹介)

第6回
Angular1 Tips編
– URLによる二重クリック対策(サンプル紹介)
– ネットワークオフライン検知について(サンプル紹介)
– $scope.$watch() や $scope.$on() でイベントのリスナーを登録する際の注意事項(監視が不要になった時点でリスナーを解除する必要がある)
– jQueryによるDOMの変更をAngular側へ通知する(trigger(‘change’)のイベントを使用すること。trigger(‘input’)はIEで動作しない)
– ng-repeat でユニークキー重複エラー(Angularが生成するhash keyが重複するケースがある)

開発者ブログをはじめます

開発者ブログはじめます。

はじめまして、代表の大井田です。
このたび、自社の開発者ブログをはじめることにしました。

なぜ、開発者ブログをはじめるに至ったか簡単な経緯をお話ししたいと思います。

当社は、サーバ構築・保守・Webシステムの受託開発等を主な業務としています。
お客様ソリューションありきのシステム開発となるため、当たり前ですが、重要なファクターの一つに低コストを念頭に考えなければなりません。

しかしながら、今の時代は新しい技術やコーディング手法等が沢山出てきていて、エンジニア魂としては、
本当に良いプロダクトを作る上で、いろいろと試したい技術やソリューションが沢山あります。

あ、僕はもともとエンジニアでした。。
昔はガリガリ書いていましたが、今は優秀な社員が沢山いるので、僕はもうコーディングはしていませんけど。
<続きを読む>