flexboxとgridを併用してレイアウトを作る


はじめに

railsアプリの基本機能が実装できて
さあ、UIブラッシュアップに着手しよ!と思った時に
「レイアウトどうすればいいか分からん…」という状況になった。

webデザインに関する情報は、ネット・書籍でも豊富にあったが
それゆえに情報整理ができなくなってしまった。

ただ、最終的に私が個人的に合う
レイアウト作成法に出会えたので、まとめておく。

Flexbox or Grid?

レイアウトを構想している初期段階は
自分のアプリには、flexboxgridどちらを使うのが良いのだろう…
と考えていた。

デザインの主流は、flexboxという記事や参考動画も多かったので
基本的にはflexboxを使うべき!
gridは表示させるコンテンツ量が多くなった時に
効果的な応用技だろ!くらいに思っていた。
(楽天やAmazonなどの商品ラインナップを表示させるみたいなイメージ)

でも、整理がしやすいように両方の技術を併用するのも
個人的には有りではないかと思う。

役割の違い

情報収集していく過程で
両者にはそれぞれ役割に違いがあることが分かった。
お互いの強みを適材適所で使い分けるのが良いということらしい。

ざっくり違いを整理すると

  • flexbox : 1次元のレイアウト

   例)対象グループ内のブロック要素を
     ・縦方向に中央揃えにする
     ・横方向に対してコンテンツの間に均一に空白を空ける

  • grid : 2次元のレイアウト

   例)対象グループ内のブロック要素を
     横列の1列目150px、2列目300px、3列目150px ...
     縦列の1列目150px、2列目300px、3列目150px ... で表示させる
 
ということかなーと解釈。

考えたレイアウト

前置きを前提に、私が勝手に分かりやすい思うレイアウトは

  1. まず、大枠をGridで作る
  2. その後、各ブロック要素をFlexboxで整える

となった。

実装

まず、application.html.erbでレイアウトの基本構成を整える。
(ヘッダー、ナビゲーションバー、メイン、フッターを
renderで別ファイルを参照する構成にしている。)

app/views/layouts/application.html.erb
〜〜省略〜〜

<body>
  <header>
    <%= render 'layouts/header' %>
  </header>

  <nav>
    <%= render 'layouts/navigation' %>
  </nav>

  <main>
    <%= yield %>
  </main>

  <footer>
    <%= render 'layouts/footer' %>
  </footer>
</body>

次に、基本構成の中の_header.html.erbは

1、ロゴ
2、ログイン・ログアウト・サインインの各リンク

といった2つのブロック要素で構成しておく。

app/views/layouts/_header.html.erb

<div>
 <%= link_to image_tag('logo.png', id: 'logo', alt:"〇〇"), "サイトURL"%>
</div>


<div>
 <ul>
   <% if logged_in? %>
     <li><%= link_to "ログアウト", logout_path, method: :delete %></li>
   <% else %>
     <li><%= link_to "ログイン", login_path %></li>
     <li><%= link_to "サインイン", signup_path %></li>
   <% end %>
 </ul>
</div>

最後に、custom.scssでデザインを整える。

まず、Gridでアウトラインを構成する。

1、display: grid;を宣言して
  grid-template:で縦と横の幅を決定して
  視覚的にアウトラインを構成する。

2、grid-area: ブロック要素;で
  application.html.erbで構成したレイアウト(header、main、nav、footer)に
  grid表内で命名した名前と紐付ける。

続いて、Flexboxでヘッダー内の
ブロック要素の並び方を変更する。

デフォルトではブロック要素が縦並びになるが、
ロゴは左側、各リンクは右側という具合に横並びに表示されるように変更する。

display: flex;を宣言して
justify-content: space-between;で
ブロック要素の間にスペースが空くように設定する。
(※header{}内にコード記載)

app/assets/stylesheets/custom.scss

body{
 display: grid;
 grid-template:
  "..... ...... ...... ...... ...... ...... .....  " auto
  "header header header header header header header" 150px
  "..... ...... ...... ...... ...... ...... .....  " 10px
  "..... navbar ...... main   main   main   .....  " 200px
  "..... ...... ...... main   main   main   .....  " 10px
  "..... footer ...... main   main   main   .....  " 150px
  "..... ...... ...... main   main   main   .....  " 1fr
  "..... ...... ...... ...... ...... ...... .....  " auto
   /10px  200px  10px   1fr    10px   200px  auto;

 header{
  grid-area: header;
  display: flex;
  justify-content: space-between;
 }

 main{
  grid-area: main;
 }

 nav{
  grid-area: navbar;
 }

 footer{
  grid-area: footer;
 }
}

完成イメージ

ざっくりは下記のような感じになるはず。

この図でいうレイアウト自体はGridで
各ブロック要素(ヘッダー等)はFlexboxで
構成するのが個人的に配置しやすかったということ。

終わりに

初学者のため、現状の気づきでまとめている。

今のところ

また、flexboxに関する参考記事が多い理由は

1、flexboxだけでもレイアウト構成が可能なため
  ・方向性を変更(縦→横並び)
  ・余白を入れる(要素に均一にスペースを空ける)
  ・要素を折り返しさせる
を全体のレイアウトに適用させる方法

2、gridがflexboxより新しい技術なため

だと思っている。

途中でもっと良い書き方に気づけば、情報を更新する。

最後までお読みいただき、ありがとうございました!