今回実装した「タブ」について、忘備録です。
今年の6月ごろに、HIROKIさんが運営する「CodeUps」に加入しました。
現在は、トップページの実装を終え、フィードバックでOKをもらい、下層ページ全部をコーディングしている途中です。
下層ページの「Information」のページに、タブの実装が出て来たので、それについてまとめてみたいと思います。
しょーごさんの「JS特訓編」を参考にしました。
CodeUpsに加入する前は、独学でしょーごさん(@samuraibrass)のコーディング課題を中級EXまで進めました。
今回、セットで購入した、JS特訓用の課題を参考にさせていただきました。
一応、「難しいと思うので、最初は丸コピーでもかまいません」と、しょーごさんもおっしゃっているので、とりあえずコピーして、そこから加工するという方法を取りました。
HTMLとCSSはなんとなく書けるのですが、Javascript, jQueryについてはまだ理解が浅く、自分で書くことはできないんですよね・・・。
タブの構造
まず、タブの構造についてですが、切り替えのためのスイッチである「タブ (tab)」と、タブを押した時に表示される内容を「コンテンツ (tab-contents)」として、二つに分けてhtmlを記述しました。
「タブ1」をクリックしたら、「コンテンツ1」が表示されるように、タブとコンテンツを紐づけて表示します。
下記の画像で、青く選択されている部分が「tab」の部分です。
下記の画像は、「tab-contents」の部分です。
jQueryで実装する(考え方)
しょーごさんの課題には、jQueryとJavaScriptの両方の実装方法が書かれていて、比較することによって学習できるようになっています。
私はまだJavaScriptが得意ではないので、今回はjQueryで実装しました。
大まかな考え方としては、二つかな。
- 「is-active」というクラス名のつけ外しによって、表示するものと表示しないものを切り替える
- tabとtab-contentsで紐づけたいものに、同じdata-idをつけておく
JavaScriptを実装する時に、参考のために色々なサイトを見るのですが、本当に千差万別で、みんな書き方が違うのですよね。どういう考え方で実装しているのかの説明なしに、いきなりコードが提供されても、私は読み解くことができません。。。
なので、しょーごさんの課題は、一つのやり方として説明があって、とりあえず自分でも書いてみる、理解できたら他の書き方も試してみる、一つの指針という使い方ができるので、本当に役立っています。いつも有難うございます。
HTMLの書き方
まずは、tabのブロックと、tab-contentsのブロックを分けてhtmlを記述します。
実際に記述したコードは以下のとおりです。
まだ正式にフィードバックを受けていないので、BEMの書き方やhtml構造については、参考程度としてください。
(見づらくてすみません・・)
ポイントは、ブロックを二つに分ける、というところです。
<!-- タブ -->
<div class="page-information__tab tab">
<ul class="tab__items">
<li class="tab__item js-tab-trigger is-active" data-id="tab01">
<span>
ライセンス<br class="u-mobile">講習
</span>
</li>
<li class="tab__item js-tab-trigger" data-id="tab02">
<span>
ファン<br class="u-mobile">ダイビング
</span>
</li>
<li class="tab__item js-tab-trigger" data-id="tab03">
<span>
体験<br class="u-mobile">ダイビング
</span>
</li>
</ul>
</div>
<!-- タブコンテンツ -->
<div class="page-information__tab-contents tab-contents">
<ul class="tab-contents__items">
<li class="tab-contents__item js-tab-target is-active" id="tab01">
<div class="tab-contents__heading">
<h2 class="tab-contents__title">
ライセンス講習
</h2>
<p class="tab-contents__text">
泳げない人も、ちょっと水が苦手な人も、ダイビングを「安全に」楽しんでいただけるよう、スタッフがサポートいたします!スキューバダイビングを楽しむためには最低限の知識とスキルが要求されます。知識やスキルと言ってもそんなに難しい事ではなく、安全に楽しむ事を目的としたものです。プロダイバーの指導のもと知識とスキルを習得しCカードを取得して、ダイバーになろう!
</p>
</div>
<figure class="tab-contents__image">
<img src="./assets/images/common/sub-information__license.jpg" alt="海に浮かぶダイバーたちの画像">
</figure>
</li>
<li class="tab-contents__item js-tab-target" id="tab02">
<div class="tab-contents__heading">
<h2 class="tab-contents__title">
ファンダイビング
</h2>
<p class="tab-contents__text">
ブランクダイバー、ライセンスを取り立ての方も安心!沖縄本島を代表する「青の洞窟」(真栄田岬)やケラマ諸島などメジャーなポイントはモチロンのこと、最北端「辺戸岬」や最南端の「大渡海岸」等もご用意!
</p>
</div>
<figure class="tab-contents__image">
<img src="./assets/images/common/sub-information__fundiving.jpg" alt="小魚の大群の画像">
</figure>
</li>
<li class="tab-contents__item js-tab-target" id="tab03">
<div class="tab-contents__heading">
<h2 class="tab-contents__title">
体験ダイビング
</h2>
<p class="tab-contents__text">
ブランクダイバー、ライセンスを取り立ての方も安心!沖縄本島を代表する「青の洞窟」(真栄田岬)やケラマ諸島などメジャーなポイントはモチロンのこと、最北端「辺戸岬」や最南端の「大渡海岸」等もご用意!
</p>
</div>
<figure class="tab-contents__image">
<img src="./assets/images/common/sub-information__diving.jpg" alt="二匹の黄色い魚の画像">
</figure>
</li>
</ul>
</div>
表示したいtabとtab-contentsに、「is-active」というクラス名がつくようにしたいので、一番左の「ライセンス講習」のタブと、それに紐づいているタブコンテンツのところに、is-activeのクラスをあらかじめつけておきます。
それによって、この二つは、「最初から表示されている」状態になります。
逆に、二つ目と三つ目のタブと、それに紐づくコンテンツは、クリックした時にjQueryでis-activeをつけるので、HTMLではis-activeのクラス名をつける必要はありません。
次に、クリックするタブの方に、js-tab-triggerというクラス名を付け、表示されるコンテンツの方に、js-tab-targetというクラス名をつけておきます。これは、tabとtab-contentsのそれぞれからis-activeをつけ外しできるようにするためですね。
次に、クリックしたタブに紐づく内容を同時に表示できるように、タブとコンテンツに共通のidをつけます。
今回の場合は、data-id=”tab01″です。同じdata-idを、タブの方にも、コンテンツの方にも付けます。
(二つ目と三つ目は、それぞれdata-id=”tab02″、data-id=”tab03″とします。)
私の場合は、タブの方もコンテンツの方も、ulとliタグで記述しました。
data-idはどちらもliタグにつけました。
この状態で、先にjQueryを記述して、まずは動くかどうかを確認します。
最初から表示させたい要素にis-activeクラスをつけておく
あとから表示させたい要素にはis-activeはつけなくて良い
タブとタブコンテンツに、それぞれjs-tab-trigger、js-tab-targetのクラス名をつける
同時に表示させたいtabとtab-contentsに、同じdata-idをつける
jQueryの書き方
今回、jQueryは、しょーごさんの課題をそのまま使ったので、画像で貼っておきます。(一応販売されている課題なので、コード丸写しを提供するのは良くないと思いますので・・・)
内容としては、
①js-tab-triggerをクリックした時に、
②全部のjs-tab-trigger(つまりタブの方)から、is-activeクラスを削除
③全部のjs-tab-target(つまりタブコンテンツの方)から、is-activeクラスを削除
④次にクリックした要素にis-activeをつけて
⑤data-idで紐づいている要素を一緒に表示する
という流れですね。
非常にシンプルですが、こんなブログを書いている私も、最初は理解できなくて、頭の中がハテナだらけでした・・・。
jQueryが動かなかった場合
最近では、chatGPTに聞けば大体解決しますが、例えば、jQueryのコードをchatGPTに貼り付けて、「クリックしても動きません。コンソールに何と入力すれば確認できますか?」「入力したら、jQueryのバージョンが表示されましたが、そのほかに何も表示されません。」など、段階を追って質問を繰り返し、なんとか回答を得ています。
jQueryやJavaScriptの場合は、数値が取れているか、意図した動きになっているか、検証ツールのコンソールで確認することができるんですね。
JavaScriptの学習を始めたころに、いきなり「コンソールに表示」する方法を説明されて、表示して何の意味があるのか??さっぱり分かりませんでした。今になって、やっと使い方がわかりましたよ・・・。
CSSの書き方
CSSについては、デザインカンプによるので、ここではポイントだけ。
今回のデザインでは、選択されているタブとそうでないタブの、「背景色」「文字色」「アイコンの色」を変える必要がありました。
方法としては、まず最初は普通に「選択されていない方のタブ」のデザインをひととおりコーディングして、あとから、選択されているタブすなわち「is-active」が付いているデザインを追加でコーディングしました。
例えば、tab__itemの背景色と文字色を変える場合は、こんな感じ。
ちなみに、tab__itemとis-activeは、親子関係ではなく、同じ要素についているクラス名なので、並べて記述するときには、スペース無しで書く必要があります。スペースが入っていると適用されないので、要注意です。
そしてもう一点大事なのが、タブコンテンツの方は、初期状態ではdisplay:none;で非表示にしておきます。
is-activeが付いた時に、表示されるようにしたいので、is-activeがついたら、display: block;で表示させます。(私の場合は、PC幅ではdisplay: grid;を使いました。)
初期状態では非表示ですが、最初から表示しておきたい要素には、あらかじめis-activeをつけているので、非表示にはなりません。
一つ、難しかったのは、タブについているクジラなどのアイコンです。
最初は、htmlにimgタグで記述していたのですが、is-activeが付いている時とそうで無い時に、色の違うアイコンを出し分ける必要があったので、最終的には、tab__item spanに、擬似要素で背景としてアイコンを配置し、is-activeが付いた時には、背景にあてる画像を別のものに変える、という方法を取りました。
もしかしたら、htmlに記述しても、pictureタグなどで出しわけができるかもしれません??これから調べてみようと思います。
そして、いつも思うのですが、jQueryやJavaScriptなど、後から動きをつける要素って、動きが付いていない時はどういう状態??って気になりませんか??
デザインカンプだと、JSで切り替える画像は、横並びで提供されていたりしますが、、、JSを記述する前の、HTMLとCSSだけの時って、どういう状態なんだ?みんなどうしているんだろう??と非常に気になります・・・。
今回のタブの場合は、jQueryを実装する前は、tab-contentsが縦一列にばーっと並んだ状態になっていました。
まとめ
ということで、無事にタブを実装することができました。
ほかにも、色々な書き方がありますが、一つコレ!というやり方を知っておけば、その他の書き方を見た時に、比較できるので、頭に入りやすいかと思います。
クラス名などは、自分が使いやすいように変えても良いと思いますので、これからもっと理解を深めて、自分流に書けるようになりたいです。
さて、次はアコーディオンの実装をがんばるぞ〜!
コメント