表示例
商品小計 4,180円
配送料 5,000円以上のご注文で無料になります。沖縄・離島は別途1,100円かかります。 550円
アイコン: Font Awesome 7 Free(fa-solid / fa-regular)
別名・英語表記
- ヘルプアイコン
- はてなアイコン
- インフォアイコン
- 説明の吹き出しボタン
- インフォメーションアイコン
- ハテナボタン
- Toggletip
実装例
<div class="x-toggletip">
<p class="x-toggletip__row">
<span class="x-toggletip__k">商品小計</span>
<span class="x-toggletip__v">4,180円</span>
</p>
<p class="x-toggletip__row">
<span class="x-toggletip__k">配送料</span>
<span class="x-toggletip__w">
<button class="x-toggletip__b" type="button" aria-label="配送料について">
<i class="fa-solid fa-circle-info" aria-hidden="true"></i>
</button>
<!-- 読み上げに届けるための入れ物。ふだんは空で、押されたら JS が一度空にしてから文を入れる。
見本なので文が入った(開いた)状態にしてある -->
<span class="x-toggletip__live" role="status">
<span class="x-toggletip__t">5,000円以上のご注文で無料になります。沖縄・離島は別途1,100円かかります。</span>
</span>
</span>
<span class="x-toggletip__v">550円</span>
</p>
</div>
/* 貼った先のリセットに頼らないよう、この部品の中だけ border-box にする */
.x-toggletip,
.x-toggletip *:not([class*="fa-"]),
.x-toggletip *:not([class*="fa-"])::before,
.x-toggletip *: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-toggletip {
width: 280px;
max-width: 100%;
padding: 12px 16px;
border: 1px solid #7f8a99;
border-radius: 8px;
background: #fff;
color: #1b2028;
font-size: 14px;
}
.x-toggletip__row {
display: flex;
align-items: center;
gap: 6px;
margin: 0;
padding: 8px 0;
}
/* 吹き出しは下の内容に重なって出る。見本では重ねる先が無いので、そのぶんの高さを取っておく */
.x-toggletip {
min-height: 170px;
}
.x-toggletip__row + .x-toggletip__row {
border-top: 1px solid #e3e6ea;
}
.x-toggletip__v {
margin-left: auto;
}
/* 吹き出しの位置の基準。ボタンのすぐ下に出す */
.x-toggletip__w {
position: relative;
display: inline-flex;
}
.x-toggletip__b {
display: grid;
place-items: center;
width: 24px;
height: 24px;
padding: 0;
border: 0;
border-radius: 50%;
background: none;
color: #1d4ed8;
font-size: 16px;
cursor: pointer;
}
.x-toggletip__b:hover {
background: #eef2fb;
}
.x-toggletip__b:focus-visible {
outline: 2px solid #1d4ed8;
outline-offset: 1px;
}
/* 入れ物が空のときは何も描かない(吹き出しの枠だけ残らないように) */
.x-toggletip__live:empty {
display: none;
}
.x-toggletip__t {
position: absolute;
top: calc(100% + 8px);
left: -12px;
z-index: 10;
width: 210px;
padding: 8px 10px;
border-radius: 6px;
background: #1b2028;
color: #fff;
font-size: 12px;
font-weight: 400;
line-height: 1.6;
}
.x-toggletip__t::before {
content: "";
position: absolute;
bottom: 100%;
left: 18px;
border: 6px solid transparent;
border-bottom-color: #1b2028;
}
AIへの指示文
「トグルチップ(Toggletip)」を実装してください。
## これは何か
項目名の横の小さな「i」や「?」のボタン。押すと短い説明の吹き出しが出て、Esc か外側を押すまで出たままになる。
## 使いどころ
- 入力欄や料金の項目に、読まなくても進められるが知りたい人には要る補足(計算のしかた・条件)を添えたいとき
- タッチ端末でも読ませたい補足で、ホバーで出すツールチップでは届かないとき
## 実装の要件
- span > button[type="button"][aria-label] + span[role="status"] の構成にし、説明の文は初めは入れずに JavaScript で入れる
- 吹き出しは外側の span(ボタンと role="status" の入れ物をまとめる要素)を position: relative; にし、文の要素を position: absolute; top: calc(100% + 8px); で下へ重ねる。これを未対応のブラウザ向けの下地に残す
- はみ出す側への反転は @supports (anchor-scope: all) の中でアンカー配置に任せる(Chrome・Edge は 131 から、Safari は 26 から、Firefox は 147 から)
- @supports の中では、外側の span に anchor-scope: --tip、ボタンに anchor-name: --tip を付ける
- @supports の中で、文の要素を position: fixed; position-anchor: --tip; inset: auto; margin-top: 8px; position-area: block-end span-inline-end; にする
- 同じ @supports の中で、反転の候補を position-try-fallbacks: flip-inline, flip-block, flip-block flip-inline; で並べる
- anchor-scope を付けないと、並べたときにどの吹き出しも最後のボタンに付く。付けるのは外側の span で、role="status" の入れ物に付けるとボタンが範囲の外になり、吹き出しがボタンに付かない
- inset: auto で下地の top と left を打ち消さないと、吹き出しが画面の外へずれる
- 文の要素の width は外さない。幅を決めないと画面の端までの残りの幅に合わせて折り返し、はみ出しとみなされずに端の近くで細長い吹き出しになる
- 矢印(::before)は反転に付いてこないので、@supports の中では出さない
- 入れ物が空のときは :empty で display: none; にし、枠だけが残らないようにする
- document の click で、押された場所がボタンの中でも吹き出しの中でもなければ閉じる。keydown で Escape を受けて閉じる
- ツールチップ(overlay/tooltip)はマウスを乗せる・フォーカスするだけで出て、離れると消える。トグルチップは押して出し、Esc か外側を押すまで残る。ボタンそのものの名前の補足ならツールチップ、項目の意味の補足ならトグルチップ
- 吹き出しの中にリンクやボタンを入れない(Inclusive Components の方針)。読み上げには文として流れるだけで、中へ移れない。リンクや操作を載せたいならポップオーバー(overlay/popover)にする
- 入力を終えるのに必須の情報は隠さない。書かないと誤入力が起きる注意は、ボタンの中ではなく欄の下に常に出しておく
- 1つの画面に何個も置くと、どれを押せばよいか分からなくなる。2〜3文を超える説明はページ内の説明文に回す
## アクセシビリティの要件
- button 要素にし、aria-label で「配送料について」のように何の説明かが分かる名前を付ける。「i」「?」の記号は aria-hidden="true" にする
- ボタンのすぐ後ろに role="status" の入れ物を置き、押されたら一度空にしてから短い間(Inclusive Components の例では 100ms)をあけて文を入れる。空にせず同じ文を入れ直すと、2回目以降が読み上げられない環境がある
- Esc キーと、吹き出しの外を押したときに入れ物を空にして閉じる。フォーカスはボタンに残したまま動かさない
- ボタンは小さくなりがちなので、押せる領域を 24×24px 以上取る(WCAG 2.5.8 ターゲットのサイズ(最低限))
## 参考にする実装
この形を出発点にして、プロジェクトの命名規則・色・余白に合わせて調整してください。
```html
<div class="x-toggletip">
<p class="x-toggletip__row">
<span class="x-toggletip__k">商品小計</span>
<span class="x-toggletip__v">4,180円</span>
</p>
<p class="x-toggletip__row">
<span class="x-toggletip__k">配送料</span>
<span class="x-toggletip__w">
<button class="x-toggletip__b" type="button" aria-label="配送料について">
<i class="fa-solid fa-circle-info" aria-hidden="true"></i>
</button>
<!-- 読み上げに届けるための入れ物。ふだんは空で、押されたら JS が一度空にしてから文を入れる。
見本なので文が入った(開いた)状態にしてある -->
<span class="x-toggletip__live" role="status">
<span class="x-toggletip__t">5,000円以上のご注文で無料になります。沖縄・離島は別途1,100円かかります。</span>
</span>
</span>
<span class="x-toggletip__v">550円</span>
</p>
</div>
```
```css
/* 貼った先のリセットに頼らないよう、この部品の中だけ border-box にする */
.x-toggletip,
.x-toggletip *:not([class*="fa-"]),
.x-toggletip *:not([class*="fa-"])::before,
.x-toggletip *: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-toggletip {
width: 280px;
max-width: 100%;
padding: 12px 16px;
border: 1px solid #7f8a99;
border-radius: 8px;
background: #fff;
color: #1b2028;
font-size: 14px;
}
.x-toggletip__row {
display: flex;
align-items: center;
gap: 6px;
margin: 0;
padding: 8px 0;
}
/* 吹き出しは下の内容に重なって出る。見本では重ねる先が無いので、そのぶんの高さを取っておく */
.x-toggletip {
min-height: 170px;
}
.x-toggletip__row + .x-toggletip__row {
border-top: 1px solid #e3e6ea;
}
.x-toggletip__v {
margin-left: auto;
}
/* 吹き出しの位置の基準。ボタンのすぐ下に出す */
.x-toggletip__w {
position: relative;
display: inline-flex;
}
.x-toggletip__b {
display: grid;
place-items: center;
width: 24px;
height: 24px;
padding: 0;
border: 0;
border-radius: 50%;
background: none;
color: #1d4ed8;
font-size: 16px;
cursor: pointer;
}
.x-toggletip__b:hover {
background: #eef2fb;
}
.x-toggletip__b:focus-visible {
outline: 2px solid #1d4ed8;
outline-offset: 1px;
}
/* 入れ物が空のときは何も描かない(吹き出しの枠だけ残らないように) */
.x-toggletip__live:empty {
display: none;
}
.x-toggletip__t {
position: absolute;
top: calc(100% + 8px);
left: -12px;
z-index: 10;
width: 210px;
padding: 8px 10px;
border-radius: 6px;
background: #1b2028;
color: #fff;
font-size: 12px;
font-weight: 400;
line-height: 1.6;
}
.x-toggletip__t::before {
content: "";
position: absolute;
bottom: 100%;
left: 18px;
border: 6px solid transparent;
border-bottom-color: #1b2028;
}
```
## 出力の約束
- HTML と CSS を分けて出す。JavaScript が要るときは素の JavaScript で書き、UIフレームワークは使わない。
- 参考実装がアイコンに Font Awesome のクラスを使っている場合は、プロジェクトで使っているアイコンかインライン SVG に置き換えてよい。
- 上のアクセシビリティ要件を満たす。満たせない箇所があるときは、理由を添えて先に知らせる。
- 色・角丸・余白は既存のデザイントークンがあればそれを使う。無ければ CSS 変数として切り出す。
使いどころ
- 入力欄や料金の項目に、読まなくても進められるが知りたい人には要る補足(計算のしかた・条件)を添えたいとき
- タッチ端末でも読ませたい補足で、ホバーで出すツールチップでは届かないとき
注意点
- ツールチップ(overlay/tooltip)はマウスを乗せる・フォーカスするだけで出て、離れると消える。トグルチップは押して出し、Esc か外側を押すまで残る。ボタンそのものの名前の補足ならツールチップ、項目の意味の補足ならトグルチップ
- 吹き出しの中にリンクやボタンを入れない(Inclusive Components の方針)。読み上げには文として流れるだけで、中へ移れない。リンクや操作を載せたいならポップオーバー(overlay/popover)にする
- 入力を終えるのに必須の情報は隠さない。書かないと誤入力が起きる注意は、ボタンの中ではなく欄の下に常に出しておく
- 1つの画面に何個も置くと、どれを押せばよいか分からなくなる。2〜3文を超える説明はページ内の説明文に回す
アクセシビリティの要点
- button 要素にし、aria-label で「配送料について」のように何の説明かが分かる名前を付ける。「i」「?」の記号は aria-hidden="true" にする
- ボタンのすぐ後ろに role="status" の入れ物を置き、押されたら一度空にしてから短い間(Inclusive Components の例では 100ms)をあけて文を入れる。空にせず同じ文を入れ直すと、2回目以降が読み上げられない環境がある
- Esc キーと、吹き出しの外を押したときに入れ物を空にして閉じる。フォーカスはボタンに残したまま動かさない
- ボタンは小さくなりがちなので、押せる領域を 24×24px 以上取る(WCAG 2.5.8 ターゲットのサイズ(最低限))