キーボード操作とフォーカス管理
リンク・名前欄・無効なボタン・詳細ボタンを用意します。右の画面でTabとShift+Tabを押して移動を確認し、Enterで詳細を開きます。最後にEscapeで閉じ、元のボタンへ戻ったことを確かめます。キー操作ごとに、左の説明と右の記録が進みます。
説明
キーボード操作では、現在のフォーカス位置と、Tabを押した後の移動先を確認します。見た目がボタンでも、HTMLの要素や状態によって操作方法が変わります。ダイアログを開くとフォーカスを内部へ移し、閉じると元の操作位置へ戻します。
リンク・名前欄・無効なボタン・詳細ボタンを用意します。右の画面でTabとShift+Tabを押して移動を確認し、Enterで詳細を開きます。最後にEscapeで閉じ、元のボタンへ戻ったことを確かめます。キー操作ごとに、左の説明と右の記録が進みます。
1操作対象を用意する
リンクやボタンを並べたkeyboardHTMLから文書を作り、ヘルプへフォーカスを置きます。
(globalThis.doc=createDocument(keyboardHTML)用意したHTMLから文書を作る,doc.getElementById("open").onclick=()=>doc.getElementById("dialog").showModal()モーダルとして開く,doc.getElementById("close").onclick=()=>doc.getElementById("dialog").close()ダイアログを閉じる,watchKeys(),doc.getElementById("help").focus()最初の操作位置,{active:doc.activeElement.id,disabled:doc.getElementById("disabled").disabled,label:doc.getElementById("name").labels[0].textContent})ヘルプの周囲にフォーカスの枠が付きます。名前欄にはlabelが対応し、準備中のボタンはdisabledです。開く処理はネイティブのdialog.showModalを使い、ダイアログ内の閉じるボタンにautofocusを付けています。
2リンクから名前欄へ
ヘルプにあるフォーカスを、Tabで次へ移します。
Tab表示された対象でキーを押す名前欄へ移ります。readonlyは値の編集を止めますが、フォーカス移動の対象から外す指定ではありません。表示上の順序とDOMの順序を自然にそろえると、移動先を予測しやすくなります。
3無効なボタンを飛ばす
名前欄でTabを押します。
Tab表示された対象でキーを押す準備中のdisabledボタンを飛ばし、詳細へ移ります。disabledは操作不可の状態で、通常のTab順にも入りません。無効な理由を伝える必要がある場合は、見える説明も用意します。
4逆方向に移動する
詳細でShift+Tabを押します。
Shift+Tab表示された対象でキーを押す名前欄へ戻ります。逆方向でも準備中のボタンは対象外です。Tab順を調整するために正のtabindexを大量に付けると、画面やDOMの順序との不一致が起きやすくなります。
5詳細へ戻る
名前欄からTabで詳細へ進みます。
Tab表示された対象でキーを押す詳細にフォーカスが戻りました。次はこのボタンをキーボードで起動します。ネイティブのbuttonはEnterなどの標準操作を備えています。
6Enterでダイアログを開く
詳細にフォーカスがある状態でEnterを押します。
Enter表示された対象でキーを押すダイアログが開き、閉じるボタンへフォーカスが移ります。showModalは背後の文書を通常の操作対象から外し、ダイアログを前面へ置きます。単にdialogにopen属性を付ける表示とは異なります。
7ダイアログ内の次のボタン
閉じるボタンでTabを押します。
Tab表示された対象でキーを押すダイアログ内の戻るボタンへ移ります。開いている間は、背後の名前欄や保存ボタンへ操作が抜けないようにします。
8ダイアログ内を逆に移動する
戻るボタンでShift+Tabを押します。
Shift+Tab表示された対象でキーを押す閉じるボタンへ戻ります。操作対象が複数ある場合にも、フォーカス位置が見えることと、順方向・逆方向の両方で移動できることを確認します。
9Escapeで閉じて元へ戻る
Escapeを押してダイアログを閉じます。
Escape表示された対象でキーを押すダイアログが閉じ、起動元の詳細ボタンへ戻ります。閉じた後に操作位置を見失わないよう、開始時の位置と終了時の戻り先を対応させます。
10要素と状態を確認する
操作した要素の種類・tabIndex・disabledを一覧にします。
["help","name","disabled","open","last"].map(id=>{const e=doc.getElementById(id);return{id,element:e.localNameネイティブ要素の種類,tabIndex:e.tabIndexプロパティ値,disabled:Boolean(e.disabled)無効状態}})disabledボタンのtabIndexプロパティも0ですが、実際のTab移動では飛ばされました。tabIndexの数値だけで操作可能性の全条件は判断できません。要素の種類・無効状態・非表示・モーダルの状態を合わせ、実際のキー操作でも確認します。
まとめ
TabとShift+Tabの移動先を、実際のフォーカス表示で確認しました。
readonlyとdisabledは異なり、tabIndexの値だけでは実際の移動対象を決められません。
モーダルでは内部へ移動し、閉じた後に起動元へ戻れるようにします。
操作履歴と解説を振り返れます。
ブラウザ / 操作・表示
(globalThis.doc=createDocument(keyboardHTML),doc.getElementById("open").onclick=()=>doc.getElementById("dialog").showModal(),doc.getElementById("close").onclick=()=>doc.getElementById("dialog").close(),watchKeys(),doc.getElementById("help").focus(),{active:doc.activeElement.id,disabled:doc.getElementById("disabled").disabled,label:doc.getElementById("name").labels[0].textContent}){
"active": "help",
"disabled": true,
"label": "名前"
}<!doctype html><html lang="ja"><head><meta charset="utf-8"><meta http-equiv="Content-Security-Policy" content="default-src 'none'; style-src 'unsafe-inline'; img-src data:; base-uri 'none'; form-action 'none'"><style>:root{color-scheme:dark}body{margin:16px;background:#111;color:#eee;font:14px/1.6 system-ui}body::after{content:"";display:block;height:calc(100vh - 32px)}a{color:#80c4d6}table{border-collapse:collapse}th,td{border:1px solid #555;padding:4px 8px}img{max-width:100%}body{font:16px/1.6 system-ui;background:#111;color:#eee;margin:16px}a{color:#80c4d6}input,button{font:inherit;margin:6px;padding:4px;background:#222;color:#eee;border:1px solid #888}label{display:block}:focus,[data-focused]{outline:2px solid #80c4d6;outline-offset:3px}dialog{background:#222;color:#eee;border:1px solid #aaa;padding:12px;max-width:420px}dialog::backdrop{background:#0009}h2{margin:0}
:root{}body{}</style></head><body inert><a id="help" href="#helptext" data-focused="">ヘルプ</a><label for="name">名前</label><input id="name" value="あおい" readonly=""><button id="disabled" disabled="">準備中</button><button id="open">詳細</button><button id="last">保存</button><dialog id="dialog" aria-labelledby="dialog-title"><h2 id="dialog-title">申込内容</h2><p>名前:あおい</p><button id="close" autofocus="">閉じる</button><button id="second">戻る</button></dialog><p id="helptext">名前と申込内容を確認します。</p></body></html>Tab{
"active": "name",
"dialogOpen": false
}<!doctype html><html lang="ja"><head><meta charset="utf-8"><meta http-equiv="Content-Security-Policy" content="default-src 'none'; style-src 'unsafe-inline'; img-src data:; base-uri 'none'; form-action 'none'"><style>:root{color-scheme:dark}body{margin:16px;background:#111;color:#eee;font:14px/1.6 system-ui}body::after{content:"";display:block;height:calc(100vh - 32px)}a{color:#80c4d6}table{border-collapse:collapse}th,td{border:1px solid #555;padding:4px 8px}img{max-width:100%}body{font:16px/1.6 system-ui;background:#111;color:#eee;margin:16px}a{color:#80c4d6}input,button{font:inherit;margin:6px;padding:4px;background:#222;color:#eee;border:1px solid #888}label{display:block}:focus,[data-focused]{outline:2px solid #80c4d6;outline-offset:3px}dialog{background:#222;color:#eee;border:1px solid #aaa;padding:12px;max-width:420px}dialog::backdrop{background:#0009}h2{margin:0}
:root{}body{}</style></head><body inert><a id="help" href="#helptext">ヘルプ</a><label for="name">名前</label><input id="name" value="あおい" readonly="" data-focused=""><button id="disabled" disabled="">準備中</button><button id="open">詳細</button><button id="last">保存</button><dialog id="dialog" aria-labelledby="dialog-title"><h2 id="dialog-title">申込内容</h2><p>名前:あおい</p><button id="close" autofocus="">閉じる</button><button id="second">戻る</button></dialog><p id="helptext">名前と申込内容を確認します。</p></body></html><!doctype html><html lang="ja"><head><meta charset="utf-8"><meta http-equiv="Content-Security-Policy" content="default-src 'none'; style-src 'unsafe-inline'; img-src data:; base-uri 'none'; form-action 'none'"><style>:root{color-scheme:dark}body{margin:16px;background:#111;color:#eee;font:14px/1.6 system-ui}body::after{content:"";display:block;height:calc(100vh - 32px)}a{color:#80c4d6}table{border-collapse:collapse}th,td{border:1px solid #555;padding:4px 8px}img{max-width:100%}body{font:16px/1.6 system-ui;background:#111;color:#eee;margin:16px}a{color:#80c4d6}input,button{font:inherit;margin:6px;padding:4px;background:#222;color:#eee;border:1px solid #888}label{display:block}:focus,[data-focused]{outline:2px solid #80c4d6;outline-offset:3px}dialog{background:#222;color:#eee;border:1px solid #aaa;padding:12px;max-width:420px}dialog::backdrop{background:#0009}h2{margin:0}
:root{}body{}</style></head><body inert><a id="help" href="#helptext">ヘルプ</a><label for="name">名前</label><input id="name" value="あおい" readonly=""><button id="disabled" disabled="">準備中</button><button id="open">詳細</button><button id="last">保存</button><dialog id="dialog" aria-labelledby="dialog-title"><h2 id="dialog-title">申込内容</h2><p>名前:あおい</p><button id="close" autofocus="">閉じる</button><button id="second">戻る</button></dialog><p id="helptext">名前と申込内容を確認します。</p></body></html>Tab{
"active": "open",
"dialogOpen": false
}<!doctype html><html lang="ja"><head><meta charset="utf-8"><meta http-equiv="Content-Security-Policy" content="default-src 'none'; style-src 'unsafe-inline'; img-src data:; base-uri 'none'; form-action 'none'"><style>:root{color-scheme:dark}body{margin:16px;background:#111;color:#eee;font:14px/1.6 system-ui}body::after{content:"";display:block;height:calc(100vh - 32px)}a{color:#80c4d6}table{border-collapse:collapse}th,td{border:1px solid #555;padding:4px 8px}img{max-width:100%}body{font:16px/1.6 system-ui;background:#111;color:#eee;margin:16px}a{color:#80c4d6}input,button{font:inherit;margin:6px;padding:4px;background:#222;color:#eee;border:1px solid #888}label{display:block}:focus,[data-focused]{outline:2px solid #80c4d6;outline-offset:3px}dialog{background:#222;color:#eee;border:1px solid #aaa;padding:12px;max-width:420px}dialog::backdrop{background:#0009}h2{margin:0}
:root{}body{}</style></head><body inert><a id="help" href="#helptext">ヘルプ</a><label for="name">名前</label><input id="name" value="あおい" readonly=""><button id="disabled" disabled="">準備中</button><button id="open" data-focused="">詳細</button><button id="last">保存</button><dialog id="dialog" aria-labelledby="dialog-title"><h2 id="dialog-title">申込内容</h2><p>名前:あおい</p><button id="close" autofocus="">閉じる</button><button id="second">戻る</button></dialog><p id="helptext">名前と申込内容を確認します。</p></body></html><!doctype html><html lang="ja"><head><meta charset="utf-8"><meta http-equiv="Content-Security-Policy" content="default-src 'none'; style-src 'unsafe-inline'; img-src data:; base-uri 'none'; form-action 'none'"><style>:root{color-scheme:dark}body{margin:16px;background:#111;color:#eee;font:14px/1.6 system-ui}body::after{content:"";display:block;height:calc(100vh - 32px)}a{color:#80c4d6}table{border-collapse:collapse}th,td{border:1px solid #555;padding:4px 8px}img{max-width:100%}body{font:16px/1.6 system-ui;background:#111;color:#eee;margin:16px}a{color:#80c4d6}input,button{font:inherit;margin:6px;padding:4px;background:#222;color:#eee;border:1px solid #888}label{display:block}:focus,[data-focused]{outline:2px solid #80c4d6;outline-offset:3px}dialog{background:#222;color:#eee;border:1px solid #aaa;padding:12px;max-width:420px}dialog::backdrop{background:#0009}h2{margin:0}
:root{}body{}</style></head><body inert><a id="help" href="#helptext">ヘルプ</a><label for="name">名前</label><input id="name" value="あおい" readonly=""><button id="disabled" disabled="">準備中</button><button id="open">詳細</button><button id="last">保存</button><dialog id="dialog" aria-labelledby="dialog-title"><h2 id="dialog-title">申込内容</h2><p>名前:あおい</p><button id="close" autofocus="">閉じる</button><button id="second">戻る</button></dialog><p id="helptext">名前と申込内容を確認します。</p></body></html>Shift+Tab{
"active": "name",
"dialogOpen": false
}<!doctype html><html lang="ja"><head><meta charset="utf-8"><meta http-equiv="Content-Security-Policy" content="default-src 'none'; style-src 'unsafe-inline'; img-src data:; base-uri 'none'; form-action 'none'"><style>:root{color-scheme:dark}body{margin:16px;background:#111;color:#eee;font:14px/1.6 system-ui}body::after{content:"";display:block;height:calc(100vh - 32px)}a{color:#80c4d6}table{border-collapse:collapse}th,td{border:1px solid #555;padding:4px 8px}img{max-width:100%}body{font:16px/1.6 system-ui;background:#111;color:#eee;margin:16px}a{color:#80c4d6}input,button{font:inherit;margin:6px;padding:4px;background:#222;color:#eee;border:1px solid #888}label{display:block}:focus,[data-focused]{outline:2px solid #80c4d6;outline-offset:3px}dialog{background:#222;color:#eee;border:1px solid #aaa;padding:12px;max-width:420px}dialog::backdrop{background:#0009}h2{margin:0}
:root{}body{}</style></head><body inert><a id="help" href="#helptext">ヘルプ</a><label for="name">名前</label><input id="name" value="あおい" readonly="" data-focused=""><button id="disabled" disabled="">準備中</button><button id="open">詳細</button><button id="last">保存</button><dialog id="dialog" aria-labelledby="dialog-title"><h2 id="dialog-title">申込内容</h2><p>名前:あおい</p><button id="close" autofocus="">閉じる</button><button id="second">戻る</button></dialog><p id="helptext">名前と申込内容を確認します。</p></body></html><!doctype html><html lang="ja"><head><meta charset="utf-8"><meta http-equiv="Content-Security-Policy" content="default-src 'none'; style-src 'unsafe-inline'; img-src data:; base-uri 'none'; form-action 'none'"><style>:root{color-scheme:dark}body{margin:16px;background:#111;color:#eee;font:14px/1.6 system-ui}body::after{content:"";display:block;height:calc(100vh - 32px)}a{color:#80c4d6}table{border-collapse:collapse}th,td{border:1px solid #555;padding:4px 8px}img{max-width:100%}body{font:16px/1.6 system-ui;background:#111;color:#eee;margin:16px}a{color:#80c4d6}input,button{font:inherit;margin:6px;padding:4px;background:#222;color:#eee;border:1px solid #888}label{display:block}:focus,[data-focused]{outline:2px solid #80c4d6;outline-offset:3px}dialog{background:#222;color:#eee;border:1px solid #aaa;padding:12px;max-width:420px}dialog::backdrop{background:#0009}h2{margin:0}
:root{}body{}</style></head><body inert><a id="help" href="#helptext">ヘルプ</a><label for="name">名前</label><input id="name" value="あおい" readonly=""><button id="disabled" disabled="">準備中</button><button id="open">詳細</button><button id="last">保存</button><dialog id="dialog" aria-labelledby="dialog-title"><h2 id="dialog-title">申込内容</h2><p>名前:あおい</p><button id="close" autofocus="">閉じる</button><button id="second">戻る</button></dialog><p id="helptext">名前と申込内容を確認します。</p></body></html>Tab{
"active": "open",
"dialogOpen": false
}<!doctype html><html lang="ja"><head><meta charset="utf-8"><meta http-equiv="Content-Security-Policy" content="default-src 'none'; style-src 'unsafe-inline'; img-src data:; base-uri 'none'; form-action 'none'"><style>:root{color-scheme:dark}body{margin:16px;background:#111;color:#eee;font:14px/1.6 system-ui}body::after{content:"";display:block;height:calc(100vh - 32px)}a{color:#80c4d6}table{border-collapse:collapse}th,td{border:1px solid #555;padding:4px 8px}img{max-width:100%}body{font:16px/1.6 system-ui;background:#111;color:#eee;margin:16px}a{color:#80c4d6}input,button{font:inherit;margin:6px;padding:4px;background:#222;color:#eee;border:1px solid #888}label{display:block}:focus,[data-focused]{outline:2px solid #80c4d6;outline-offset:3px}dialog{background:#222;color:#eee;border:1px solid #aaa;padding:12px;max-width:420px}dialog::backdrop{background:#0009}h2{margin:0}
:root{}body{}</style></head><body inert><a id="help" href="#helptext">ヘルプ</a><label for="name">名前</label><input id="name" value="あおい" readonly=""><button id="disabled" disabled="">準備中</button><button id="open" data-focused="">詳細</button><button id="last">保存</button><dialog id="dialog" aria-labelledby="dialog-title"><h2 id="dialog-title">申込内容</h2><p>名前:あおい</p><button id="close" autofocus="">閉じる</button><button id="second">戻る</button></dialog><p id="helptext">名前と申込内容を確認します。</p></body></html><!doctype html><html lang="ja"><head><meta charset="utf-8"><meta http-equiv="Content-Security-Policy" content="default-src 'none'; style-src 'unsafe-inline'; img-src data:; base-uri 'none'; form-action 'none'"><style>:root{color-scheme:dark}body{margin:16px;background:#111;color:#eee;font:14px/1.6 system-ui}body::after{content:"";display:block;height:calc(100vh - 32px)}a{color:#80c4d6}table{border-collapse:collapse}th,td{border:1px solid #555;padding:4px 8px}img{max-width:100%}body{font:16px/1.6 system-ui;background:#111;color:#eee;margin:16px}a{color:#80c4d6}input,button{font:inherit;margin:6px;padding:4px;background:#222;color:#eee;border:1px solid #888}label{display:block}:focus,[data-focused]{outline:2px solid #80c4d6;outline-offset:3px}dialog{background:#222;color:#eee;border:1px solid #aaa;padding:12px;max-width:420px}dialog::backdrop{background:#0009}h2{margin:0}
:root{}body{}</style></head><body inert><a id="help" href="#helptext">ヘルプ</a><label for="name">名前</label><input id="name" value="あおい" readonly=""><button id="disabled" disabled="">準備中</button><button id="open">詳細</button><button id="last">保存</button><dialog id="dialog" aria-labelledby="dialog-title"><h2 id="dialog-title">申込内容</h2><p>名前:あおい</p><button id="close" autofocus="">閉じる</button><button id="second">戻る</button></dialog><p id="helptext">名前と申込内容を確認します。</p></body></html>Enter{
"active": "close",
"dialogOpen": true
}<!doctype html><html lang="ja"><head><meta charset="utf-8"><meta http-equiv="Content-Security-Policy" content="default-src 'none'; style-src 'unsafe-inline'; img-src data:; base-uri 'none'; form-action 'none'"><style>:root{color-scheme:dark}body{margin:16px;background:#111;color:#eee;font:14px/1.6 system-ui}body::after{content:"";display:block;height:calc(100vh - 32px)}a{color:#80c4d6}table{border-collapse:collapse}th,td{border:1px solid #555;padding:4px 8px}img{max-width:100%}body{font:16px/1.6 system-ui;background:#111;color:#eee;margin:16px}a{color:#80c4d6}input,button{font:inherit;margin:6px;padding:4px;background:#222;color:#eee;border:1px solid #888}label{display:block}:focus,[data-focused]{outline:2px solid #80c4d6;outline-offset:3px}dialog{background:#222;color:#eee;border:1px solid #aaa;padding:12px;max-width:420px}dialog::backdrop{background:#0009}h2{margin:0}
:root{}body{}</style></head><body inert><a id="help" href="#helptext">ヘルプ</a><label for="name">名前</label><input id="name" value="あおい" readonly=""><button id="disabled" disabled="">準備中</button><button id="open">詳細</button><button id="last">保存</button><dialog id="dialog" aria-labelledby="dialog-title" open=""><h2 id="dialog-title">申込内容</h2><p>名前:あおい</p><button id="close" autofocus="" data-focused="">閉じる</button><button id="second">戻る</button></dialog><p id="helptext">名前と申込内容を確認します。</p></body></html><!doctype html><html lang="ja"><head><meta charset="utf-8"><meta http-equiv="Content-Security-Policy" content="default-src 'none'; style-src 'unsafe-inline'; img-src data:; base-uri 'none'; form-action 'none'"><style>:root{color-scheme:dark}body{margin:16px;background:#111;color:#eee;font:14px/1.6 system-ui}body::after{content:"";display:block;height:calc(100vh - 32px)}a{color:#80c4d6}table{border-collapse:collapse}th,td{border:1px solid #555;padding:4px 8px}img{max-width:100%}body{font:16px/1.6 system-ui;background:#111;color:#eee;margin:16px}a{color:#80c4d6}input,button{font:inherit;margin:6px;padding:4px;background:#222;color:#eee;border:1px solid #888}label{display:block}:focus,[data-focused]{outline:2px solid #80c4d6;outline-offset:3px}dialog{background:#222;color:#eee;border:1px solid #aaa;padding:12px;max-width:420px}dialog::backdrop{background:#0009}h2{margin:0}
:root{}body{}</style></head><body inert><a id="help" href="#helptext">ヘルプ</a><label for="name">名前</label><input id="name" value="あおい" readonly=""><button id="disabled" disabled="">準備中</button><button id="open">詳細</button><button id="last">保存</button><dialog id="dialog" aria-labelledby="dialog-title"><h2 id="dialog-title">申込内容</h2><p>名前:あおい</p><button id="close" autofocus="">閉じる</button><button id="second">戻る</button></dialog><p id="helptext">名前と申込内容を確認します。</p></body></html>Tab{
"active": "second",
"dialogOpen": true
}<!doctype html><html lang="ja"><head><meta charset="utf-8"><meta http-equiv="Content-Security-Policy" content="default-src 'none'; style-src 'unsafe-inline'; img-src data:; base-uri 'none'; form-action 'none'"><style>:root{color-scheme:dark}body{margin:16px;background:#111;color:#eee;font:14px/1.6 system-ui}body::after{content:"";display:block;height:calc(100vh - 32px)}a{color:#80c4d6}table{border-collapse:collapse}th,td{border:1px solid #555;padding:4px 8px}img{max-width:100%}body{font:16px/1.6 system-ui;background:#111;color:#eee;margin:16px}a{color:#80c4d6}input,button{font:inherit;margin:6px;padding:4px;background:#222;color:#eee;border:1px solid #888}label{display:block}:focus,[data-focused]{outline:2px solid #80c4d6;outline-offset:3px}dialog{background:#222;color:#eee;border:1px solid #aaa;padding:12px;max-width:420px}dialog::backdrop{background:#0009}h2{margin:0}
:root{}body{}</style></head><body inert><a id="help" href="#helptext">ヘルプ</a><label for="name">名前</label><input id="name" value="あおい" readonly=""><button id="disabled" disabled="">準備中</button><button id="open">詳細</button><button id="last">保存</button><dialog id="dialog" aria-labelledby="dialog-title" open=""><h2 id="dialog-title">申込内容</h2><p>名前:あおい</p><button id="close" autofocus="">閉じる</button><button id="second" data-focused="">戻る</button></dialog><p id="helptext">名前と申込内容を確認します。</p></body></html><!doctype html><html lang="ja"><head><meta charset="utf-8"><meta http-equiv="Content-Security-Policy" content="default-src 'none'; style-src 'unsafe-inline'; img-src data:; base-uri 'none'; form-action 'none'"><style>:root{color-scheme:dark}body{margin:16px;background:#111;color:#eee;font:14px/1.6 system-ui}body::after{content:"";display:block;height:calc(100vh - 32px)}a{color:#80c4d6}table{border-collapse:collapse}th,td{border:1px solid #555;padding:4px 8px}img{max-width:100%}body{font:16px/1.6 system-ui;background:#111;color:#eee;margin:16px}a{color:#80c4d6}input,button{font:inherit;margin:6px;padding:4px;background:#222;color:#eee;border:1px solid #888}label{display:block}:focus,[data-focused]{outline:2px solid #80c4d6;outline-offset:3px}dialog{background:#222;color:#eee;border:1px solid #aaa;padding:12px;max-width:420px}dialog::backdrop{background:#0009}h2{margin:0}
:root{}body{}</style></head><body inert><a id="help" href="#helptext">ヘルプ</a><label for="name">名前</label><input id="name" value="あおい" readonly=""><button id="disabled" disabled="">準備中</button><button id="open">詳細</button><button id="last">保存</button><dialog id="dialog" aria-labelledby="dialog-title" open=""><h2 id="dialog-title">申込内容</h2><p>名前:あおい</p><button id="close" autofocus="">閉じる</button><button id="second">戻る</button></dialog><p id="helptext">名前と申込内容を確認します。</p></body></html>Shift+Tab{
"active": "close",
"dialogOpen": true
}<!doctype html><html lang="ja"><head><meta charset="utf-8"><meta http-equiv="Content-Security-Policy" content="default-src 'none'; style-src 'unsafe-inline'; img-src data:; base-uri 'none'; form-action 'none'"><style>:root{color-scheme:dark}body{margin:16px;background:#111;color:#eee;font:14px/1.6 system-ui}body::after{content:"";display:block;height:calc(100vh - 32px)}a{color:#80c4d6}table{border-collapse:collapse}th,td{border:1px solid #555;padding:4px 8px}img{max-width:100%}body{font:16px/1.6 system-ui;background:#111;color:#eee;margin:16px}a{color:#80c4d6}input,button{font:inherit;margin:6px;padding:4px;background:#222;color:#eee;border:1px solid #888}label{display:block}:focus,[data-focused]{outline:2px solid #80c4d6;outline-offset:3px}dialog{background:#222;color:#eee;border:1px solid #aaa;padding:12px;max-width:420px}dialog::backdrop{background:#0009}h2{margin:0}
:root{}body{}</style></head><body inert><a id="help" href="#helptext">ヘルプ</a><label for="name">名前</label><input id="name" value="あおい" readonly=""><button id="disabled" disabled="">準備中</button><button id="open">詳細</button><button id="last">保存</button><dialog id="dialog" aria-labelledby="dialog-title" open=""><h2 id="dialog-title">申込内容</h2><p>名前:あおい</p><button id="close" autofocus="" data-focused="">閉じる</button><button id="second">戻る</button></dialog><p id="helptext">名前と申込内容を確認します。</p></body></html><!doctype html><html lang="ja"><head><meta charset="utf-8"><meta http-equiv="Content-Security-Policy" content="default-src 'none'; style-src 'unsafe-inline'; img-src data:; base-uri 'none'; form-action 'none'"><style>:root{color-scheme:dark}body{margin:16px;background:#111;color:#eee;font:14px/1.6 system-ui}body::after{content:"";display:block;height:calc(100vh - 32px)}a{color:#80c4d6}table{border-collapse:collapse}th,td{border:1px solid #555;padding:4px 8px}img{max-width:100%}body{font:16px/1.6 system-ui;background:#111;color:#eee;margin:16px}a{color:#80c4d6}input,button{font:inherit;margin:6px;padding:4px;background:#222;color:#eee;border:1px solid #888}label{display:block}:focus,[data-focused]{outline:2px solid #80c4d6;outline-offset:3px}dialog{background:#222;color:#eee;border:1px solid #aaa;padding:12px;max-width:420px}dialog::backdrop{background:#0009}h2{margin:0}
:root{}body{}</style></head><body inert><a id="help" href="#helptext">ヘルプ</a><label for="name">名前</label><input id="name" value="あおい" readonly=""><button id="disabled" disabled="">準備中</button><button id="open">詳細</button><button id="last">保存</button><dialog id="dialog" aria-labelledby="dialog-title" open=""><h2 id="dialog-title">申込内容</h2><p>名前:あおい</p><button id="close" autofocus="">閉じる</button><button id="second">戻る</button></dialog><p id="helptext">名前と申込内容を確認します。</p></body></html>Escape{
"active": "open",
"dialogOpen": false
}<!doctype html><html lang="ja"><head><meta charset="utf-8"><meta http-equiv="Content-Security-Policy" content="default-src 'none'; style-src 'unsafe-inline'; img-src data:; base-uri 'none'; form-action 'none'"><style>:root{color-scheme:dark}body{margin:16px;background:#111;color:#eee;font:14px/1.6 system-ui}body::after{content:"";display:block;height:calc(100vh - 32px)}a{color:#80c4d6}table{border-collapse:collapse}th,td{border:1px solid #555;padding:4px 8px}img{max-width:100%}body{font:16px/1.6 system-ui;background:#111;color:#eee;margin:16px}a{color:#80c4d6}input,button{font:inherit;margin:6px;padding:4px;background:#222;color:#eee;border:1px solid #888}label{display:block}:focus,[data-focused]{outline:2px solid #80c4d6;outline-offset:3px}dialog{background:#222;color:#eee;border:1px solid #aaa;padding:12px;max-width:420px}dialog::backdrop{background:#0009}h2{margin:0}
:root{}body{}</style></head><body inert><a id="help" href="#helptext">ヘルプ</a><label for="name">名前</label><input id="name" value="あおい" readonly=""><button id="disabled" disabled="">準備中</button><button id="open" data-focused="">詳細</button><button id="last">保存</button><dialog id="dialog" aria-labelledby="dialog-title"><h2 id="dialog-title">申込内容</h2><p>名前:あおい</p><button id="close" autofocus="">閉じる</button><button id="second">戻る</button></dialog><p id="helptext">名前と申込内容を確認します。</p></body></html><!doctype html><html lang="ja"><head><meta charset="utf-8"><meta http-equiv="Content-Security-Policy" content="default-src 'none'; style-src 'unsafe-inline'; img-src data:; base-uri 'none'; form-action 'none'"><style>:root{color-scheme:dark}body{margin:16px;background:#111;color:#eee;font:14px/1.6 system-ui}body::after{content:"";display:block;height:calc(100vh - 32px)}a{color:#80c4d6}table{border-collapse:collapse}th,td{border:1px solid #555;padding:4px 8px}img{max-width:100%}body{font:16px/1.6 system-ui;background:#111;color:#eee;margin:16px}a{color:#80c4d6}input,button{font:inherit;margin:6px;padding:4px;background:#222;color:#eee;border:1px solid #888}label{display:block}:focus,[data-focused]{outline:2px solid #80c4d6;outline-offset:3px}dialog{background:#222;color:#eee;border:1px solid #aaa;padding:12px;max-width:420px}dialog::backdrop{background:#0009}h2{margin:0}
:root{}body{}</style></head><body inert><a id="help" href="#helptext">ヘルプ</a><label for="name">名前</label><input id="name" value="あおい" readonly=""><button id="disabled" disabled="">準備中</button><button id="open">詳細</button><button id="last">保存</button><dialog id="dialog" aria-labelledby="dialog-title" open=""><h2 id="dialog-title">申込内容</h2><p>名前:あおい</p><button id="close" autofocus="">閉じる</button><button id="second">戻る</button></dialog><p id="helptext">名前と申込内容を確認します。</p></body></html>["help","name","disabled","open","last"].map(id=>{const e=doc.getElementById(id);return{id,element:e.localName,tabIndex:e.tabIndex,disabled:Boolean(e.disabled)}})[
{
"id": "help",
"element": "a",
"tabIndex": 0,
"disabled": false
},
{
"id": "name",
"element": "input",
"tabIndex": 0,
"disabled": false
},
{
"id": "disabled",
"element": "button",
"tabIndex": 0,
"disabled": true
},
{
"id": "open",
"element": "button",
"tabIndex": 0,
"disabled": false
},
{
"id": "last",
"element": "button",
"tabIndex": 0,
"disabled": false
}
]<!doctype html><html lang="ja"><head><meta charset="utf-8"><meta http-equiv="Content-Security-Policy" content="default-src 'none'; style-src 'unsafe-inline'; img-src data:; base-uri 'none'; form-action 'none'"><style>:root{color-scheme:dark}body{margin:16px;background:#111;color:#eee;font:14px/1.6 system-ui}body::after{content:"";display:block;height:calc(100vh - 32px)}a{color:#80c4d6}table{border-collapse:collapse}th,td{border:1px solid #555;padding:4px 8px}img{max-width:100%}body{font:16px/1.6 system-ui;background:#111;color:#eee;margin:16px}a{color:#80c4d6}input,button{font:inherit;margin:6px;padding:4px;background:#222;color:#eee;border:1px solid #888}label{display:block}:focus,[data-focused]{outline:2px solid #80c4d6;outline-offset:3px}dialog{background:#222;color:#eee;border:1px solid #aaa;padding:12px;max-width:420px}dialog::backdrop{background:#0009}h2{margin:0}
:root{}body{}</style></head><body inert><a id="help" href="#helptext">ヘルプ</a><label for="name">名前</label><input id="name" value="あおい" readonly=""><button id="disabled" disabled="">準備中</button><button id="open">詳細</button><button id="last">保存</button><dialog id="dialog" aria-labelledby="dialog-title"><h2 id="dialog-title">申込内容</h2><p>名前:あおい</p><button id="close" autofocus="">閉じる</button><button id="second">戻る</button></dialog><p id="helptext">名前と申込内容を確認します。</p></body></html>演習完了