ウェブ開発で AI が間違える上位 10 項目

公開日: 2026 年 11 月 11 日

今週、Modern Web Guidance のバージョン 1.0 をリリースしました。これは、ウェブ プラットフォームの専門知識、ベスト プラクティス、ブラウザの互換性データをコーディング エージェントに直接組み込む一連のスキルです。Modern Web Guidance の目標は、AI コーディング エージェントを使用するデベロッパーが最新のウェブ プラットフォームのパワーと機能を最大限に活用できるようにし、最終的にはユーザーのウェブ エクスペリエンスを向上させることです。

5 月に Modern Web Guidance の早期プレビュー版を初めてリリースして以来、コーディング エージェントはますます進化し、多くの素晴らしい新しいフロンティア モデルがリリースされています。よく寄せられる質問の一つに、「これらの新しいフロンティア モデルは、すでにウェブ開発のベスト プラクティスに沿っているのではないか?」というものがあります。

残念ながら、答えは「いいえ」です。テストの結果、答えが「いいえ」であることがわかっています。

Modern Web Guidance の各ガイドでは、ガイドのベスト プラクティスが適切に遵守されている場合に満たすべき一連の期待値を定義しています。次に、評価スイートは、Modern Web Guidance がインストールされたエージェント(ガイド付きエージェント)と、Modern Web Guidance がインストールされていないエージェント(ガイドなしエージェント)に同じプロンプトを送信して、これらのガイドをテストします。両方の実行の出力が、ガイドで定義されている期待値と照合されます。

ガイド付きとガイドなしの合格率を比較すると、AI モデル(最新のフロンティア モデルであっても)は、最新のウェブ開発のベスト プラクティスを独自に確実に遵守しているわけではないことがわかります。

平均すると、ガイドなしのコーディング エージェントは、評価スイートのチェックの約 50% しか合格しません。これに対し、Modern Web Guidance を使用した場合は約 90% が合格します。

最先端のコーディング エージェントにおける平均評価チェック合格率を比較した横棒グラフ(2026 年 11 月 9 日時点)。Modern Web Guidance なしでは 52%、Modern Web Guidance ありでは 91% となっています。

評価ダッシュボードでは、各ガイドで実行される特定のチェックの完全なリストと、各モデルのスコアを確認できます。

この投稿では、ウェブ デベロッパーが日常業務で遭遇する可能性が高い、アクセシビリティ、ユーザー エクスペリエンス、パフォーマンス、セキュリティなどの主要な分野で、AI モデルが常に間違っていることが確認されている 10 の最も問題のある領域について、概要を説明します。

1. ユーザー補助: キーボード フォーカスと inert の管理

キーボードやスクリーン リーダーで操作するユーザーにとって、インタラクティブな UI を使用可能にするのは、予測可能なフォーカス順序です。これがないと、フォーカスが非表示のバックグラウンド コンテンツに移動したり、数十個の余分なタブストップでスタックしたりする可能性があります。

フォーカスと inert の管理は、評価におけるアクセシビリティの最大のギャップの一つであり、Modern Web Guidance で最も改善される領域の一つです。よくある間違いは次のとおりです。

  • 新しく開いたビューにフォーカスを移動せず、戻る際にトリガー要素にフォーカスを戻すのを忘れる。
  • モーダル <dialog> を使用したり、背景コンテンツを inert とマークしたりする代わりに、カスタム モーダルで手動の JavaScript タブトラップと aria-modal="true" に依存している。
  • ロービング tabindex で単一のタブストップを使用する代わりに、ツールバーまたは方向グリッド内のすべてのアイテムを個別のタブストップとして公開する。
  • 隣接する背景とのコントラスト比が 3:1 に満たないカスタム :focus-visible アウトラインを作成する。

2. ユーザー補助: モーションを抑制するサポート

予期しないページの動きや大規模なアニメーションは、気が散るだけでなく、前庭障害や乗り物酔いしやすいユーザーにとっては、めまい、吐き気、頭痛を引き起こす可能性があります。

