CSS Grid Layout の auto-fit を @mixin で実現

CSS Grid Layout の auto-fit を @mixin で実現


CSS Grid Layout の auto-fit を擬似的に IE11 で実現させる」の続きです。

IE11 では対応していいない Grid Layout の auto-fit を擬似的に対応させます。擬似的というのは、auto-fit を使えばメディアクエリを使う必要がないのですが、IE11 で同様のことを実現しようとしますと、どうしてもメディアクエリを使わざるを得ないということになります。


実現したいことの整理

まず、やりたいことを整理しますと、grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)) 、つまり、同サイズのブロックを最小サイズ 300pxで、ウィンドウサイズが変わっても、常に親ブロックの横幅いっぱいに並べたいということです。それを IE11 で実現します。

で、前回記事でわかったことは、IE11 では、

  • 親要素に -ms-grid-rows-ms-grid-columns で2次元グリッドトラックを構築
  • 各子要素に -ms-grid-row-ms-grid-column を指定し、どのグリッドトラックに表示するかを指定

する必要があるということです。


前回記事にも書きましたように、autoprefixer を使って、なおかつ grid-gap を有効にするためには、grid-template-areas ですべてのグリッドトラックにネーミングする必要があります。そのための sass のコードも書いてみたのですが、ふと、そんなことなら、IE11 対応のコードを直に書き出せば同じではないかと気づき、@mixin を使うことを思いつきました。


@mixin を使う

で、その @mixin のコードがこちらです。


@mixin iegridhack ($element, $child, $column, $gapr:false, $gapc:false) {
    $temp: "";
    @for $i from 1 through ceil($child / $column) {
        $temp: $temp + auto + " ";
        @if $gapr != false and $i < ceil($child / $column) {
            $temp: $temp + $gapr + " ";
        }
    }
    -ms-grid-rows: #{$temp};

    $temp: "";
    @for $i from 1 through $column {
        $temp: $temp + 1fr + " ";
        @if $gapc != false and $i < $column {
            $temp: $temp + $gapc + " ";
        }
    }
    -ms-grid-columns: #{$temp};

    @content;

    $r: 1;
    $c: 1;
    @for $i from 1 through $child {
        #{$element}:nth-child(#{$i}) {
            -ms-grid-row: $r;
            -ms-grid-column: $c;
            @if ($i % $column == 0) {
                $r: $r + 1;
                @if $gapr != false { $r: $r + 1; }
            }
            @if $gapc != false {
                $c: $c + 1;
                @if ($i % $column == 0) { $c: 0; }
                $c: $c + 1;
            }
        }
    }
}

汎用性はありません。grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)) を実現させるだけです。引数は、

  • $element: 子要素のセレクタ
  • $child: 子要素の数
  • $column: 列数
  • $gapr:false 行間
  • $gapc:false 列間

です。


呼び出しは、

.archive-entries {
    display: grid;
    @include iegridhack('.archive-entry', 12, 2, 10px, 10px) {
        grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
        grid-gap: 10px;
    }
}

こんなふうにします。コンパイルされる css は、

.archive-entries {
    display: -ms-grid;
    display: grid;
    -ms-grid-rows: auto 10px auto 10px auto 10px auto 10px auto 10px auto ;
    -ms-grid-columns: 1fr 10px 1fr ;
    grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
    grid-gap: 10px;
}
.archive-entries .archive-entry:nth-child(1) {
    -ms-grid-row: 1;
    -ms-grid-column: 1;
 }
.archive-entries .archive-entry:nth-child(2) {
    -ms-grid-row: 1;
    -ms-grid-column: 3;
}
.archive-entries .archive-entry:nth-child(3) {
    -ms-grid-row: 3;
    -ms-grid-column: 1;
}
.archive-entries .archive-entry:nth-child(4) {
    -ms-grid-row: 3;
    -ms-grid-column: 3;
}

(略)

.archive-entries .archive-entry:nth-child(12) {
    -ms-grid-row: 11;
    -ms-grid-column: 3;
}

となり、


f:id:ausnichts:20181129170444j:plain

こうなります。


メディアクエリを使って、

@media (min-width: 768px) {
    .page-index.page-archive {
        .archive-entries {
            display: grid;
            @include iegridhack('.archive-entry', 12, 2, 10px, 10px) {
                grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
                grid-gap: 10px;
            }
        }
    }
}

とくくれば、上の画像のように 768px以上で2列となり、


さらに、

@media (min-width: 1037px) {
    .page-index.page-archive {
        .archive-entries {
            @include iegridhack('.archive-entry', 12, 3, 10px, 10px);
        }
    }
}

と追加すれば、1037px以上で3列になります。この 1037px は公開しています「はてなブログ グリッドレイアウト開発環境」で、grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)) を指定した場合に、3列に変わるウィンドウ幅を計算した値です。


f:id:ausnichts:20181129170500j:plain

こうなります。

何だか無駄なことをやっているのではないないかという迷いはありますが、Grid layout でテーマを作るベースは出来ました。