SEVENSPIRALS

The Semantic Grid System

プログラミング

Bootstrapは私のようなセンスいまいちな開発者でも簡単に見栄えの良いサイトが作れる素晴らしいフレームワークなんですが1点だけ気になって夜も眠れないところがあります。(昨夜は熟睡でした)

気になるところって?

気になるところというのは段組を表現するためのGridシステムで、例えばBootstrapで左右に分割したレイアウトにしようと思ったら、

<div class="container">
  <div class="row">
    <div id="navigation" class="span6">
      ~ナビゲーション~
    </div>
    <div id="content" class="span6">
      ~コンテンツ~
    </div>
  </div>
</div>

のようにします。

class属性に.rowとか.span*とか付けてGrid構造を記述していますが、これではHTML内にGridのレイアウトが記述されているため、レイアウトを変えようと思ったらHTMLを変更しないといけません。

また、特に.rowは純粋にGridの行を記述するためのものなので出来れば書きたくありません。

ただ、これはCSSを直接使った場合であってGitHubリポジトリから取得すればlessファイルが同梱されています。

この中に記述されたMixinを使えば任意のCSSセレクタを使ってGridレイアウトを定義できます。

@import "bootstrap/variables";
@import "bootstrap/mixins";

.side {
  .makeColumn(6);
}
.main {
  .makeColumn(6);
}

こんな感じで記述したlessファイルをlesscコマンドでコンパイルすると.side.mainを指定した要素が.span6を指定したのと同じになります。

で、このスタイルを使用するように書き換えたHTMLは以下のように、

<div class="container">
  <div class="row">
    <div id="navigation" class="side">
      ~ナビゲーション~
    </div>
    <div id="content" class="main">
      ~コンテンツ~
    </div>
  </div>
</div>

.span6という決め打ちがなくなったので例えば.sideの幅を減らして.mainを広く取りたいとなったときにスタイルシートを変更するだけで対応できるようになります。

.container.rowについても.container-fixed();.makeRow();というMixinが定義されているので置き換える事が可能ですが、今回の例では特に例を思いつかなかったのでそのままです。

.rowの存在が何となく気に入らない(おい)以外は固定幅ならこれで問題無く使えるんですがResponsiveな場合や、複雑なレイアウトだと計算が面倒なので.row-fluidを使いたいんですが何故か上手くいかずに挫折。

Responsiveな場合はメディアクエリの内容にに応じて@gridColumnWidth@gridGutterWidthの値を定義してやればいけそうなんですがfluidだけはどうもこれらを%指定にするだけでは駄目らしく上手く動いてくれません。(やり方知ってるよという方是非教えて下さい。)

ここから本題

で、これを解決するために何か無いかと探していたら今回のタイトルのThe Semantic Grid System(以下長いのでURLからsemantic.gs)が見つかったので使ってみました。

これは何かというと、先ほど出てきた.makeRow();.makeColumn();のようなGridレイアウトのためのMixin定義で、less, scss, stylの3形式で提供されています。

提供されるMixinは、それぞれ.makeRow();makeColumn();に対応する.row();.column();、offsetのための.push();.pull();です。

.containerに相当する物はないので自分で定義する必要がありますが、初期設定では(固定幅なら)Bootstrapの.containerがそのまま使えます。

これを使って先ほどのHTMLとスタイルシートを書き換えてみます。

まずlessファイルから、

@import "grid"

.side {
  .column(6);
}
.main {
  .column(6);
}

あんまり変わりませんね。次はHTML、

<div class="container">
  <div id="navigation" class="side">
    ~ナビゲーション~
  </div>
  <div id="content" class="main">
    ~コンテンツ~
  </div>
</div>

.rowが消せました、やったね。サイトのサンプルにあるように複雑なレイアウトだと.row();を使う必要がありますが、簡単なレイアウトなら無くても動作します。

また、デフォルトでは固定幅ですが、@total-width100%を指定するとfluid layoutとして動作します。

先ほどのようにBootstrapの.containerを使う場合、Responsive だと、コンテナの幅がウィンドウ(画面)のサイズによって変わるので、fluid layoutにして追従するようにした方が何かと楽です。

注意点としては、BootstrapではSmartphone向けの表示になると全ての.span*の幅が100%になりますが、semantic.gsではそういう指定は特に入っていないので必要なら自分で指定します。

最初、Bootstrapと競合しないか不安だったんですがある程度考慮して作られているらしく、特に問題無く動いています。

というわけで、.containerこそ残っていますが、それ以外はほぼ満足のいく結果になったのでこれからは安眠できそうです。(繰り返しますが昨夜は熟睡でした)