AI モデルは通常、標準の CSS 遷移やキーフレーム アニメーションを追加する際に prefers-reduced-motion を確認することを忘れません。しかし、スムーズ スクロール、ビュー遷移、スクロール駆動型アニメーションなどの新しい機能を使用する場合、モーションの軽減を忘れたり、実装時にミスをしたりすることがよくあります。

  • ルート要素に scroll-behavior:smooth をグローバルかつ無条件に設定する。
  • スクロールドリブン CSS アニメーションを使用しているが、モーション軽減のチェックがない。
  • スクロール中のモーションを減らすために、カルーセル アイテムの transition 期間を削除したが、変換プロパティの削除も忘れたため、スクロール中にアイテムのサイズが急に変わる。
  • モーションの軽減が有効になっている場合に、*、*::before、*::after に 0.01ms の期間リセットを全面的に適用し、重要なモーション以外の遷移(UI 状態の変化を伝えるために必要)もすべて消去します。
  • ドキュメント間のビュー遷移を無条件に有効にし、モーションの軽減が有効になっている場合は ::view-transition-* アニメーションをオーバーライドします。モーションの軽減チェックの背後で @view-transition ルールをゲートするだけではありません。

3. ユーザー補助: フォーム検証、形式のヒント、自動入力の状態

フォームは、ウェブ上のクリティカル ユーザー ジャーニーのほとんどで重要な役割を果たします。購入手続きフォームのちょっとした不具合が、ビジネスの収益に大きな影響を与えることがあります。

フォームを作成する際、AI モデルは基本的な部分の多くを正しく処理します。しかし、検証エラー、プレースホルダと形式ヒントの適切な配置、パスワード マネージャーや自動入力機能との正しい統合など、小さいながらも重要な詳細部分で失敗することがよくあります。

  • カスタム JavaScript blur 検証を使用して CSS :user-invalid を再実装する。この場合、ユーザーがタブで移動すると、未操作の required フィールドにすぐにフラグが付けられることがよくあります。
  • aria-invalid が同期されず、目に見えるエラーが発生する。blur で aria-invalid="true" を早めに設定するか、JavaScript で aria-invalid を同期せずに CSS で :user-invalid のスタイルを設定する。
  • aria-describedby にリンクされた永続的なヒントをレンダリングする代わりに、消える placeholder テキストに依存して、必要な形式(カードの有効期限入力の MM/YY など)を表示する。
  • 形式のヒントとパスワード ルールを <input> の上ではなく下に配置すると、ユーザーがそれらを読む必要があるときに、モバイル キーボードや自動入力ポップオーバーによって隠れてしまう可能性があります。
  • :autofill 入力をハイライト表示する際に、枠線の色のみを変更し、レイアウトを変更しない色以外のキュー(インセット box-shadow など)と色を組み合わせていない。

4. ユーザー エクスペリエンス: スワイプとタップの操作

エージェントは、命令型 JavaScript を使用してタッチ操作を実装し、独自のカスタム物理ロジックを作成することに優れています。これらの実装は機能しますが、JavaScript を利用したタッチ操作は、ユーザーがネイティブ アプリに期待するほどスムーズに感じられることはほとんどありません。

これらのインタラクションの多くは、CSS とネイティブ スクロール API を使用して実装できます。これにより、ブラウザはメインスレッド外でジェスチャー物理を実行できます。しかし、Google の評価では、AI モデルがこれらの特徴を見落とすことがよくあります。

  • CSS スクロール スナップを使用する代わりに、pointermove または touchmove リスナーを使用して、スワイプして閉じる、またはスワイプして表示するジェスチャーを実装する。
  • タブスワイプ インターフェースで overscroll-behavior-x:none を省略すると、オーバースワイプ中にブラウザの戻る / 進むナビゲーションが誤ってトリガーされる可能性があります。
  • スクロール駆動型アニメーションを使用する代わりに、JavaScript コールバックのメインスレッドでスワイプの進行状況効果を駆動する。
  • スクロールベースのスワイプ操作パネルでキーボード フォーカスが適切にサポートされていない。

