JSフレームワークでCSSがいくぶん楽になるかもしれない

まえがき

※これはJSフレームワークを使いたいがための社内の説得材料として書いています。あと自分用のメモです。

ここから本題

CSS辛く無いですか?

CSS設計の辛み

  • CSSファイルをどういう単位で分割するか人によってバラバラ(ページ毎・パーツ毎・機能毎・CSSのプロパティの種類毎)。
  • 意図しないスタイルが被ってしまう。
  • 命名規則でイライラ
  • BEM等のルールを作ったところで、所詮は紳士協定なので「全員」がルールが守られなければ意味なし
  • 巨大なCSSファイルを同時に更新してコンフリクトしてギャーってなる
  • 競合が怖くて、使い回しができない。

JSフレームワークを使うと幾分楽にできそうなので、Vueを使ってみる

今回は僕自身が慣れている、JSフレームワークのVueを使ってWebComponents風に実装して、 CSSを少しだけ楽にしてくれるサンプルを掲載してみる。

Vueの中では単にコンポーネントと記載されているので、以降はココでもそのように記載する。 HTML+CSSやWordPressの経験者はコンポーネントをテンプレートとして読み替えればわかりやすいと思う。

VueでWebComponent風に書いてみたサンプル

面倒なので、コンポーネントの実装を中心にだけ記載しておく。

app.vue
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<style lang="stylus">
font-stack = Helvetica, sans-serif
primary-color = #999
body
  font 100% font-stack
  color primary-color
</style>

<template lang="jade">
div
  h1 
  comp-a
  comp-b
</template>

<script>
import compA from './components/a.vue'
import compB from './components/b.vue'

export default {
  data () {
    return {
      msg: 'Hello from Babel!'
    }
  },
  components: {
    'comp-a': compA,
    'comp-b': compB
  }
}
</script>
components/a.vue
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<style scoped>
:scope {
  border: 1px solid #00f;
}
.red {
  color: #f00;
}
</style>

<template>
  <div>
    <h2 class="red"></h2>
  </div>
</template>

<script>
export default {
  data () {
    return {
      msg: 'Hello from Component A!'
    }
  }
}
</script>
components/b.vue
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<style scoped>
:scope {
  border: 1px solid #f00;
}
h2 {
  color: #393;
}

.red {
  color: #0F0;
}
</style>

<template>
  <div>
    <h2 class="red">Hello from Component B!</h2>
  </div>
</template>

画面

vue-sample

ざっくり解説

  • vueファイルにHTML,CSS,JSをべったり書いていく。(気持ち悪いですか?)
  • HTMLはtempalateタグの中に書く
  • HTMLを細かくパーツ毎にテンプレート化して、テンプレートファイルに直接CSSを実装していく
  • styleタグにscopedプロパティを付与すると、別のコンポーネントで同じ名前のクラスに対して被らない。
  • つまり、ComponentA.vueの.redとComponentB.vueの.redは別物としてブラウザは認識する。

いいところ

  • HTML+CSS+JSの使いまわしがとても簡単
  • HTML+CSS+JSが全部集約されているので、見通しがいい
  • コンポーネントにCSSを書いていけばいいので、CSSのファイル構成を考えなくていい
  • コンポーネント間でCSS+JSがバッティングしづらい(CSSはstyleのscopedプロパティを使用した時)
  • BEMを採用してもコンポーネントの名前を基準に命名すればいいので、コンポーネントの名前が決まれば迷わない。
  • コンポーネント間でCSSを使い回ししたいときはstyleにscopedプロパティは付与しないか、親コンポーネントに対して実装する。
  • コンポーネントを使いまわすときはコンポーネントの読み込みを数行書くだけでとても楽
  • コンパイルして使用するものなので、副産物的にCSSプリプロセッサのSass,Stylus HTMLの軽量マークアップ言語のjadeを使用することが出来る。
  • コンパイル時に単数、もしくは少数の複数ファイルにいい感じに纏めてくれる。

あまり良くない部分

  • 機能は揃っているけど、コンポーネントはどう設計すればいいかというレール(規約)がないで、コンポーネントの設計を考える必要はある
  • IE8以前には未対応(ChromeやFirefoxを始めとしたモダンブラウザに対応している)
  • HTML+CSS+JSが全部まとまっているという状況は人によっては受け付けない(気持ち悪い)感じになる
  • やっぱりセクショニングは無理。(あんまりセクショニングしらんけど)
  • 工夫しないとSEOに弱い。(VueといよりはSPA全般に言えること。そもそもSEOをそこまで考慮しない、かつSPAで使用していく場合はそこまでデメリットにはならない。)
  • 「原則として」jQueryが使えない。というか使いたくない
  • あとどうしても学習コストは存在する。
  • 分割したコンポーネントのファイルにソースコードハイライト・補完が効かないので対策が必要(SublimeはあるけどCodaはしらん)

HTML+CSSを書いていく人への影響

  • どの単位でコンポーネントを分割(再利用できるように実装)していくかがより重要に
  • エンジニアとの協業がより重要に(JSのロジックが絡んでくるので、コンポーネントの分割方法に問題がある時にマズい)
  • コンポーネントの読み込み部分ははどうしてもJSを使用するので、追加したい時はエンジニアにお願いするか、自分でやるしかない。
  • 色々環境を作らないといけない。(Vagrantでサーバーを共有すれば解決可能。)
  • コンポーネントをまとめてひとつ、または複数のファイルにまとめるので、いわゆるコンパイルが必要。(自動化出来る)