12
15

More than 5 years have passed since last update.

[Sass(SCSS)]レスポンシブ対応。カラム数とカラム間marginを自由に設定するMixin

Last updated at Posted at 2015-11-28

最近はCSSのフレームワークを利用する機会が増えましたが、フレームワークだと基本的にカラム間のmarginが固定されているので、ブロックまたはブレイクポイントによってmarginの値を変えたい時に不便に感じることがあります。
例えば、Bootstrapだと$grid-gutter-width で設定した値が固定のmarginになります。

_variables.scss
$grid-gutter-width: 30px !default;

Bootstrap例

bootstrap.png

デザインによってはブロックごとにカラム間のmarginが違ったり、PCとスマートフォンでmarginを変えたかったり、フレームワークだと対応しきれないことが多いです。

そのためオリジナルのcssでブロック毎にスタイルを設定しなければならないのですが、都度カラム数に応じてwidthやmarginを書いていくのは面倒なので、mixinにまとめて記述量を減らそうと思います。

実現したいこと

  • カラム数とカラム間marginを指定するcssを簡単に書きたい。
  • 包括要素(.container)の左右端に子要素(.item)をピッタリ合わせる。
  • 基本的にflexboxを採用するがfloatによる代替えも出来るようにしておく。

なお、基本的なHTMLの構造は以下のようになります。
親要素.containerとは別に、カラムの包括要素.rowを使用します。
比較しやすいようにBootstrapと同じclass名にしています。

<div class="container">
    <div class="row">
        <p class="item">.item</p>
        <p class="item">.item</p>
        <p class="item">.item</p>
    </div><!-- /.row -->
</div><!-- /.container -->

preview.png

コード

Sass(SCSS)

// clearfixのmixinを用意
@mixin clearfix{
    &:before,&:after { content: ""; display: table;}
    &:after {clear: both;}
    zoom: 1;
}

// こちらがカラム設定用Mixin
@mixin col(
    $column-count,
    $column-margin  : margin(),
    $selector       : '.item',
    $is-list        : false,
    $is-flex        : true
) {

    // リストに適用する場合
    @if $is-list == true {
        $selector : '> li';
    }

    // is Flex (default)
    @if $is-flex == true {
        display: flex;
        flex-wrap: wrap;
        justify-content: space-between;

        $margin-size : #{$column-margin * ($column-count - 1)};

        #{$selector} {
            width: calc((100% - #{$margin-size}) / #{$column-count});
            @content;
        }
    } // end Flex

    // not Flex
    @else {
        @include clearfix;
        margin-left : #{-$column-margin};
        $margin-size : #{$column-margin * $column-count};

        #{$selector} {
            float: left;
            margin-right: -.1px;    // 小数点以下の切り捨て・切り上げ解釈違いに対応
            margin-left:#{$column-margin};
            width: calc((100% - #{$margin-size}) / #{$column-count});
            @content;
        }
    } // end if not Flex
}

// 書き方
// @include col(カラム数,margin値,'セレクタ');

使用例1 基本の使い方

  • 包括要素:.container
  • カラム数:3
  • margin:40px
  • カラムのセレクタ:.item

3x40.png

SCSS

.container {
    margin-right: auto;
    margin-left: auto;
    width: 800px;
}

.row {
    @include col(3,40px,'.item');
}

アウトプット後のCSS

.container {
  margin-right: auto;
  margin-left: auto;
  width: 800px;
}

.row {
  display: flex;
  justify-content: space-between;
  flex-wrap: wrap;
}

.row .item {
  width: calc((100% - 80px) / 3);
}

使用例2 カラムに他のスタイルを追加する

  • カラム数:4
  • margin:15px
  • カラムのセレクタ:.item
  • .item にスタイルを追加

4x15+style.png

SCSS

.row {
    @include col(4,15px,'.item') {
        background-color: #fff;
        color: #6BC9FF;
    }
}

.item にスタイルを追加する場合は @include col(4,15px,'.item') { // ここに記入 } このようにカッコ内に書きます。

アウトプット後のCSS

.row {
  display: flex;
  justify-content: space-between;
  flex-wrap: wrap;
}

.row .item {
  width: calc((100% - 45px) / 4);

  /* 追加したスタイル */
  background-color: #fff;
  color: #6bc9ff;
}

使用例3 リストに使用する

  • カラム数:3
  • margin:40px
  • カラムのセレクタ:> li

SCSS

.row {
    @include col(3,40px,$is-list:true);
}

セレクタを指定しない代わりに $is-list:true を指定します。

アウトプット後のCSS

.row {
  display: flex;
  justify-content: space-between;
  margin-top: 0;
  margin-bottom: 0;
  flex-wrap: wrap;
}

.row > li {
  width: calc((100% - 80px) / 3);
}

使用例4 Flexboxではなくfloatで実装する

  • floatを使う
  • カラム数:3
  • margin:40px
  • カラムのセレクタ:.item

SCSS

.row {
    @include col(4,20px,'.item',$is-flex:false);
}

アウトプット後のCSS

.row {
  margin-left: -20px;
}

.row::after {
  content: '';
  display: table;
  clear: both;
}

.row .item {
  float: left;
  margin-right: -.1px;
  margin-left: 20px;
  width: calc((100% - 80px) / 4);
}

.row にマイナスマージンを入れることで.container の左右端に.item を合わせています。
なので、基本的には背景や幅を指定するclassは.container になり、.row はあくまでもレイアウト用のclassになります。

4x15float.png

使用例5 メディアクエリ内で使用

SCSS

.row {
    @media screen and (min-width: 768px) {
        @include col(3,30px,'.item');
    }
}

アウトプット後のCSS

@media screen and (min-width: 768px) {
  .row {
    display: flex;
    justify-content: space-between;
    flex-wrap: wrap;
  }

  .row .item {
    width: calc((100% - 60px) / 3);
  }
}


以上になります。

包括要素(.row)が必要にはなりますが、カラム間marginまで設定できるのは他のフレームワークではあまり無いように感じたので、結構便利に使っています。

参考になりましたら幸いです。

12
15
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
15