INODEVLOG

WEBアプリ開発・事業開発・ビジネスモデル・読書の情報などをお届けしています。

Railsで不定数要素をBootstrapレスポンシブ対応する方法

今日はRailsエンジニアのデザイン向けTipsをお届けまします。どうも、井上です。

先日友人がTwitterBootstrapの仕様で「要素の数はわからないけれど、1行に3つずつ順番に表示したい」というときに表現方法に困っていました。

確かに行毎にrowクラスを指定したdivタグで囲むという表現など、若干ややこしいかと思います。

ただ、これはひとつだけ新しいメソッドを知っておけば簡単に出来るので、今回はその小技をご紹介します。

f:id:inodev:20170111002253p:plain

前提:Bootstrapでレスポンシブにするには?

  • rowクラスを指定したdivで1行分を囲む
  • col-sm-12などカラムが各デバイスで合計12になるようにする

という条件がありました。

仮に合計4つの表示したい要素があって、1行に3つまで要素を置きたい場合は、

<div class="row">
  <div class="col-sm-4">
    要素1
  </div>
  <div class="col-sm-4">
    要素2
  </div>
  <div class="col-sm-4">
    要素3
  </div>
</div>
<div class="row">
  <div class="col-sm-4">
    要素4
  </div>
</div>

という風に書くかと思います。

これでPCから見たときには↓みたいに並び、

■ ■ ■  
■

スマホから見たときには↓みたいに並ぶわけですね。

■  
■  
■  
■

これが3個とか4個とか5個とか、WEBアプリで配置する要素の数が動的に変わっても堪えられる書き方を紹介したいと思います。

不特定要素をRailsでレスポンシブデザイン対応させる

UsersController#indexがデフォルトのままallメソッドを使っていたとして、

app/controllers/users_controller.rb

class UsersController < ApplicationController
  def index
    @users = User.all
  end

  # ...
end

対応するViewは次のように書くと3つずつ綺麗にrowで行を区切って配置出来ます。

app/views/users/index.html.erb

<% if @users.present? %>
  <% @users.each_slice(3) do |users| %>   <!-- # ①  -->
    <div class="row">                     <!-- # ②  -->
      <% users.reverse_each do |user| %>
        <div class="col-sm-4.text-center">
          <%= user.email %> 
        </div>
      <% end %>
    </div>
  <% end %>
<% end %>

個人的にBootstrap使う時にERBをそのまま使うとすごく気分が悪くなるのでSLIMの内容も載せておきます。

app/views/users/index.html.slim

- if @users.present?
  - @users.each_slice(3) do |users|   # ①
    .row -                            # ②
      - users.reverse_each do |user|
        .col-sm-4.text-center
          = user.email 

解説(each_sliceメソッド)

通常のeachメソッドはイテレータ*1を順次処理出来ますが、each_sliceは指定した数の要素を一度に処理できるというものです。

ここでは1行に3つの要素を並べたいので、①でブロックに3つ要素を投げ込んでいます。

①で要素の数が1つ以上残っていたら②でrowクラスを指定したdivタグで1行分の囲いを作っています。

あとは取り出した3つ以下の要素で、各カラムを指定して配置すればOKです!

これで行毎にrowクラスのdivタグで区切られて最後は1〜3つの要素で終わる綺麗なHTMLになります。

もし不特定多数の要素を並べるときには、each_sliceのメソッドを思い出してみて下さいね。

*1:配列やハッシュみたいに順々に処理出来るようにつくられているもの