🥨

投稿一覧画面でタブ表示 (CSSで設定)

2023/04/26に公開2

投稿一覧表示画面でタブ表示を実装します。
このように表示されます。

タブに表示されている文字「ドッグラン」〜「他」はカテゴリー名です。
カテゴリーは、(管理者により)あらかじめ用意されているものから投稿時に選択します。
この一覧画面では、カテゴリー別に自動で振り分けられています。

それでは記述方法を見ていきましょう。


記述するファイル

posts_controller.rb
posts/index.html
posts/_index.html
posts/_map_index.html
app/javascript/packs/application.css

コードは以下のように書きました。

posts/index.html.erb
posts/index.html.erb
<!--tab表示-->
<div class="wrapper">
  <ul class="tab-menu">
    <li class="<%= 'active' unless @category %>"><%= link_to '全て', posts_path %></li>
    <!--タブに表示されたカテゴリー名に紐づく投稿を一覧表示-->
    <% @categories.each do |category| %>
      <li class="<%= 'active' if category == @category %>"><%= link_to category.name, posts_path(category: category.name) %></li>
    <% end %>
  </ul>

  <div class="tab-contents">
    <div class="tab-area is-active">
      <div class="row">
      <!--一覧-->
        <div class="col-md-8">
          <%= render 'index', posts: @posts %>
          <div class="row justify-content-center my-2">
            <%= paginate @posts %>
          </div>
        </div>

        <div class="col-md-4">
          <%= render 'map_index', posts: @posts %>
        </div>
      </div>
      <!--Top-pageリンク-->
      <p id="page-top"><a href="#">Page Top</a></p>
    </div>
  </div>
</div>

タブ表示のタブ部分を作成するコードを確認します。

<ul> <li>リスト名</li> <ul> でリストを作成
② リスト(タブ)はCSSで横並びにする
③ カテゴリー名を取得してリスト名(タブ名)として表示する
④ タブを選択するとカテゴリーに紐づく投稿一覧を表示する

リスト名 = タブに表示される名称 = カテゴリー名 です。

<ul class="tab-menu">
  <li class="<%= 'active' unless @category %>"><%= link_to '全て', posts_path %></li>
  <% @categories.each do |category| %>
    <li class="<%= 'active' if category == @category %>"><%= link_to category.name, posts_path(category: category.name) %></li>
  <% end %>
</ul>

ここに、<li class="<%= 'active' ... %>"></li> というコードが2つあります。
これはif文の条件次第で'active'クラスが付くということです。
(if文の結果がfalseであれば、'active'クラスは付かない)

1つ目
<li class="<%= 'active' unless @category %>"><%= link_to '全て', posts_path %></li>

  • 全てタブに関するコードです。
    @category はコントローラで定義されています。
posts_controller.rb
def index
  @categories = Category.all
  # タブ表示(カテゴリー別or全件)
  if params[:category]
    @category = Category.find_by(name: params[:category])
    @posts = @category.posts
  else
    @posts = Post.all
  end
end

カテゴリータブを選択している場合、
そのカテゴリー名をもとにデータベースからcategoriesテーブルのレコードを取得し、@categoryに代入します。
レコードを取得できない場合(存在しない場合)はnilが代入されます。取得できない場合とは、'全て'タブを選択している時です。

つまりこの場合、@category = nil → 全て の場合に 'active' クラスが付きます。

<%= link_to '全て', posts_path %>
これはposts_path(投稿一覧)へのリンクで、タブには ’全て’ と表示されます。
’全て’ というタブが選択されているとき、投稿一覧(全件)が表示されます。

2つ目
<li class="<%= 'active' if category == @category %>"><%= link_to category.name, posts_path(category: category.name) %></li>

  • カテゴリー名タブに関する記述です。
    コントローラに定義しているように、@categoriesからeach文でデータベースよりカテゴリーのデータを一つ一つ取得しタブに表示します。

if category == @category ですが、選択されているカテゴリーのデータが取得できた場合(nilでない場合)に 'active' クラスが付きます。

<%= link_to category.name, posts_path(category: category.name) %>
同じくposts_path(投稿一覧)へのリンクですが、そのカテゴリーに紐づく投稿のみ表示されます。
タブには 'カテゴリー名' が表示されます。

