Pocket

こんにちは、未経験からITエンジニアへの転職を目指しているごんにんごんです。

今日はjQueryの「タブ切り替え機能」について、理解を深めるために記載したいと思います。

というのも、現在所属しているTechCampでは、Ruby on Railsを使ったサーバーサイドの演習がメイン(カリキュラム全体の8割強)となっています。そのため、カリキュラムをやり通しても、「あれ?HTML/CSSに触るの、カリキュラムの3日目以来だな…」とか、「JavaScriptって発火くらいしかわかってない」てな感じで、フロントの知識がほぼ身についていないのです(体験談)

今取り組んでいるWebアプリケーションもそうですが、アプリケーションを作る上でフロントの知識も必須のはず。本来ならフロントの専門書を一読してから、進めるべきかもしれませんが、私はこんな▼感じで手を動かしながら身につけようと思います。

  1. アプリケーションに○○な機能を導入したい、どうやってやるんだろう?
  2. 類似事例を見つけた!私のアプリケーションだとどうなるだろう?
  3. アウトプットで内容を知識定着させよう

ということで、jQueryのアウトプットをやっていきたいと思います。

こんな機能を作った!

冷蔵庫のシェアリングアプリを制作中なんですが、ユーザーに食材を登録してもらう機能を実装しています。

シンプルに作るのであれば、「食材ごとにカテゴリをプルダウンで選んでもらう」方法かなと思いますが、ユーザー視点で考えてみると、、、

  • 食材の登録する量は思いのほか有る。登録の度に、プルダウンでカテゴリを選んでもらうのは手間。
  • 面倒なステップが一つでもあれば、アプリから離れてしまうので、極力「操作させない」ことがポイント。

だと思ったので、タブで切り替えることにしました。

Image from Gyazo

HTMLファイル

まずはHTMLファイルについて説明します。

構成は以下の通りです。

  • “タブエリア”“コンテンツエリア”として、2つのクラスを用意する。
  • デフォルトで表示させるタブ(今回は一番上のタブ)のクラスに、”active”を付与しておく。
  • タブと連動させる形で、表示させるコンテンツのクラスに、”show”を付与しておく。

HTMLファイルにごちゃごちゃ書いてますが、5つの「タブクラス」と「コンテンツクラス」が有るんだなぁと思ってください。

“active”と”show”については、この後のCSSファイルで説明します。

<div class="item-contents">
  <h2 class="items-sell-title">食材 <i class="fa-solid fa-box-archive"></i> を登録しよう</h2>
  <h3>登録する食材のカテゴリを選ぼう!</h3>
  <div class="tab-area">
    <div class="tab active" id="tab-fish" data-value='1' >
      <i class="fa-solid fa-fish fa-2x"></i>Fish
    </div>
    <div class="tab" id="tab-veg" data-value='2' >
      <i class="fa-solid fa-carrot fa-2x"></i>Vegitable
    </div>
    <div class="tab" id="tab-meat" data-value='3'>
      <i class="fa-solid fa-cow fa-2x"></i>Meat
    </div>
    <div class="tab" id="tab-drink" data-value='4'>
      <i class="fa-solid fa-wine-bottle fa-2x"></i>Drink
    </div>
    <div class="tab" id="tab-flozen" data-value='5'>
      <i class="fa-solid fa-ice-cream fa-2x"></i>Flozen
    </div>
  </div>
  
  <%# <div class="items-sell-main"> %>
  <div class="content-area">
    <%= form_with model: @form, url: box_foods_path, method: :post, local: true do |form| %>
      <%= render 'shared/foods_error_messages', model: @form %>
        <%# TODO : フォーム追加できるようにする。https://web-tsuku.life/add-form-appendchild/ %>
      <div class="content show">
        <%= render partial: 'shared/fields_for', locals:{ form: form, i: 1 } %>
      </div>

      <div class="content">
        <%= render partial: 'shared/fields_for', locals:{ form: form, i: 2 } %>
      </div>

      <div class="content">
          <%= render partial: 'shared/fields_for', locals:{ form: form, i: 3 } %>
      </div>

      <div class="content">
        <%= render partial: 'shared/fields_for', locals:{ form: form, i: 4 } %>
      </div>

      <div class="content">
        <%= render partial: 'shared/fields_for', locals:{ form: form, i: 5 } %>
      </div>

      <div class="sell-btn-contents">
        <%= form.submit "登録する" ,class:"sell-btn", id:"food-btn" %>
        <%=link_to 'もどる', root_path, class:"back-btn" %>
      </div>
    <% end %>
  </div>