5. ユーザー エクスペリエンス: ダイアログ、ポップオーバー、最上位レイヤの遷移

Google の評価では、モーダル ダイアログやポップオーバーのスクロールのアニメーション、閉じ、包含を行う際に、モデルが命令型 JavaScript の回避策にフォールバックすることがよくあります。

最上位レイヤのオーバーレイ用に構築された最新の HTML 機能や CSS 機能に依存する代わりに、エージェントはエントリと終了のステートマシン、履歴フック、ボディ スクロール ロックを手動で作成することがよくあります。これらはメンテナンスが難しく、微妙な UI バグが発生しやすくなります。

これらのインタラクションを適切に処理することで、不安定なエクスペリエンスを、ユーザーが信頼できる洗練されたエクスペリエンスに変えることができます。よくある間違いは次のとおりです。

  • popover を使用する代わりに、ライトディスミスのために手動のクリックアウトサイド ハンドラを使用してカスタム position:fixed オーバーレイを構築する。
  • @starting-style と transition-behavior を使用して純粋な CSS で行うのではなく、CSS 遷移クラスを切り替え、requestAnimationFrame() リスナーと transitionend リスナー(setTimeout() フォールバックを使用)と連携して、エントリ アニメーションと終了アニメーションを作成する。
  • <dialog> 要素を使用してオーバースクロールを制御する代わりに、<html> に overflow:hidden を設定して、開いているモーダルの背後でページ スクロールをロックする。
  • モーダル <dialog> 要素のネイティブの戻るボタンによる閉じる機能を使用するのではなく、popstate リスナーを追加して Android の戻るジェスチャーを検出し、開いているモーダルを閉じる。

6. ユーザー エクスペリエンス: ダークモードとテーマ適応型コントロール

ユーザーは目の疲れや眩しさを軽減するためにダークモードを有効にしているため、ページ読み込み時の明るい白いフラッシュ、テーマが適用されていないフォーム コントロール、OS の設定と同期していないトグルは、すぐにエクスペリエンスを損ないます。

ダークモードの切り替えは一見簡単そうに見えますが、評価におけるガイドなしのモデルは、テーマの切り替えやネイティブ フォーム コントロールを正しく行うために必要なプラットフォームの重要な詳細を常に把握できていません。

  • <head> に <meta name="color-scheme" content="light dark"> がないため、ダークモードのユーザーに、外部スタイルシートの読み込み中に白いキャンバスが点滅して表示されます。
  • color-scheme を設定せずに、カスタムカラーでダークモードまたはダークサーフェス コンポーネントのスタイルを設定すると、ネイティブのスクロールバーとフォーム コントロールがライトモードのままになります。
  • アクティブな color-scheme に自動的に従うテーマ適応型のカラー トークンを定義する際に、CSS の light-dark() 関数を見落としている。
  • localStorage で明示的なオーバーライドを設定するバイナリのライトモードまたはダークモードの切り替えのみを提供し、OS のデフォルトに戻すオプションを提供しない。
  • storage イベント リスナーの追加を忘れると、ユーザーがテーマを変更したときに、開いている他のタブが同期されなくなります。

7. パフォーマンス: ランタイムの応答性と滑らかさ

ユーザーは、ウェブページの読み込みが完了した後にほとんどの時間を費やすため、インタラクションが遅く、遷移がぎこちないと、最初の読み込みが遅い場合と同じようにユーザー エクスペリエンスが損なわれる可能性があります。

評価では、モデルは一般的に、Lighthouse などのツールで長年推奨されてきた従来の読み込み時間のベスト プラクティスに従っており、通常は明らかに重いループをウェブワーカーにオフロードすることを認識しています。一貫して苦労しているのは、INP の最適化に不可欠なメインスレッドの応答性です。レイアウト作業の分離、優先度によるタスクのスケジューリング、メインスレッド外でレンダリング作業を行う新しい HTML と CSS の機能の活用などです。