posts/_index.html.erb
posts/_index.html.erb
<div class="row">
  <% posts.each do |post| %>
  <div class="card-deck ml-1 my-2">
    <div class="card border-secondary bg-light" style="width: 10rem">
      <div class="card-img-top">
        <%= image_tag post.get_post_image, height: '120', width: '100%' %>
      </div>
      <div class="card-body">
        <%= link_to post_path(post), class: 'link' do %>
          <h6 class="card-title border-bottom"><b><%= post.name.truncate(14) %></b></h6>
        <% end %>
        <small>
          <div class="card-text"><%= post.introduction.truncate(18) %></div>
        </small>
      </div>
      <div class="card-footer bg-light">
        <small>
          <div class="card-text">所在地: <%= post.prefecture %></div>
            <% if member_signed_in? %>
              <div class="card-btn-area card-text">
                <div class="card-btn favorite-btn_<%= post.id %>">
                  <%= render 'public/favorites/favorite_btn', post: post %>
                </div>
                <div class="card-btn interest-btn_<%= post.id %>">
                  <%= render 'public/interests/interest_btn', post: post %>
                </div>
                <div class="card-btn">
                  <i class="far fa-comment-dots"></i> <%= post.comments.count %>
                </div>
              </div>
            <% end %>
          <div class="card-text">投稿者: <%= post.member.nickname %></div>
          <div class="card-text">投稿日: <%= l post.created_at %></div>
        </small>
      </div>
    </div>
  </div>
  <% end %>
</div>

タブの下に表示される投稿一覧は、部分テンプレートにまとめています。
私はbootstrapのcardで表示していますが、ここは表示したいように変更してください。

タブ表示の設定をCSSに記述

app/javascript/packs/application.css
app/javascript/packs/application.css
.wrapper {
  width: 100%;
  margin: 0 auto;
}
.tab-menu {
  display: flex;
  margin: 0;
}
.tab-menu li {
  list-style-type: none;
  width: 25%;
}
.tab-menu li a {
  color: #2e1212;
  text-decoration: none;
  display: block;
  margin: 0 5px;
  padding: 10px 10px;
  text-align: center;
  background: #f9f9f9;
}
.tab-menu li a:hover {
  font-weight: bolder;
}
.tab-menu li.active a {
  background: #F9F5EB;
  color: #2e1212;
}
.tab-contents {
  display: flex;
  justify-content: center;
}
.tab-area {
  display: none;/*はじめは非表示*/
  opacity: 0;/*透過0*/
  background: #F9F5EB;
  padding: 50px 20px;
  width: 100%;
}
.tab-area.is-active {
  display: block;/*選択されたら表示*/
  animation-name: displayAnime;/*ふわっと表示させるためのアニメーション*/
  animation-duration: 2s;
  animation-fill-mode: forwards;
}
@keyframes displayAnime{
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

CSSについて

.wrapper タブ表示による全体部分。横幅指定。
.tab-menu タブの部分。flex指定により、横並びに。
.tab-menu li 各タブの文字の設定。<li>による ’・’ は非表示に。
.tab-menu li a a はリンクになっているタブの文字部分。リンクの下線、文字の色、背景色、余白等の設定。
.tab-menu li a:hover タブの文字にカーソルを合わせている時、文字を太字に。
.tab-menu li.active a activeクラスがついているタブ(選択されているタブ)は色を変える。
.tab-contents タブに対応する一覧表示範囲の設定。
.tab-area 各タブに紐づく一覧表示部分。デフォルトとして非表示に設定。
.tab-area.is-active タブにactiveクラスの付いた一覧表示部分。デフォルトとして非表示から、クラスが付くと一覧をふわっと表示させる。
@keyframes displayAnime 非表示からふわっと表示させるアニメーション。.tab-area.is-active の ”animation-name: displayAnime;” と紐づく。


これでカテゴリーとタブが紐づき、それぞれの一覧が表示されるはずです。

以上です。

Discussion

AirichanAirichan

すごい!うまくまとめてられてる!!
CSSの命名規則で、BEMというものもある!!!
自分のまとめはこのようにしたけど(今見たらわかりずらいから修正するか..!)
よく使われる命名規則でもあるのでみてみると面白いと思う!✨

comugicomugi

ありがとです!
BEMってちゃんと考えられたことないかも。。
もっとよく調べて勉強する!😊