表示例
絞り込み
128件
- 3,000〜5,000円
- ぷちラボ
アイコン: Font Awesome 7 Free(fa-solid / fa-regular)
別名・英語表記
- ファセット検索
- 絞り込み検索
- 条件パネル
- フィルターパネル
- ファセットナビゲーション
- 検索条件の絞り込み
- 条件検索
- Filter panel
実装例
<section class="x-filter-panel" aria-labelledby="x-filter-panel-h">
<div class="x-filter-panel__head">
<h2 class="x-filter-panel__h" id="x-filter-panel-h">絞り込み</h2>
<p class="x-filter-panel__count" role="status">128件</p>
<button class="x-filter-panel__clear" type="button">条件をクリア</button>
</div>
<ul role="list" class="x-filter-panel__chips" aria-label="選んでいる条件">
<li><span class="x-filter-panel__chip">3,000〜5,000円<button class="x-filter-panel__x" type="button" aria-label="3,000〜5,000円 の条件を外す"><i class="fa-solid fa-xmark" aria-hidden="true"></i></button></span></li>
<li><span class="x-filter-panel__chip">ぷちラボ<button class="x-filter-panel__x" type="button" aria-label="ぷちラボ の条件を外す"><i class="fa-solid fa-xmark" aria-hidden="true"></i></button></span></li>
</ul>
<div class="x-filter-panel__groups">
<fieldset class="x-filter-panel__g">
<legend class="x-filter-panel__lg">価格帯</legend>
<label class="x-filter-panel__r"><input type="checkbox" name="price" value="0-3000">〜3,000円<span class="x-filter-panel__n">42件</span></label>
<label class="x-filter-panel__r"><input type="checkbox" name="price" value="3000-5000" checked>3,000〜5,000円<span class="x-filter-panel__n">61件</span></label>
<label class="x-filter-panel__r"><input type="checkbox" name="price" value="5000-">5,000円〜<span class="x-filter-panel__n">25件</span></label>
</fieldset>
<fieldset class="x-filter-panel__g">
<legend class="x-filter-panel__lg">ブランド</legend>
<label class="x-filter-panel__r"><input type="checkbox" name="brand" value="puchi" checked>ぷちラボ<span class="x-filter-panel__n">54件</span></label>
<label class="x-filter-panel__r"><input type="checkbox" name="brand" value="mori">もり工房<span class="x-filter-panel__n">38件</span></label>
<label class="x-filter-panel__r"><input type="checkbox" name="brand" value="sora">そら製作所<span class="x-filter-panel__n">36件</span></label>
</fieldset>
</div>
</section>
/* 貼った先のリセットに頼らないよう、この部品の中だけ border-box にする */
.x-filter-panel,
.x-filter-panel *:not([class*="fa-"]),
.x-filter-panel *:not([class*="fa-"])::before,
.x-filter-panel *:not([class*="fa-"])::after {
box-sizing: border-box;
/* 貼った先の既定の書体に引きずられないようにする。書体が変わると
文字の幅と高さが変わり、枠のサイズまでずれる */
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Hiragino Sans", "Noto Sans JP", "Yu Gothic UI", Meiryo, sans-serif;
}
.x-filter-panel {
width: 340px;
max-width: 100%; /* 狭い画面では親の幅に合わせて縮む */
padding: 10px 12px 8px;
border: 1px solid #cfd4dc;
border-radius: 10px;
background: #fff;
color: #1b2028;
}
.x-filter-panel__head {
display: flex;
align-items: center;
gap: 8px;
}
.x-filter-panel__h {
margin: 0;
font-size: 13px;
font-weight: 700;
}
.x-filter-panel__count {
margin: 0;
font-size: 11px;
color: #56606f;
}
.x-filter-panel__clear {
min-height: 26px;
margin-left: auto;
padding: 2px 8px;
border: 1px solid #7f8a99;
border-radius: 6px;
background: #fff;
color: #1b2028;
font: inherit;
font-size: 11px;
cursor: pointer;
}
.x-filter-panel__chips {
display: flex;
flex-wrap: wrap;
gap: 6px;
margin: 8px 0 4px;
padding: 0;
list-style: none;
}
.x-filter-panel__chip {
display: inline-flex;
align-items: center;
gap: 2px;
padding: 0 0 0 10px;
border: 1px solid #1d4ed8;
border-radius: 999px;
background: #eff4ff;
color: #1d3fae;
font-size: 11px;
}
.x-filter-panel__x {
width: 24px;
height: 24px;
border: 0;
border-radius: 50%;
background: none;
color: #1d3fae;
font-size: 11px;
cursor: pointer;
}
.x-filter-panel__groups {
display: flex;
gap: 10px;
}
.x-filter-panel__g {
flex: 1;
min-width: 0;
margin: 0;
padding: 0;
border: 0;
}
.x-filter-panel__lg {
padding: 4px 0 2px;
font-size: 11.5px;
font-weight: 700;
}
.x-filter-panel__r {
display: flex;
align-items: center;
gap: 6px;
min-height: 26px;
font-size: 11.5px;
cursor: pointer;
}
.x-filter-panel__r input {
width: 15px;
height: 15px;
margin: 0;
accent-color: #1d4ed8;
}
.x-filter-panel__n {
margin-left: auto;
font-size: 12px;
color: #56606f;
}
.x-filter-panel__clear:focus-visible,
.x-filter-panel__x:focus-visible,
.x-filter-panel__r input:focus-visible {
outline: 2px solid #1d4ed8;
outline-offset: 1px;
}
AIへの指示文
「絞り込みパネル(Filter panel)」を実装してください。
## これは何か
価格帯やブランドなどの項目ごとにチェックボックスと件数を並べ、選んだ条件のチップと該当件数を上に出す箱。通販や検索結果の横に置く。
## 使いどころ
- 通販や求人・不動産のように、件数が多い一覧を複数の条件で絞らせたいとき
- 条件ごとの件数を見せて、0件になる選び方を避けさせたいとき
- 表の上に置く小さな絞り込み(テーブルツールバー)では条件が収まらないとき
## 実装の要件
- section[aria-labelledby] > 見出し + 件数(role=status)+ 「条件をクリア」button + 選択中の条件のチップ + fieldset > legend + label > input[type=checkbox] + 件数
- 条件は URL のクエリに反映し、読み込み時にそこから復元する
- 狭い画面ではドロワーかボトムシートに移し、結果を表示するボタンを下端に置く
- 同じ項目の中は「または」、項目どうしは「かつ」で絞るのが通例。違う決まりにするなら画面に書く
- 選んだ瞬間に一覧を更新するか「適用」ボタンを押させるかを決めて揃える。混ぜると、押したのに変わらないと思われる
- 選ぶと0件になる条件は、件数「0件」を出して押せないようにするか、選べることを残すかを決めておく
- 条件は URL のクエリに残す。戻るボタンや共有で条件が消えると、最初から選び直しになる
- 狭い画面では横に置けない。「絞り込み」ボタンからドロワーやボトムシートで開き、下に「128件を表示」のボタンを置く
## アクセシビリティの要件
- 項目ごとに fieldset と legend でまとめる。チェックボックスは label で囲み、件数もラベルの中に入れる
- 該当件数は role="status" の要素に書き、変わったことを控えめに伝える。チェックのたびにフォーカスを動かさない
- 選んだ条件のチップにある × には「(条件名)の条件を外す」の名前を付ける。外したあとはボタンが消えるので、隣のチップか見出しへフォーカスを移す
- 条件が選ばれていることを色だけで示さない。チェックの印とチップの文字で示す
## 参考にする実装
この形を出発点にして、プロジェクトの命名規則・色・余白に合わせて調整してください。
```html
<section class="x-filter-panel" aria-labelledby="x-filter-panel-h">
<div class="x-filter-panel__head">
<h2 class="x-filter-panel__h" id="x-filter-panel-h">絞り込み</h2>
<p class="x-filter-panel__count" role="status">128件</p>
<button class="x-filter-panel__clear" type="button">条件をクリア</button>
</div>
<ul role="list" class="x-filter-panel__chips" aria-label="選んでいる条件">
<li><span class="x-filter-panel__chip">3,000〜5,000円<button class="x-filter-panel__x" type="button" aria-label="3,000〜5,000円 の条件を外す"><i class="fa-solid fa-xmark" aria-hidden="true"></i></button></span></li>
<li><span class="x-filter-panel__chip">ぷちラボ<button class="x-filter-panel__x" type="button" aria-label="ぷちラボ の条件を外す"><i class="fa-solid fa-xmark" aria-hidden="true"></i></button></span></li>
</ul>
<div class="x-filter-panel__groups">
<fieldset class="x-filter-panel__g">
<legend class="x-filter-panel__lg">価格帯</legend>
<label class="x-filter-panel__r"><input type="checkbox" name="price" value="0-3000">〜3,000円<span class="x-filter-panel__n">42件</span></label>
<label class="x-filter-panel__r"><input type="checkbox" name="price" value="3000-5000" checked>3,000〜5,000円<span class="x-filter-panel__n">61件</span></label>
<label class="x-filter-panel__r"><input type="checkbox" name="price" value="5000-">5,000円〜<span class="x-filter-panel__n">25件</span></label>
</fieldset>
<fieldset class="x-filter-panel__g">
<legend class="x-filter-panel__lg">ブランド</legend>
<label class="x-filter-panel__r"><input type="checkbox" name="brand" value="puchi" checked>ぷちラボ<span class="x-filter-panel__n">54件</span></label>
<label class="x-filter-panel__r"><input type="checkbox" name="brand" value="mori">もり工房<span class="x-filter-panel__n">38件</span></label>
<label class="x-filter-panel__r"><input type="checkbox" name="brand" value="sora">そら製作所<span class="x-filter-panel__n">36件</span></label>
</fieldset>
</div>
</section>
```
```css
/* 貼った先のリセットに頼らないよう、この部品の中だけ border-box にする */
.x-filter-panel,
.x-filter-panel *:not([class*="fa-"]),
.x-filter-panel *:not([class*="fa-"])::before,
.x-filter-panel *:not([class*="fa-"])::after {
box-sizing: border-box;
/* 貼った先の既定の書体に引きずられないようにする。書体が変わると
文字の幅と高さが変わり、枠のサイズまでずれる */
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Hiragino Sans", "Noto Sans JP", "Yu Gothic UI", Meiryo, sans-serif;
}
.x-filter-panel {
width: 340px;
max-width: 100%; /* 狭い画面では親の幅に合わせて縮む */
padding: 10px 12px 8px;
border: 1px solid #cfd4dc;
border-radius: 10px;
background: #fff;
color: #1b2028;
}
.x-filter-panel__head {
display: flex;
align-items: center;
gap: 8px;
}
.x-filter-panel__h {
margin: 0;
font-size: 13px;
font-weight: 700;
}
.x-filter-panel__count {
margin: 0;
font-size: 11px;
color: #56606f;
}
.x-filter-panel__clear {
min-height: 26px;
margin-left: auto;
padding: 2px 8px;
border: 1px solid #7f8a99;
border-radius: 6px;
background: #fff;
color: #1b2028;
font: inherit;
font-size: 11px;
cursor: pointer;
}
.x-filter-panel__chips {
display: flex;
flex-wrap: wrap;
gap: 6px;
margin: 8px 0 4px;
padding: 0;
list-style: none;
}
.x-filter-panel__chip {
display: inline-flex;
align-items: center;
gap: 2px;
padding: 0 0 0 10px;
border: 1px solid #1d4ed8;
border-radius: 999px;
background: #eff4ff;
color: #1d3fae;
font-size: 11px;
}
.x-filter-panel__x {
width: 24px;
height: 24px;
border: 0;
border-radius: 50%;
background: none;
color: #1d3fae;
font-size: 11px;
cursor: pointer;
}
.x-filter-panel__groups {
display: flex;
gap: 10px;
}
.x-filter-panel__g {
flex: 1;
min-width: 0;
margin: 0;
padding: 0;
border: 0;
}
.x-filter-panel__lg {
padding: 4px 0 2px;
font-size: 11.5px;
font-weight: 700;
}
.x-filter-panel__r {
display: flex;
align-items: center;
gap: 6px;
min-height: 26px;
font-size: 11.5px;
cursor: pointer;
}
.x-filter-panel__r input {
width: 15px;
height: 15px;
margin: 0;
accent-color: #1d4ed8;
}
.x-filter-panel__n {
margin-left: auto;
font-size: 12px;
color: #56606f;
}
.x-filter-panel__clear:focus-visible,
.x-filter-panel__x:focus-visible,
.x-filter-panel__r input:focus-visible {
outline: 2px solid #1d4ed8;
outline-offset: 1px;
}
```
## 出力の約束
- HTML と CSS を分けて出す。JavaScript が要るときは素の JavaScript で書き、UIフレームワークは使わない。
- 参考実装がアイコンに Font Awesome のクラスを使っている場合は、プロジェクトで使っているアイコンかインライン SVG に置き換えてよい。
- 上のアクセシビリティ要件を満たす。満たせない箇所があるときは、理由を添えて先に知らせる。
- 色・角丸・余白は既存のデザイントークンがあればそれを使う。無ければ CSS 変数として切り出す。
使いどころ
- 通販や求人・不動産のように、件数が多い一覧を複数の条件で絞らせたいとき
- 条件ごとの件数を見せて、0件になる選び方を避けさせたいとき
- 表の上に置く小さな絞り込み(テーブルツールバー)では条件が収まらないとき
注意点
- 同じ項目の中は「または」、項目どうしは「かつ」で絞るのが通例。違う決まりにするなら画面に書く
- 選んだ瞬間に一覧を更新するか「適用」ボタンを押させるかを決めて揃える。混ぜると、押したのに変わらないと思われる
- 選ぶと0件になる条件は、件数「0件」を出して押せないようにするか、選べることを残すかを決めておく
- 条件は URL のクエリに残す。戻るボタンや共有で条件が消えると、最初から選び直しになる
- 狭い画面では横に置けない。「絞り込み」ボタンからドロワーやボトムシートで開き、下に「128件を表示」のボタンを置く
アクセシビリティの要点
- 項目ごとに fieldset と legend でまとめる。チェックボックスは label で囲み、件数もラベルの中に入れる
- 該当件数は role="status" の要素に書き、変わったことを控えめに伝える。チェックのたびにフォーカスを動かさない
- 選んだ条件のチップにある × には「(条件名)の条件を外す」の名前を付ける。外したあとはボタンが消えるので、隣のチップか見出しへフォーカスを移す
- 条件が選ばれていることを色だけで示さない。チェックの印とチップの文字で示す