😸
いい感じのmixin作りたいけどすごい冗長的になったのでもっとカッコいいのを書き方を考え中
基本的なspacingはmarginのbottomとrightで管理したいので下記のようなmixinを作りました。
marginのbottomとrightだけ許容する@mixinを作成
$margins: (
small: 8px,
medium: 12px,
large: 50px,
);
@mixin margin($size: medium, $property: bottom) {
margin-#{$property}: map-get($margins, $size);
}
.section {
@include margin(large, bottom);
@include margin(small, right);
}
// コンパイル後
.section {
margin-bottom: 50px;
margin-right: 8px;
}
@mixinの仕様
@mixin margin($size: medium, $property: bottom)
$size
と$property
にはデフォルトの値を設定しておきます。
Interpolation(インターポレーション)で文字列として扱う
:::note info
Interpolation(インターポレーション)#{$property}
利用することで動的にプロパティを操作できるようにします。
$property = bottom;
コンパイル前:margin-#{$property}
コンパイル後:margin-bottom
:::
@errorで指定以外を弾く設定を追加
追加でmargin-bottom
とmargin-right
以外は許容したくないので、
@errorを追加してbottomとright以外を第二引数に入れるとエラーを出すようにする。
これでおかしな使われ方はできない。
@mixin margin($sizes: (), $property) {
@if $property {
}
@else {
}
@if ($property != bottom and $property != right) {
@error "$propertyはbottomかrightのみ";
}
@if (length($sizes) == 1) {
margin-bottom: marginSize($sizes);
} @else {
@for $i from 1 through 4 {
$property: join($property, $sizes);
}
@debug $sizes;
//margin: marginSize(nth($sizes, 1)) marginSize(nth($sizes, 2));
}
}
条件分の書き方は注意
:::note warn
条件式で&&
や||
は使えないので、and
やor
を利用する
:::
作った@mixinの課題
いい感じにできたと思いきやこれだと問題が発生します。
コンテンツ間のspacingは@include margin($size, $property);
記述できる。
ただ、margin: 0 auto;
やmargin: 10px 8px 12px
とか指定したいてなったら記述バラバラでそのうちカオスになるのではないか?
具体例
.section {
@include margin(large, bottom);
@include margin(small, right);
}
.section2 {
margin: 0 auto;
}
.section3 {
margin: 10px 8px 12px;
}
@mixinが対応できていない範囲は、これまで通り書かないといけません。
同じmarginを指定するのに違う書き方が存在すると後に混乱を招くかもしれない…。
意図的なのか偶発的なのかは判断できないかもしれない…
@mixinを汎用的に拡張を試みてみる
@mixinを拡張することにしたがめっちゃ冗長的に…
@mixin margin($sizes: (), $property: bottom) {
@if ($property != bottom and $property != right) {
@error "$propertyはbottomかrightのみ";
}
margin-#{$property}: map-get($margins, $size);
}
第一引数を配列にする。
$property
のデフォルト値をセットしている場合は諸々の判定に第一引数を使います。
@mixin margin($sizes: (), $property: bottom) {
@if (length($sizes) == 1) {
margin-#{$property}: map-get($margins, $sizes);
}
@else if (length($sizes) == 2) {
margin: marginSize(nth($sizes, 1)) marginSize(nth($sizes, 2));
}
@else if (length($sizes) == 3) {
margin: marginSize(nth($sizes, 1)) marginSize(nth($sizes, 2) marginSize(nth($sizes, 3));
}
@else if (length($sizes) == 4) {
margin: marginSize(nth($sizes, 1)) marginSize(nth($sizes, 2) marginSize(nth($sizes, 3) marginSize(nth($sizes, 4));
}
}
nth()を使って配列から取り出す
:::note info
リストの指定した位置の要素を取得する nth(list, $n)
:::
もっといい書き方があるだと思ってますが…
いい記述方法を考えついたら更新します。
Discussion