最近はCSSのフレームワークを利用する機会が増えましたが、フレームワークだと基本的にカラム間のmarginが固定されているので、ブロックまたはブレイクポイントによってmarginの値を変えたい時に不便に感じることがあります。
例えば、Bootstrapだと$grid-gutter-width
で設定した値が固定のmarginになります。
$grid-gutter-width: 30px !default;
Bootstrap例
デザインによってはブロックごとにカラム間の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 -->
コード
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
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
にスタイルを追加
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になります。
使用例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まで設定できるのは他のフレームワークではあまり無いように感じたので、結構便利に使っています。
参考になりましたら幸いです。