はてなにおけるCSSメタ言語(CSSプリプロセッサ)の導入について

こんにちは、id:tikedaです。数年前から登場して以来、利用されるケースが増え続けているCSSメタ言語CSSプリプロセッサ)。近年、様々な大規模サービスへの導入が進む中、はてなのサービス開発においても導入を行うため、2012/3/6に勉強会を実施しました。その内容を公開いたします。CSSメタ言語そのものの説明よりも、社内導入の為に必要な内容が中心となります。

アジェンダ

  • どんなものがあるか
  • 導入の背景と目的
  • はてなでの選択
  • 何がやれるか
  • どう使うか
  • 事例・実演
  • 運用ルール
  • 今後の展望

どんなものがあるか

Sass(scss,sass)
f:id:tikeda:20120305162511p:image
http://sass-lang.com/
PCSS(他色々)
f:id:tikeda:20120307112446p:image
http://pcss.wiq.com.br/

導入の背景

前提条件
デザイナー目線での導入
  • フロントエンド専門のエンジニアやマークアップのスタッフはおらず、基本的にはデザイナーがCSSを書く
  • エンジニアも時々書く
  • プロジェクト型の組織体制である
  • テンプレート(Perl Template Toolkit)をデザイナーも触っている
問題意識
  • デザインできたんですがコーディングが苦手です
    • CSSより書きやすいと思うので頑張る
  • CSSは可読性悪くて何がどこに書いてあるか忘れました
    • →Nesting
  • ベンダープレフィックスがいっぱいでみずらいです
    • →Mixins
  • グレーは999かAAAか忘れたのでA9A9A9にしておきます
    • →Variables

導入の目的

以下のような仮説が考えられる
仮説
  • 便利な機能が使える為、CSSコーディングコストを減らすことができる
  • 複数人でサービス開発をする組織において、記述ルールが統一され可読性が向上される事でメンテナンスコストが下がる
  • 構造的なCSSを書くことでシンプルかつ統一したインターフェイスを効果的にユーザーに提供することができると考える
個人的な見解
  • 個人的な観点では3つめに述べた「統一しシステム化されたデザインをユーザーに提供しやすくなる」という仮説に目を向けている
    • これまで、社内的にはHatena-touch.css、汎用CSSの運用や、世間的にはreset.css960gsblueprintLess Frameworkといった様々なCSSフレームワークがあるが、これらと組み合わせ、上手に使いこなす事によってUIデザイン標準化への取り組みがこれまで以上に強力におこなえると考える。

はてなでの選択

どれを選ぶかは、組織体制、開発環境、仕事分担など状況において変わってくると考える。
Less
f:id:tikeda:20120305162510p:image
  • CSSに近い記述ルール
  • 特別な環境構築の必要がない。導入が楽
  • 導入・撤退が比較的楽に思える
  • 厳密な書き方をする必要がない
  • 接頭子などsassより少ない
    • mixin, extendの選択を考えなくてすむ。もちろんデメリットもあるが。
  • Twitter Bootstrapなど比較的大規模なフレームワークにも採用されてる
  • シンプルで導入が現実的なライブラリもある
    • 詳しくは後述

何がやれるか

代表的なものを実践を踏まえ紹介
  • Nesting
  • Variables
  • Mixins
  • Color functions
Nesting
.section {
  img {
    border: 0;
    &.profile-image {
      float: left;
      width: 32px;
      // 以下解説
      #nav & {
        float: none;
        width: 16px;
        vertical-align: middle;
      }
    }
  }
}
Variables
@link  : #000666;
@vlink : #0000ff;
@margin: 10px;
@domain: "http://www.hatena.ne.jp/images/";

a {
  color: @link;
  &:visited {
    color: @vlink;
    // 要注意
    background: url("@{domain}icon.gif") 0 50% no-repeat;
  }
}

div {
  margin:@margin;
  &.long {
    margin:@margin * 2;
  }
}
Mixins
.border-radius (@radius: 3px) {
  border-radius: @radius;
  -webkit-border-radius: @radius;
  -moz-border-radius: @radius;
  -o-border-radius: @radius;
  -ms-border-radius: @radius;
}

.button {
  .border-radius;
  &.large {
    .border-radius(10px);
  }
}
Color functions
実践向きではないが、参考まで
@color: #5279e7;
@link : @color; 
@vlink: lighten(@color, 10%);
@alink: darken(@color, 10%);

.more {
  a {
    color: @link;
    &:visited {
      color: @vlink;
    }
    &:active {
      color: @alink
    }
  }
}
その他色々... 詳しい事はhttp://lesscss.org/などを読んでください。

Compile

.less → .css
いくつかの手段
lessc styles.less > styles.css
  • 開発環境組み込み
手段の選択
すぐに導入させられる
  • 基本的にCompilerアプリ(今すぐに導入可能)
    • コンパイル時間は体感的にはほとんど意識しないですむ。(5000行程度までテスト)
  • 今後の検証しだいでコマンドライン
    • まだ未検証
    • 要開発
補足
Compilerの選択
書き出すCSSを統一したいので、Compilerは限定させる。別のものを利用した場合何度かConfrictを経験

実例紹介

