SvelteKitでポップアップを開発しています。エラーが出たので解析してください。
Visible, non-interactive elements with a click event must be accompanied by a keyboard event handler. Consider whether an interactive element such as <button type="button"> or <a> might be more appropriate
https://svelte.dev/e/a11y_click_events_have_key_eventssvelte(a11y_click_events_have_key_events)
<div> with a click handler must have an ARIA role
Svelteのアクセシビリティ(a11y)警告についてですね。
エラーメッセージの内容から、以下の2つの問題が発生している可能性があります。
click
イベントを持つ非インタラクティブ要素にキーボードイベントがない警告:
Visible, non-interactive elements with a click event must be accompanied by a keyboard event handler.
(クリックイベントを持つ可視の非インタラクティブ要素には、キーボードイベントを追加する必要があります。)
原因:<div>
や <span>
のような非インタラクティブな要素に on:click
を設定すると、
キーボード操作(Enter
や Space
キー)では操作できません。
解決策:
<button>
や <a>
を使用するon:keydown
で Enter
や Space
を対応させる修正例:
<!-- ❌ NG: 非インタラクティブな要素に click イベントだけを設定 -->
<div on:click={handleClick}>Click me</div>
<!-- ✅ OK: button を使う -->
<button on:click={handleClick}>Click me</button>
<!-- ✅ OK: キーボードイベントを追加する -->
<div tabindex="0" role="button" on:click={handleClick} on:keydown={(e) => (e.key === "Enter" || e.key === " ") && handleClick()}>
Click me
</div>
<div>
で click
を使う場合は ARIA role が必要警告:
<div>
with a click handler must have an ARIA role.
(クリックハンドラー(クリックされたときの動き)を持つ<div>
は ARIA role を持つ必要があります。)
原因:<div on:click={handleClick}>
にはデフォルトのアクセシビリティ情報がないため、
スクリーンリーダーなどでボタンのように認識されません。
解決策:
<div>
に role="button"
を設定tabindex="0"
を追加してフォーカス可能にする修正例:
<!-- ❌ NG: role なしの <div> に click ハンドラーだけ設定 -->
<div on:click={handleClick}>Click me</div>
<!-- ✅ OK: role="button" を追加 -->
<div role="button" tabindex="0" on:click={handleClick} on:keydown={(e) => (e.key === "Enter" || e.key === " ") && handleClick()}>
Click me
</div>
<button>
を使う(デフォルトでアクセシビリティが考慮されている)<div>
を使うなら role="button"
や tabindex="0"
を追加on:keydown
)も設定し、Enter
や Space
をサポート❌ NG | ✅ OK |
---|---|
<div on:click={handleClick}>Click me</div> |
<button on:click={handleClick}>Click me</button> |
<div on:click={handleClick}>Click me</div> |
`<div role="button" tabindex="0" on:click={handleClick} on:keydown={(e) => (e.key === "Enter" |
Svelte で開発する際は、アクセシビリティを意識して要素を適切に選ぶのが大事ですね!
div要素やspanにクリックの指示をしていることが原因なのですね。本来の使い方と間違えているということですか。
その通りです!Svelte(というかHTML全体)のルールとして、<div>
や <span>
は 本来インタラクティブな要素ではない ため、click
を直接設定すると間違った使い方になってしまいます。
<div>
や <span>
は「グループ化」や「装飾」のための要素であり、ユーザーが操作することを前提としていないTab
キー でのフォーカスや Enter
/ Space
でのクリック)に対応していないそのため、もしクリック可能にしたい場合は 適切な要素 を使うか、アクセシビリティの設定を追加 する必要があります。
❌ 間違い | ✅ 正しい |
---|---|
<div on:click={handleClick}>Click me</div> |
<button on:click={handleClick}>Click me</button> |
<span on:click={handleClick}>Click me</span> |
<a href="#" on:click={handleClick}>Click me</a> |
<div>
を使いたい場合もしスタイルの都合などで <div>
を使いたい場合は、次のように アクセシビリティ対応 を追加します。
<div role="button" tabindex="0" on:click={handleClick}
on:keydown={(e) => (e.key === "Enter" || e.key === " ") && handleClick()}>
Click me
</div>
role="button"
→ スクリーンリーダーに「ボタンである」と認識させるtabindex="0"
→ キーボードで Tab
を押したときにフォーカスできるようにするon:keydown
→ Enter
や Space
キーでクリックできるようにする
<div>
や<span>
には基本的にclick
を設定しない!
ボタンなら<button>
、リンクなら<a>
を使うのがベスト!
どうしても<div>
を使うならアクセシビリティ対応を追加する!
Svelteでは、こうしたHTMLの基本ルールを守ることで、より良いコードが書けます! 🚀
<div>
要素や<span>
要素は、本来インタラクティブな要素として意図されていません。これらの要素にclick
イベントハンドラを設定すること自体は可能ですが、いくつかの問題を引き起こす可能性があります。
本来の使い方との違い:
<div>
や<span>
は、コンテンツのグループ化や装飾のために使用される汎用的な要素です。一方、ボタンやリンクは、特定のインタラクション (クリック、移動など) を示す意味を持つ要素です。<div>
や<span>
にclick
イベントを設定することは、これらの要素が本来持つ意味合いと矛盾します。<div>
や<span>
にclick
イベントを設定しても、スクリーンリーダーはそれがクリック可能な要素であることを認識できません。そのため、視覚障碍者などのユーザーは、その要素を操作できない可能性があります。<div>
や<span>
に設定されたclick
イベントは操作できません。SvelteKitが警告する理由:
SvelteKitは、開発者がウェブアクセシビリティを意識したコードを書くことを支援するために、このような警告を表示します。これは、より多くのユーザーがウェブサイトを利用できるようにするための重要な取り組みです。
推奨される解決策:
<button>
要素や<a>
要素 (リンクの場合) など、意味的に正しいインタラクティブ要素を使用することを推奨します。<div>
や<span>
を使用する必要がある場合は、role
属性で適切なARIAロール (例えば、role="button"
、role="link"
) を指定し、スクリーンリーダーに要素の意味を伝える必要があります。まとめ:
<div>
要素や<span>
要素にclick
イベントハンドラを設定することは、本来の使い方ではありません。ウェブアクセシビリティの観点からも、適切な要素を使用するか、ARIAロールを正しく指定することが重要です。
アクセシビリティをカタカナを使わずに簡単に説明してください。
アクセシビリティをカタカナを使わずに簡単に説明すると、
「どんな人でも、どんな道具を使っていても、無理なく使えるようにすること」 です!😊
人によって、コンピュータの使い方は違います。
たとえば…
✅ マウスを使わずにキーボードだけで操作する人
✅ 目が見えにくく、画面を読み上げる機能(音声)を使う人
✅ スマホの画面が小さく、ボタンを押しにくい人
こういう人たちも 「困らずに使える」ようにする工夫 が大切です。
1️⃣ キーボードでも操作できるようにする
→ クリックだけじゃなく、「Enterキー」や「スペースキー」でも動くようにする
<div role="button" tabindex="0" on:click={doSomething} on:keydown={(e) => (e.key === "Enter" || e.key === " ") && doSomething()}>
ここを押す
</div>
🔹 こうすると、キーボードでも操作できる!
2️⃣ 画面を読み上げる人のために、説明をつける
→ alt
をつけて、画像の意味を伝える
<img src="photo.jpg" alt="夕日の写真">
🔹 目が見えない人でも、画面読み上げソフトが「夕日の写真」と教えてくれる!
3️⃣ 小さいボタンを押しやすくする
→ 余白をつけて、スマホでも押しやすくする
<button class="p-4">押す</button>
🔹 スマホで小さすぎるボタンは、押しにくいからね!
📌 どんな人でも、どんな道具を使っていても、無理なく使えるようにすること!
📌 「マウスがなくてもOK」「画面を見なくてもOK」「スマホでも押しやすい」ようにする工夫!
小さな工夫で、たくさんの人が快適に使えるようになります!😊
インタラクティブとは簡単に何ですか。
「インタラクティブ(Interactive)」 とは、簡単に言うと 「ユーザーが操作できるもの」 という意味です。
インタラクティブな要素とは、クリック・タップ・キーボード操作などで ユーザーが関与できる要素 のことを指します。例えば:
✅ インタラクティブな要素(操作できる要素)
<button>
(ボタン → クリック可能)<a>
(リンク → クリックで移動)<input>
(入力欄 → 文字を入力できる)<select>
(ドロップダウン → 選択できる)<textarea>
(テキストエリア → 長文を入力できる)❌ 非インタラクティブな要素(操作できない要素)
<div>
(ブロックのグループ化)<span>
(テキストの装飾)<p>
(段落)<h1>
(見出し)<img>
(画像)Svelte(というかHTML全体)では、ユーザーが操作する要素には 適切なインタラクティブ要素を使う ことが推奨されています。
例えば、以下のコードは 間違った使い方 です:
<div on:click={handleClick}>Click me</div>
なぜなら、<div>
は本来インタラクティブな要素ではなく、キーボード操作も考慮されていないからです。
✅ 正しい書き方
<button on:click={handleClick}>Click me</button>
こうすると、キーボードやスクリーンリーダーも適切に動作します!
<button>
を使う<a>
を使う<div>
や <span>
を使いたい場合は、role
や tabindex
を追加するこれを意識すると、アクセシビリティ(a11y)にも対応できるので、使いやすいWebアプリが作れます!💡
functionを使ってscriptタグ内に Enterキーまたはスペースキーが押されたら closeModal を実行する関数を記載することにしました。 以下のコードはletで定義していないのに実行できました。event.keyはどこから出てきたのですか。
<script>
function handleKeydown(event) {
// Enterキーまたはスペースキーが押されたら closeModal を実行
if (event.key === "Enter" || event.key === " ") {
closeModal();
}
}
</script>
<div
class="fixed inset-0 bg-black/50 flex items-center justify-center"
on:click={closeModal}
role="button"
tabindex="0"
on:keydown={handleKeydown}
>
event.key
良い質問ですね! event.key
はどこから来るのか、分かりやすく説明します。
event
はどこから来るのか?event
は ブラウザが自動で提供するオブジェクト です。
これは、キーボードやマウスなどの イベント(on:keydown など)が発生したときに、自動的に関数の引数として渡される ものです。
つまり、以下のように handleKeydown(event)
の event
は、Svelte(というかJavaScript)が自動的に渡してくれます。
<script>
function handleKeydown(event) {
console.log(event); // ← ここで event の中身を確認できる
if (event.key === "Enter" || event.key === " ") {
closeModal();
}
}
</script>
<div
tabindex="0"
on:keydown={handleKeydown}
>
モーダル
</div>
このコードで Enterキーを押すと、console.log(event)
によって event
の中身が確認できます!
(ブラウザの開発者ツールのコンソールで表示されます)
event.key
は何?event
は 「キーボードイベント」の情報が入ったオブジェクト です。event.key
は 押されたキーの名前を取得 できます。例えば、次のコードを試すと、キーを押したときに event.key
の値が分かります。
<script>
function handleKeydown(event) {
console.log("押したキー:", event.key);
}
</script>
<input type="text" on:keydown={handleKeydown} placeholder="何かキーを押してみて!" />
このコードで A
を押すと、コンソールに 押したキー: a
と表示されます。
let event
を宣言しないのか?通常の変数(let name = "Svelte"
のようなもの)は 自分で作る必要があります が、event
は JavaScript が自動で渡してくれる ので let event
のように宣言する必要はありません。
関数の引数として event
を受け取るだけでOK!
function handleKeydown(event) {
console.log(event.key); // どのキーが押されたかを表示
}
これは、JavaScript のイベントハンドラの基本的な仕組みです。
✅ event
は、イベントが発生すると JavaScript が自動で渡してくれるオブジェクト
✅ event.key
で、どのキーが押されたかを取得できる
✅ let event
のように宣言しなくてもOK(ブラウザが自動で渡す)
JavaScript のイベントを理解する良いきっかけですね! 😃
SvelteKitのエラーの原因は、非インタラクティブな要素(<div>
や <span>
)に click
を設定したこと
<div>
や <span>
は本来クリック可能な要素ではないため、アクセシビリティ上の問題が発生。<button>
や <a>
)を使用するか、role="button"
や tabindex="0"
を追加し、キーボードイベント(on:keydown
)を設定する。「インタラクティブ」とは、ユーザーが操作できる要素のこと
<button>
や <a>
はインタラクティブ要素として設計されており、クリックやキーボード操作が可能。<div>
や <span>
はインタラクティブではなく、イベントを追加する場合は適切な設定が必要。キーボード操作(Enterキー・スペースキー)でポップアップを閉じる処理を関数にまとめる
handleKeydown(event)
関数を作成し、event.key
をチェックして closeModal()
を実行。event
はブラウザが自動で提供するオブジェクトであり、明示的に let event
と宣言する必要はない。SvelteKitのアクセシビリティエラーを防ぐためのベストプラクティス
<button>
を使用する。<div>
を使う場合は、role="button"
や tabindex="0"
を追加する。on:keydown
) にも対応し、スクリーンリーダーの互換性を確保する。この修正により、エラーが解消され、アクセシビリティにも対応したポップアップが実装できます! 🚀