たとえば、エージェントは次のようなことをよく行います。

  • scheduler.postTask() でユーザーに表示されるタスクを優先したり、ブラウザがサポートしている場合に scheduler.yield() でタスクの継続を利用したりする代わりに、バックグラウンドまたは優先度の低い作業用にカスタム setTimeout() キューをローリングする。
  • content-visibility:auto と contain-intrinsic-size を適用せずに複雑なレイアウト(高密度のデータグリッドなど)を構築している。つまり、ユーザー操作後の更新によってページ全体のリフローがトリガーされる。
  • content-visibility:hidden(inert とペア)を使用する代わりに、display:none を使用してアクティブでない SPA ビューを非表示にする(または破棄する)。前者はキャッシュに保存されたレンダリング状態を破棄するため、切り替え時に完全なレイアウトとペイントがトリガーされます。
  • content-visibility:auto と contentvisibilityautostatechange イベントをペアリングするのではなく、Intersection Observer コールバックを使用して画面外の <canvas> アニメーションとバックグラウンド ループを一時停止し、要素がスクロールして表示される前にブラウザの事前レンダリング マージンを逃している。
  • CSS スクロール状態クエリ(Intersection Observer のフォールバック付き)を使用するのではなく、継続的なレイアウト計算を強制する scroll イベント リスナーを使用して、スクロール アフォーダンス UI ヒントを構築している。

8. パフォーマンス: レイアウト シフトと視覚的なちらつき

予期しないレイアウト シフトは、読者の集中を妨げ、ユーザーが予期しないボタンをクリックする原因となることがあります。場合によっては、取り返しのつかない結果を招くこともあります。

モデルは、レイアウト シフトを防ぐために、標準の <img> 要素に width 属性と height 属性を確実に追加しますが、レイアウト シフトの他の一般的な原因や、<video> 要素、ウェブフォントのスワップ、モバイル ブラウザのツールバー、クライアントサイドのテストによるプリペイント フラッシュを見落とすことがよくあります。これらはすべて CLS に影響する可能性があります。

  • <video> 要素で明示的な width 属性と height 属性を省略する(読み込まれていないプレーヤーはデフォルトで 300×150 になり、メタデータが読み込まれるとレイアウトがシフトする)、またはメディア要素に aspect-ratio と object-fit を直接設定する代わりにメディア ラッパー要素のスタイルを設定する。
  • font-size-adjust を使用せずにウェブフォントをシステム フォールバック フォントと組み合わせているため、ウェブフォントがスワップされると、段落と見出しが目に見えてリフローされます。
  • 動的または小さなビューポート単位(dvh、svh)ではなく、静的な vh 単位を使用してヒーロー セクションと全画面レイアウトのサイズを設定すると、モバイル ブラウザのツールバーが展開および縮小する際にコンテンツがジャンプします。
  • クライアントサイドの A/B テストで、従来の opacity:0 または visibility:hidden アンチフリッカー スニペットと数秒のタイムアウトを使用してコンテンツを非表示にしている(LCP が遅延し、非表示の要素がクリック可能なままになる)。代わりに、利用可能な場合は blocking="render" を含むスクリプトを使用してください。
  • rel="expect" と blocking="render" で最初のレンダリングを保持するのではなく、重要なスクロールせずに見える範囲のマークアップが解析される前にドキュメント間のビュー遷移をトリガーすると、遷移の途中で解析が完了していない要素がポップアップします。

9. セキュリティ: DOM XSS 防御と HTML サニタイズ

クロスサイト スクリプティング(XSS)の欠陥が 1 つあるだけで、攻撃者はユーザーのブラウザで任意のコードを実行し、セッション データを盗んだり、ユーザーの代わりに操作を行ったりすることができます。そのため、安全な HTML サニタイズ、Trusted Types、厳格な CSP など、ブラウザで適用される防御策が非常に重要です。