いくつかのサービスにおいて早速導入し、デザイナー3人による運用を開始している状況を紹介
project
lessの機能が複数あることと、ファイルが長くなってきた場合の可読性を考え、ある程度の細分化させ新たな機能導入も行いやすくしている
static
  |-less/
  |    `-project.less
  |      |-_variable.less
  |      |-_mixin.less
  |      |-_layout.less
  |      |-_common.less
  |      |-_core.less
  |      |-_theme.less
  |      |-_permalink.less (page)
  |      `-_guest.less (page)
  |-css/
  |   `-project.css
  • service-name.less
    • 親のLess。"_"付のLessファイルを@importさせて結果的にはalbum.cssという1つのCSSファイルに結合してコンパイルしています。その為、コンパイルするのはこのファイル1つ
  • _variable.less
    • 変数定義用。現状は基本カラーと、背景に使う画像のpathの管理をしています
  • _mixin.less
    • mixin用です。ベンダープレフィックスが必要なもの、clearfixなど基本的なものやボタンパーツなど。基本的なものについては全社共通で使えそうなパーツが多い
  • _layout.less
    • 大まかな骨組みの部分だけこっちで定義させてます。サイドバーの幅を変えたりレイアウト調整する場合、楽になります
  • _common.less
    • bodyやanchorなど基本的な指定やResetになります
  • _core.less
    • 一番いじってるLess。ここから他のLessファイルに分散できるものを吟味している状況で現在はtemp的な役割
  • _theme.less
    • テーマが絡むサービスな為、_coreに書かれた内容を打ち消す為に用いています
  • _permalink.less, _guest.less
    • ページ単位で比較的大きく独自のスタイルの定義が入る場合はページ毎にLessを作ってみています
one
static
  |-less/
  |    `-portal-one-top.less
  |       `-one.less
  |         |-_variable.less
  |         |-_mixin.less
  |         |-_common.less
  |         `-_display_none.less
  |-css/
  |   |-portal-one-top.css → ポータルトップに利用
  |   `-one.css → one全体に利用
Less導入前は以下のようなhtmlに併記する書き方をしていたが、Lessによるimportが吸収可能な為、portal-top-one.cssのみを出力することも可能になった
<link type="text/css" rel="stylesheet" href="/css/one.css">
<link type="text/css" rel="stylesheet" href="/css/portal-top-one.css">
複数サービス運用してみて感じたのは_mixinは似たファイルになる部分も大きいので、共通化やsnippetのシェアを念頭に入れる必要あり。

導入ライブデモ

ちょっといじってみます

厄介な点・注意点

  • Compilerを毎回立ち上げる必要がある
    • 慣れてくると意外に思う事もあるかもしれない
  • Compilerによって構文エラーを感知できない時がある
    • WinLessで何度か体験ずみ。エラーでcompileされてないけどsuccessになる
  • lessのcommit忘れに注意
  • firebugなどから該当するlessの箇所を探すのが少し面倒
    • CSSのパスが一致しないので検索できない

現状での運用ルール案

以上の内容を踏まえ運用ルールを提案します
  • 導入は必須ではないが、アクティブなサービスは順次移行推奨
    • プロジェクトによってless,css両方書く事を避けたい
  • 導入する場合はLessを使いましょう
  • ファイルはできる限りわかりやすく分割しましょう
  • 各プロジェクトのLessの具体的な運用方法はまずはお任せ。みんなでノウハウの蓄積を。
    • 命名規則。templates同様importファイルは「_」をつけるなどして視覚的にわかりやすく
  • Compilerは指定した物を利用する
    • less.app, Winless
推奨
  • Compileする際にはなるべく1つのCSSにしましょう
    • なにでどうimportされるかわからなくなる。mixinなど読み込まれているかわからなくなる
    • ※IEの場合css selecter 「4,096」の制限に注意

将来的な展望

ライブラリの導入
まずは自社のノウハウを貯める段階だと思いますが現状の候補として
Preboot.less
Less Elements
Twitter Bootstrap

Hatena.lessの導入案

はてな全体で使われる標準的lessファイルの導入によりサービス全体の統一感やサービス側での負担を軽減させる目的を果たすと考える。現在定めているガイドラインをソースコードに落とし込んでシェアさせる事でルールの運用がより強力になる
Hatena
  `-Hatena.less ------------------------Hatena-Project1/
       |-_Hatena_variables.less ---|  |     `-project.less
       |-_Hatena_mixin.less     ---|  |        |-_variable.less
       |-_Hatena_layout.less    ---|  |        |-_mixin.less
       `-_library.less(外部?)---|  |        `-_core.less
                                      |     
                                      |-Hatena-Project2/
                                      |     `-project.less
                                      |        |-_variable.less
                                      |        |-_mixin.less
                                      |        |-_layout.less
                                      |        `-_core.less
                                      |
                                      |-Hatena-Project3/
                                            `-project.less
                                               |-_variable.less
                                               |-_mixin.less
                                               |-_common.less
                                               `-_core.less

今後の運用について

  • チーム間(デザイナー、エンジニア、ディレクター)での使用感をシェア
デザイン会
  • 運用状況、TIPSのシェア
  • Lessを導入した事が本当に正しかったのかの仮説の検証
  • mixin snippetをシェアしつつ、library、Hatena.lessの必要性を検討