</div>

JavaScriptファイル

次に肝要のJSファイルについて。実装の流れは、以下の通りです。

  1. 【タブ】いずれかのタブがクリックされたら発火する。
  2. 【タブ】クリックされていることを表すために色を変えるクラス(activeクラス)が、タブクラスにくっついているので、全て外す。
  3. 【タブ】クリックされたタブにactiveクラスを付与する。
  4. 【共通】何番目のタブがクリックされたか判定する。
  5. 【コンテンツ】コンテンツを表示させるためのクラス(showクラス)が、コンテンツクラスにくっついているので、全て外す。
  6. 【コンテンツ】4で判定したタブ・コンテンツに対して、showクラスを付与する。

クリックを起点にして、activeクラスとshowクラスを使って、タブ遷移を実装していますね。どうやって実装しているんでしょうか。CSSを見てみましょう。

const tab = () => {
  let tabs = $(".tab"); // tabのクラスを全て取得し、変数tabsに配列で定義
  $(".tab").on("click", function() { // tabをクリックしたらイベント発火
    $(".active").removeClass("active"); // activeクラスを消す
    $(this).addClass("active"); // クリックした箇所にactiveクラスを追加
    const index = tabs.index(this); // クリックした箇所がタブの何番目か判定し、定数indexとして定義
    $(".content").removeClass("show").eq(index).addClass("show"); // showクラスを消して、contentクラスのindex番目にshowクラスを追加
  })

window.addEventListener('DOMContentLoaded',tab)

CSSファイル

CSSファイルは以下のとおりです。

.tab-area {
  display: flex;
  justify-content: space-around;
  background-color: #222e3e;
  cursor: pointer;
  margin-top: 30px;
  .tab {
    width: 200px;
    height: 60px;
    line-height: 30px;
    text-align: center;
    padding: 10px 0;
    color: white;
    border-right: 1px solid #50637b;
    border-left: 1px solid #222e3e;
  }
  // activeクラス : 色を変えることで、選択されていることを表す
  .tab.active {
    background-color: #ccc;
    color: #222e3e;
    border: none;
  }
}

.content-area {
  font-size: 30px;
  text-align: center;
  // contentクラス : display: noneなので、基本的に非表示
  .content {
    display: none;
  }
  // showクラス : display: blockとすることで、コンテンツが表示される
  .content.show {
    margin-top: 50px;
    display: block;
  }
}

ポイントは、タブエリアとコンテンツエリアでのタブ遷移の実装方法です。

タブエリア(activeクラス)

   .tab {
    width: 200px;
    height: 60px;
    line-height: 30px;
    text-align: center;
    padding: 10px 0;
    color: white;
    border-right: 1px solid #50637b;
    border-left: 1px solid #222e3e;
  }
 // activeクラス : 色を変えることで、選択されていることを表す
  .tab.active {
    background-color: #ccc;
    color: #222e3e;
    border: none;
  }

クリックされているタブの色を変えることで表現しています。JavaScriptにて、activeクラスが付与されると、色が変わる(クリックされた)ようになっています。

コンテンツエリア(showクラス)

  // contentクラス : display: noneなので、基本的に非表示
  .content {
    display: none;
  }
  // showクラス : display: blockとすることで、コンテンツが表示される
  .content.show {
    margin-top: 50px;
    display: block;
  }

こちらは、表示・非表示でタブの遷移を表現しています。基本的にコンテンツは、display: noneによって非表示となっています。JavaScriptにて、showクラスが付与されると、display: blockによって表示される仕組みです。

まとめ

ホームページでよく目にするタブは、クリックを起点として「タブ遷移を司るクラスの付け外し」していたのだと理解できました。

タブ機能を実装したことで、ユーザビリティの観点で使いやすくなったと思いますので、ぜひ導入してみてください。

投稿者

waco@jp

30代未経験でエンジニア転職を目指しています。前職はメーカーで営業と製品開発を担当。22年3月からTechCampを受講し、5月に卒業。現在、就活とオリジナルアプリケーション制作の両輪で活動しています。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です