Bootstrapで、xsのカラム数をファブレットとスマートフォンで分ける方法

More than 1 year has passed since last update.

困ったこと

Bootstrap3のグリッドシステムでは、col-xs-6のように、クラス名に特殊な接頭辞と数字を組み合わせて、レスポンシブなレイアウトを簡単に構築することができます。

しかし、768px以下の場合のxsサイズのレイアウトを実際に見てみると、

  • 400pxくらいのスマートフォンで見た場合
  • 700pxくらいのファブレット(あるいはそれくらいの幅のブラウザ)で見た場合

ひとつのレイアウトで表現しようとすると違和感があることがあります。

例えば、400pxの場合、以下の表示とします。

350px.PNG

これを680pxくらいに広げるとこうなりました。

680px_before.PNG

画像の右側が空いていて、無駄な感じがします。

しかし、

<div class="col-xs-6">
      <img class="img-responsive" src="/image/dummy.jpg"> 
</div>

のように、グリッドシステムでcol-xs-6を指定しているので、画像の右側に要素を配置することが出来ません。

xsの下に、xxsみたいなサイズ指定が出来れば……

これで解決してみた

Bootstrapを拡張してcol-xxs-3みたいなxsの下のサイズを定義できれば楽だと考えたので、以下のようなJavaScriptを書いてみました。

簡単に説明すると、スマートフォンとファブレットサイズでグリッドサイズを分けたいクラスに、custom-col-xsを定義し、そのタグにデータ属性data-xsdata-xxsを定義します。

画面のロード時やウィンドウ幅変更時に、データ属性の値を読み取ってcustom-col-xsのクラス属性をcol-xsのクラスに動的に書き換えます。

/**
 * bootstrap-expand.js
 * HTMLでのロード順は、
 * jQuery -> 本ファイル -> bootstrapにすること
 */
$(function(){

    $(window).on('load resize', function(){
        applyCustomColXs();
    });

    function applyCustomColXs() {
        var THRESHOLD = 420;
        if ($(window).width() > THRESHOLD) {
            applyPhablet();
        } else {
            applySmartphone();
        }
    }

    // ファブレット用表示に切り替える
    function applyPhablet() {
        $(".custom-col-xs").each(function(){
            // data-xs属性の値を使って、新しくcol-xs-* クラス属性を追加する
            updateColXsClass($(this), $(this).attr('data-xs'));
        });
    }

    // スマートフォンサイズ用の表示に切り替える
    function applySmartphone() {
        $(".custom-col-xs").each(function(){
            // data-xxs属性の値を使って、新しくcol-xs-* クラス属性を追加する
            updateColXsClass($(this), $(this).attr('data-xxs'));
        });
    }

    function updateColXsClass($elem, val) {
        var cls = $elem.attr("class");
        var class_arr = cls.split(" ");
        // 一旦、col-xs-* のクラス属性を削除する
        $elem.removeClass (function (index, css) {
            return (css.match (/(^|\s)col-xs-\S+/g) || []).join(' ');
        });
        $elem.addClass('col-xs-' +  val);
    }

});

先のHTMLはこうなります。

<!-- ファブレットサイズでは3カラム、スマートフォンサイズでは6カラム使用することを意味する -->
<div class="custom-col-xs" data-xs="3" data-xxs="6">
      <img class="img-responsive" src="/image/dummy.jpg"> 
</div>

こうすることで、680pxでの表示が、

680px_after.PNG

いい感じになりました。

デザイナがいない現場ということもあり、正攻法で無い気がしますが、他によい方法などあれば知りたいです。