Upgrade to Pro — share decks privately, control downloads, hide ads and more …

たかがボタン、されどボタン ~button要素から深ぼるボタンUIの定義について~ / Bur...

たかがボタン、されどボタン ~button要素から深ぼるボタンUIの定義について~ / BuriKaigi 2026

BuriKaigi 2026での発表内容(Webページ版

Avatar for Okuto Oyama

Okuto Oyama

January 10, 2026
Tweet

More Decks by Okuto Oyama

Other Decks in Technology

Transcript

  1. <form> <label><input type="text" name="zipCode">郵便番号</label> <button onclick="searchAddress()">住所検索</button> <label><input type="text" name="prefecture" autocomplete="address-level1">都道府県</label>

    <label><input type="text" name="city" autocomplete="address-level2">市区町村</label> <label><input type="text" name="address" autocomplete="address-line1">番地</label> <button>送信する</button> </form>
  2. <!-- 🔴 危険:フォーム内で意図せず送信が発生 --> <form> <button onclick="searchAddress()">住所検索</button> <button>送信する</button> </form> <!--

    🟢 用途に分けてtype指定 --> <form> <button type="button" onclick="searchAddress()">住所検索</button> <button type="submit">送信する</button> </form>
  3. Markuplint で独自設定 { "rules": { "required-attr": true, }, "nodeRules": [

    { "selector": "button", "rules": { "required-attr": { "value": [ { "name": "type", "value": ["button", "reset", "submit"] } ], } }
  4. type にまつわる余談 ①新しいtype 属性が提案されていた・いる type="share" (未採択) Web Share API のボタン

    type="selectlist" (未採択) <select> 要素内でリストボックスを開くためのボタンのため type="press" (提案中) 押下されている状態を表現
  5. type にまつわる余談 ②type 属性のデフォルト値を変えたい! Investigate making the invalid state of

    <button type> not submit · Issue #10462 · whatwg/html type が無効値のときにsubmit 扱いになる現在仕様を見直す提案が議論されている 互換性リスクや既存サイトへの影響が大きく、仕様変更には慎重な検討が必要とさ れている 代替案として、仕様の明確化やlint 的な警告など、破壊的変更を避ける方向性も示さ れている
  6. ARIA Authoring Practices Guide Button "A button is a widget

    that enables users to trigger an action or event, such as submitting a form, opening a dialog, canceling an action, or performing a delete operation." (ボタンは、フォーム送信、ダイアログを開く、アクションのキャンセル、削除操作など、アク ションやイベントをトリガーするウィジェットです) Link "A link widget provides an interactive reference to a resource. The target resource can be either external or local." (リンクは、リソースへの対話的な参照を提供します。対象リソースは外部でもローカルでも構 いません)
  7. キーボード操作 Button Space : Activates the button. Enter : Activates

    the button. Link Enter : Executes the link and moves focus to the link target. Shift + F10 (Optional): Opens a context menu for the link.
  8. リンクそのものの処理を除外する処理 const link = document.getElementById('link'); link.addEventListener('keydown', (e) => { if

    (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); link.click(); } }); link.addEventListener('keyup', (e) => { if (e.key === ' ') { e.preventDefault(); } }); link.addEventListener('contextmenu', (e) => { e.preventDefault();
  9. ✨ ✨ ✨ ✨ ✨ ✨ ✨ ✨ ✨ ✨

    ✨ ✨ ✨ ✨ ✨ ✨ ✨ ✨ ✨ 👉 👈 ⚡ 今すぐ押して! ⚡
  10. 暗黙の役割 <button> … ボタン <a> … リンク <img> … 画像

    <table> … テーブル <div> … generic 自分自身で意味を持たない名前のない役割
  11. 4.1.2 名前 (name) ・役割 (role) ・値 (value) 達成基準 すべてのユーザインタフェース コンポーネント

    ( フォームを構成する要素、リンク、スクリプト が生成するコンポーネントなど) では、名前 (name) 及び役割 (role) は、プログラムによる解釈が 可能である。 役割を上書きすることで「ボタン」と読み上げられる しかし<button> 本来がもつキーボード操作は付与されていない <div role="button" onclick="openDialog()">ダイアログを開く</div>
  12. 2.1.1 キーボード ( レベル A) 達成基準 コンテンツのすべての機能は、個々のキーストロークに特定のタイミングを要することなく、キ ーボードインタフェースを通じて操作可能である。 他にも Enter

    や Space でアクションさせる挙動も必要 Enter はkeydown で発火し、押しっぱなしだと連続で発火する Space はkeyup で発火するが、押しっぱなしのまま Tab でフォーカス移動すると発 火しない <div role="button" tabindex="0" onclick="openDialog()">ダイアログを開く</div>
  13. ガイドラインから学ぶ鉄則 Using ARIA If you can use a native HTML

    element or attribute with the semantics and behavior you require already built in, instead of re-purposing an element and adding an ARIA role, state or property to make it accessible, then do so. (必要なセマンティクスと振る舞いを持つネイティブHTML 要素が使えるなら、ARIA で無理やり 作るのではなく、それを使ってください) ARIA Authoring Practices Guide No ARIA is better than Bad ARIA (悪いARIA より、ARIA を使わない方がマシである)
  14. ざんねんなボタンUI 実装への対処方法 ① type 属性を忘れた<button> <button> の挙動を正しく理解し、適切なtype 属性を付与する ② <a>

    で実装されたボタンUI HTML 要素がもつ役割を正しく認識し、適切な場面で適切な要素を扱うようにする ③ <div> で実装されたボタンUI