はじめに:【複数タブ選択式】高機能なコンテンツフィルターを実装しよう
Webサイトの記事一覧や制作実績(ポートフォリオ)ページで、ユーザーが複数のカテゴリーや条件を自由に組み合わせてコンテンツを絞り込めるようにしたいと思ったことはありませんか?
通常のフィルター機能は「いずれか一つ」しか選べませんが、本記事で実装するのは、複数のタブを同時に選択し、絞り込み条件を重ねて適用できる、より高度なフィルター機能です。これにより、ユーザーが目的の情報へ素早くたどり着けるようになり、ユーザビリティ(使いやすさ)が大幅に向上します。
この記事では、Web制作の現場で広く使われているJavaScriptライブラリ「jQuery」を使って、この「複数タブ選択式フィルター」を簡単に実装する方法を、コード付きで分かりやすく解説します。
完成:OR条件による同時絞り込み
まずは完成形をご覧ください。このデモでは、選択した複数のタブのいずれか一つでも含むアイテムが表示されるOR(または)条件で絞り込みが動作しています。
複数のタブを選択しても、選択が解除されずに維持される点にご注目ください。
実装方法:HTML、SCSS、jQueryのコード解説
実装は「HTML」「SCSS (CSS)」「jQuery」の3つの要素で構成されます。それぞれのコードと役割を見ていきましょう。
1. HTML(骨組み)
まず、絞り込みのトリガーとなる「タブ」部分と、絞り込み対象となる「コンテンツリスト」部分のHTMLを用意します。ポイントは、jQueryで操作するためのid属性(js_tab_nav, js_tab_contents)と、タブとコンテンツを紐付けるためのdata-tag属性やclass名(tag1, tag2…)です。
HTML
<div class="tab_wrap">
<dl class="tab_head">
<dt>絞り込み</dt>
<dd>
<!-- 絞り込みタブを格納するコンテナ (jQueryで操作するためのID: js_tab_nav) -->
<ul id="js_tab_nav" class="tab_nav">
<!-- タブの項目。data-tag属性の値がコンテンツ側のクラス名と対応 -->
<li><a class="tab_item" data-tag="tag1">桃</a></li>
<li><a class="tab_item" data-tag="tag2">レモン</a></li>
<li><a class="tab_item" data-tag="tag3">メロン</a></li>
</ul>
</dd>
</dl>
<!-- 絞り込み対象となるコンテンツを格納するコンテナ (jQueryで操作するためのID: js_tab_contents) -->
<ul id="js_tab_contents" class="tab_contents">
<!-- 絞り込み対象のコンテンツ単位 (tab_item) -->
<li class="tab_item">
<ul class="tag_list">
<!-- タグ情報(絞り込みの条件となるクラス名を付与) -->
<li class="tag1">桃</li>
<li class="tag2">レモン</li>
<li class="tag3">メロン</li>
</ul>
</li>
<!-- 以下、同様にコンテンツと対応タグを記述 -->
<li class="tab_item">
<ul class="tag_list">
<li class="tag1">桃</li>
<li class="tag2">レモン</li>
</ul>
</li>
<li class="tab_item">
<ul class="tag_list">
<li class="tag1">桃</li>
</ul>
</li>
<li class="tab_item">
<ul class="tag_list">
<li class="tag2">レモン</li>
<li class="tag3">メロン</li>
</ul>
</li>
<li class="tab_item">
<ul class="tag_list">
<li class="tag2">レモン</li>
</ul>
</li>
<li class="tab_item">
<ul class="tag_list">
<li class="tag1">桃</li>
<li class="tag3">メロン</li>
</ul>
</li>
<li class="tab_item">
<ul class="tag_list">
<li class="tag3">メロン</li>
</ul>
</li>
</ul>
</div>
2. SCSS(デザイン)
次に見栄えを整えるためのスタイルシートです。クリックされたタブボタンに付与される.activeクラスのスタイルが特に重要で、これにより、どのタブが選択されているか視覚的に分かります。
SCSS
.tab_wrap {
margin: 2em auto;
width: 80%;
}
.tab_head {
text-align: center;
dt {
line-height: 1;
font-size: 18px;
font-weight: bold;
}
.tab_nav {
margin-top: 1em;
display: flex;
justify-content: center;
flex-wrap: wrap;
width: 100%;
.tab_item {
/* タブボタンの基本デザイン */
margin: 0 2px;
padding: 2px 18px;
border: solid 2px #000;
border-radius: 15px;
display: inline-flex;
align-items: center;
cursor: pointer;
/* クリックで付与されるアクティブ状態(active)のスタイル */
&:hover,
&.active {
border: solid 2px #ffd100;
outline: solid 2px #ff8500;
}
}
}
}
.tab_contents {
/* コンテンツリストのコンテナ */
margin: 2em auto;
display: flex;
justify-content: space-between;
flex-wrap: wrap;
> li {
/* 個別コンテンツ(tab_item)の基本デザイン */
margin-bottom: 1em;
padding: 1em;
border-radius: 5px;
display: flex;
align-items: flex-start;
position: relative;
width: 32%;
background: #f4f4f4;
box-sizing: border-box;
/* NOTE: コンテンツの表示/非表示はjQueryの .show() / .hide() で制御 */
}
.tag_list {
/* コンテンツ内のタグ表示リスト */
display: flex;
flex-direction: column;
li {
margin: 0 2px 5px;
padding: 2px 1em;
border: solid 2px #000;
border-radius: 15px;
display: inline-flex;
align-items: center;
justify-content: center;
white-space: nowrap;
}
}
}
3. jQuery(動き):OR(または)条件のロジック
最後に、絞り込み機能の「動き」を制御するjQueryコードです。このコードが、複数のタブを選択状態に維持し、OR条件でコンテンツを絞り込むという複雑なロジックを担っています。
jQuery
// activeになっているtagを格納するための配列を用意
let activeTagArray = new Array();
// #js_tab_nav .tab_item のいずれかをクリックしたら
$('#js_tab_nav .tab_item').on('click', function() {
//クリックした要素の「data-tag="xxxx"」を取得して変数に格納
const tagData = $(this).data('tag');
//クリックした要素の"active"をtoggle
$(this).toggleClass("active");
//toggleした結果、クリックした要素がactiveを持っていたら、配列にtagDataを追加
if($(this).hasClass("active")) {
activeTagArray.push(tagData);
//toggleした結果、クリックした要素がactiveを持っていなかったら、配列からtagDataを削除
} else {
activeTagArray = activeTagArray.filter(function( item ) {
return item !== tagData;
});
}
// #js_tab_contents .tab_item を 変数「contentTabItem」に格納する
const contentTabItem = $('#js_tab_contents .tab_item');
// contentTabItem を、一旦全て非表示
contentTabItem.hide();
// 配列activeTagArrayに格納されている「tag」を含む contentTabItem を表示させる
activeTagArray.forEach(function(val){
contentTabItem.has('.'+val).show();
});
// 配列activeTagArrayが空の場合(クリックした後、active要素がひとつもない場合)、全てのcontentTabItemを表示
if(!activeTagArray.length) {
contentTabItem.show();
}
});
OR(または)条件のロジック解説
このjQueryコードは、以下の流れで動作することで、「選択したタブのいずれか一つでも含まれていれば表示する」というOR検索を実現しています。
- 選択タブの記録:アクティブなタブの
data-tag属性の値(例:`tag1`)を、配列(`activeTagArray`)に一つずつ記録・削除します。 - リセット:絞り込みを実行する前に、すべてのコンテンツを非表示(
hide())にします。 - OR検索の実行:`activeTagArray`(アクティブなタグのリスト)に一つでもタグが入っている場合、配列内のタグを一つずつループ処理します。
- 部分的な再表示:ループ内で、特定のタグ(例:`.tag1`)をクラス名として持つコンテンツを見つけ、それを再表示(`show()`)します。
- OR条件の成立:このロジックにより、Aタブで表示され、その次にBタブで表示されたコンテンツは、非表示に戻されることなく表示が維持されます。つまり、AまたはBのどちらかを持っていれば表示されることになります。
- 全表示:`activeTagArray`が空(アクティブなタブが一つもない)の場合は、全てのコンテンツを再表示(`show()`)し、絞り込みを解除します。
このように、「全体を隠してから、各アクティブタグに該当するものを順次表示していく」というロジックが、OR検索の重要なポイントです。
まとめ
今回は、jQueryを使って簡単に、Webサイトに複数条件を同時に適用できるフィルター機能を実装する方法を紹介しました。今回ご紹介したOR検索のロジックは、複数のカテゴリーに属するコンテンツの一覧を表示する際に非常に有効です。
HTMLの構造とjQueryのロジックを理解すれば、タイトルにあるようにAND(かつ)条件への応用も可能です。ぜひあなたのWebサイトにも導入して、ユーザーにとってより使いやすいサイトを目指してみてください。
よくある質問(FAQ)
Q1: このコードを動かすには、他に何が必要ですか?
A1: このコードはjQueryライブラリを使用しているため、HTMLファイル内でjQuery本体を読み込む必要があります。</head>タグの直前、または</body>タグの直前に、以下のCDN(Content Delivery Network)のscriptタグを追加するのが最も簡単です。
(※バージョンは2025年10月現在のものです。最新版はjQuery公式サイトで確認してください。)
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
Q2: 選択したタブを「すべて含む」項目だけ表示する(AND検索)にはどうすればいいですか?
A2: AND検索を実装するには、jQueryのロジックを大きく変更する必要があります。現在のコード(OR検索)は「アクティブなタグを一つでも含めば表示」していますが、AND検索では「アクティブなタグをすべて含んでいるか」をチェックします。
具体的には、まず全コンテンツを表示(または非表示)した上で、activeTagArray内の全てのタグ(クラス)をすべて持たないアイテムを特定し、それを非表示にする(または、全て持っているアイテムのみを表示する)ロジックへの変更が必要です。
Q3: タブをクリックしても絞り込みが動きません。
A3: いくつかの原因が考えられます。以下の点を確認してみてください。
- jQueryライブラリ(Q1参照)が正しく読み込まれていますか?
- ブラウザのコンソール(開発者ツール)でJavaScriptのエラーが出ていませんか?
- HTMLに記述した
id名(js_tab_nav,js_tab_contents)と、jQueryコード内のセレクタ指定($('#js_tab_nav ...')など)は一致していますか? - タブボタンの
data-tag属性の値(例:tag1)と、コンテンツリスト内のクラス名(例:.tag1)は正しく対応していますか?