モデルがこれらのセキュリティ上の懸念にプロアクティブに対処することはほとんどありません。たとえば、評価スイート全体のすべてのタスクにおいて、モデルは明示的なプロンプトなしにコンテンツ セキュリティ ポリシー(CSP)やクロスオリジン分離ヘッダーを追加することはありませんでした。

プロンプトでセキュリティを直接リクエストした場合でも、ガイドなしのモデルはセキュリティ チェックの半分以上で失敗し、脆弱なカスタム フォールバックや不完全なポリシーに到達します。これは、DOM XSS に対する防御で明確に示されています。

  • ネイティブ サニタイズが利用できない場合に、DOMPurify などの検証済みライブラリを使用する代わりに、setHTML() フォールバックとして、または Trusted Types ポリシー内で、手動で作成した DOMParser 許可リスト サニタイザーを作成する。
  • ネイティブの setHTML() がサポートされている場合はそれを使用し、DOMPurify は代替としてのみ遅延読み込みするのではなく、ページ読み込みのたびに DOMPurify を積極的にバンドルする。
  • シンクの適用を弱める、寛容な (input) => input パススルー Trusted Types ポリシーを登録しています。
  • 静的ページで Trusted Types をホスト許可リスト script-src 'self' CSP と組み合わせる。SHA-256 ハッシュでインライン スクリプトをロックダウンする代わりに、この方法を使用します。
  • ノンスベースの script-src コンテンツ セキュリティ ポリシーを構成する際に、'strict-dynamic' と 'report-sample' を省略している。

10. セキュリティ: パスキーによるログイン、再認証、認証情報のライフサイクル

パスキーは、ユーザーのセキュリティを強化し、企業のログイン コンバージョンを向上させますが、実装は(エージェントの支援があっても)困難です。

WebAuthn には、シリアル化、機能検出、シグナリングに固有の API があり、ガイドなしのモデルでは、評価でほぼ完全に失敗します。AI モデルにパスキーによるログイン、管理、ステップアップ再認証を追加するよう依頼すると、手動のバイト エンコード ヘルパーが作成されたり、管理 UI での機能チェックがスキップされたり、認証情報がパスワード マネージャーと同期されなくなったりすることがよくあります。

  • parseCreationOptionsFromJSON()、parseRequestOptionsFromJSON()、credential.toJSON() などの組み込みのシリアル化メソッドに依存するのではなく、atob() と btoa() の Base64URL 変換ヘルパーを手動で作成する(プライマリ パスとして、または冗長なフォールバック ボイラープレートとして)。
  • サーバーが不明な認証情報 ID を報告したときに、ログイン中に PublicKeyCredential.signalUnknownCredential() を省略し、削除または取り消されたパスキーをユーザーのパスワード マネージャーに残す。
  • パスキーの作成と管理の UI をレンダリングする前に PublicKeyCredential.getClientCapabilities() をスキップする。
  • ステップアップ パスキー再認証リクエストの開始時に AbortController と AbortSignal を省略する。
  • 簡素化されたログイン メッセージに uiMode:"immediate" ではなくオリジン トライアルの mediation:"immediate" オプションを渡す。

これらのギャップを埋める

この 10 の領域は、網羅的なリストとはほど遠いものであり、特定の知識ギャップは時間の経過とともに変化すると予想されます。モデルは追いつき、ウェブ プラットフォームは進化し続けるでしょう。

Modern Web Guidance は、これらのギャップをすべて解消し、プラットフォームとともに進化し続けます。

Modern Web Guidance を開始するには、次のコマンドを実行するか、エージェントのプラグイン マーケットプレイスで検索します。

npx modern-web-guidance@latest install

モデルが他のウェブ開発タスクを間違えたことはありますか?ぜひお聞かせください。Modern Web Guidance の GitHub リポジトリで問題を報告するか、プロジェクトに貢献して、他のデベロッパーのためにギャップを埋めるのを手伝ってください。