Fippiyのプログラム学習内容アウトプットBlog

日々の学習内容をアウトプットして振り返りを実施する。

スタイルシート、アイテムリストの全体的なサイズを設定するだけで、自動的にスタイルを適用したい

RubyRubyフレームワークであるRailsを利用して、Webページにてよくある商品一覧表示画面のような物を作成していた時の事です。

ページによって表示スタイルが全て同じであれば、一つのスタイルを作ればそれで完了なんですが、作成時にいろんなパターンに適用できる柔軟なスタイル設定をしたいと思い試行錯誤しました。

 

 

 

何がしたいか

要素を等間隔に配置

f:id:Fippiy:20190306124609p:plain

要素配置1

 

要素の数が変更になっても等間隔で配置

f:id:Fippiy:20190306124707p:plain

要素配置2

これをそれぞれ別のスタイルシートを最初はつくっていたんですが、一部の値が変化するだけなので、できればコードは一緒にしてしまいというのが今回の趣旨。

 

 

やりたいこと

値を設定すれば、あとは自動的に設定できるようにする

  1. 全体の横幅が変わっても範囲内で自動的にサイズ調整したい
  2. 横に配置する要素数を数値で指定して簡単にスタイルを適用させたい 

f:id:Fippiy:20190306123312p:plain

完成形イメージ

 

やったこと

大きさとブロック数の指定だけ決めて、後の要素は自動算出する

  1. 全体のサイズ・横に配置する要素数・要素の間隔を指定して、あとは計算によって全体の横幅に合うようにする。
  2. 「横の要素数と間隔」の変化によって全体幅を超過しないような調整をした

 

f:id:Fippiy:20190306122352p:plain

作業内容イメージ

やった内容

ここからはコードの話になります。

f:id:Fippiy:20190306130504p:plain

作成コード(一部抜粋)

mixinを利用して、表示エリアを作成

スタイル適用範囲をmixinとして作成を実施。

引数に縦横の大きさ等の必要な設定を変数として設定します。

 

全体の横幅に収まるように要素の横幅を設定する

 

要素の横幅を計算

7行目: $margin: calc(#{$interval} * (#{$block} - 1));

ここで要素の間隔の合計を計算、要素数($block)-1することで、左端にくる要素にはmargin設定しないので除外しています。 

要素1つの横幅を算出

8行目:width: calc*1 {
margin-left: $interval;
}

親要素からn番目に対して設定を追加する機能を利用して作成。

:nth-child(3n)とすると、子要素の3の倍数を指定することになります。

では、ここでは何をしているか?

$block = 要素数...たとえば3だったとすると

(3 + n - (3 -1) = 3n-2 を指定しています。

nが1だと、3(1)-2 = 1

nが2だと、3(2)-2 = 4

これで3つの要素指定時に左側にくる要素を選択出来るようにしています。

素数が変化しても常に左側の要素のみを取り出せるようになりました。

そしてここで、選択した要素にmargin-leftで間隔を設定してあげることで、全体の横幅に収めることができました。

値の設定方法にもう一工夫

が、もうちょっと記述を減らす工夫をしました。

先程の12行目の記述ですが

&:not(:nth-child(#{$block + n - ($block - 1)})) {
margin-left: $interval;
}

 not()という記述があります。

()内を否定する記述になっています。

つまり、対象の要素に該当しない場合にmargin-leftを指定することになっています。

簡単に言うと左端"ではない"場合を指定して、その場合のみmargin-leftで間隔を指定しています。

 

全ての要素にmarginを指定して、左端の要素のみを指定しない書き方をはじめはしていました。

しかし、デフォルトではmargin設定がない状態で、全部にmargin指定をして、そこから一部の設定を解除するといった面倒なことをしていることに気がつきました。

 

であれば、最初からmargin-leftを設定する物のみ指定をすればいいという結論になりました。

先程の計算結果をもう一度考えてみると、n=1の時は1,n=2の時は4がはいります。

1,4の時はnotになるので対象のスタイルが適用されない、つまりmargin-leftがあたらない設定としました。

 

後は作成したmixinを適用したい場所にincludeで適用してあげて、引数で設定したい要素全体の大きさや要素数を指定することで柔軟に対応できるようになりました。

 

github.com


 

*1:#{$width} - #{$margin}) / #{$block});

先程の$marginを利用して全体の横幅から間隔に仕様するサイズを引き算。これで実質の横のサイズが決定します。そこから要素数で割り算することによってひとつの箱のサイズを決定することにしました。これで要素数が変化しても対応できます。

要素の位置によってmargin-leftの値を入れるか入れないかを決定する

12行目から:

&:not(:nth-child(#{$block + n - ($block - 1)}