12k
All articles

テーブルは Div ではない: 真の表形式データのためのシンプルな API

HTML table DOM API のネイティブメソッドを使い、XSS リスクを回避しながらセマンティックでアクセシブルな表形式データを構築する方法を解説する。

OpenReplay Team
OpenReplay Team
テーブルは Div ではない: 真の表形式データのためのシンプルな API

ダッシュボードや管理ツールを構築する多くの JavaScript 開発者は、テーブルのレンダリングに苦労した経験があるでしょう。HTML 文字列を連結したり、innerHTML と格闘したり、同僚がネストした div と CSS Grid を使ってテーブルを再構築するのを見たことがあるかもしれません。しかし、Web の初期から目の前に隠れていた、よりシンプルな方法があります。それが HTML テーブル DOM API です。

HTMLTableElement インターフェースは、テーブル構造を段階的に作成、読み取り、変更するためのネイティブメソッドを提供します。文字列連結や完全な再レンダリングは不要です。この API は、テーブルを生成すべきマークアップとしてではなく、操作すべき構造化データとして扱います。

重要なポイント

  • HTMLTableElement インターフェースは、insertRow()insertCell()deleteRow() などのネイティブメソッドを提供し、文字列連結なしで直接テーブルを操作できます。
  • ライブな HTMLCollection オブジェクト(rowscells)は自動的に更新されるため、段階的な変更が容易です。
  • テーブル API を使用することで、innerHTML に内在する XSS 脆弱性を回避し、リアルタイム更新時のレイアウトスラッシングを軽減できます。
  • 適切な <thead><th><tbody> を持つセマンティックな <table> 要素は、div ベースのレイアウトでは実現できない組み込みのアクセシビリティを提供します。

忘れられた JavaScript テーブル API

HTML テーブル DOM API は、すべての <table> 要素に存在します。insertRow()insertCell()deleteRow()createTHead() などのメソッドに加え、テーブルの変更に応じて自動的に更新される rowscells などのライブコレクションが含まれています。

基本的なパターンは次のとおりです:

const table = document.createElement('table')
const row = table.insertRow()
const cell = row.insertCell()
cell.textContent = 'Hello'

テンプレートリテラルも innerHTML も不要です。目的に特化したメソッドによる直接的な DOM 操作だけです。

インデックスを使って任意のセルにアクセスできます:

console.log(table.rows[0].cells[0]) // <td>Hello</td>

rowscells プロパティは、ライブな HTMLCollection オブジェクトを返します。行を削除すると、table.rows.length が即座に更新されます。これにより段階的な更新が簡単になります。データが到着したら行を追加し、削除されたら行を削除する、テーブルの残りの部分には触れずに。

開発者が HTMLTableElement を忘れた理由

この API には癖があります。末尾に追加するための -1 インデックス規約は奇妙に感じられます。insertHeaderCell() メソッドは存在せず、createElement()<th> 要素を手動で作成して追加する必要があります。これらの粗削りな部分と、DOM 操作を完全に抽象化するフレームワークの台頭が相まって、この API は忘れ去られました。

しかし、制限は軽微です。ヘッダーセルの回避策は簡単です:

const thead = table.createTHead()
const headerRow = thead.insertRow()
const th = document.createElement('th')
th.textContent = 'Name'
headerRow.appendChild(th)

createTFoot()createCaption() も使用でき、複数のボディセクションには table.tBodies でアクセスできます。この API はテーブル構造全体をカバーしています。

セキュリティとパフォーマンスの利点

innerHTML でテーブルを構築すると、XSS 脆弱性を招きます。サニタイズされていないユーザーデータは、実行可能な HTML になります。テーブル API はこれを完全に回避します。textContentinsertCell() は HTML を解析しません。

パフォーマンスも重要です。API を使って単一のセルを変更しても、ブラウザがテーブル全体を再解析して再構築する必要はありません。リアルタイムで更新されるダッシュボードでは、この段階的なアプローチにより、不要な再解析とリフローを削減できます。

セマンティックテーブルと組み込みのアクセシビリティ

div ベースのテーブル再実装が間違っている点は、セマンティクスを捨ててしまうことです。適切な <thead><th><tbody> 要素を持つ本物の <table> は、スクリーンリーダーや支援技術が表形式データをナビゲートするために必要なすべてを提供します。アクセシブルなデータテーブルが本質的に無料で手に入るのです。

ヘッダーセルに scope="col" を追加し、<caption> 要素を追加すれば完璧です。ARIA grid ロールは不要です。それらはインタラクティブなウィジェットグリッド用であり、データテーブル用ではありません。セマンティックテーブルは、構造化情報を表示するための正しいプリミティブです。

ネイティブ API を使用すべき場合

HTML テーブル DOM API は、バニラ JavaScript のコンテキストで輝きます。内部ツール、軽量ダッシュボード、管理パネル、またはフレームワークのオーバーヘッドなしで直接制御したい場合などです。

React や Vue を使用している場合は、すでにレンダリングを処理する仮想 DOM を使用しています。TanStack Table v8 のようなライブラリは、フレームワークレンダリングとうまく組み合わせられるヘッドレステーブルロジックを提供します。しかし、バニラ JS やプログレッシブエンハンスメントのシナリオでは、ネイティブ API がよりクリーンな選択肢であり続けます。

まとめ

テーブルは、表形式データに対する正しいツールであることをやめたことはありません。変わったのは、それらを構築する方法です。HTMLTableElement インターフェースは、生の文字列操作と重い抽象化の間の中間的な道を提供します。ネイティブで、段階的で、安全です。

この API は存在します。すべてのブラウザで動作します。デフォルトでセマンティックでアクセシブルなマークアップを生成します。JavaScript で実際のデータを扱うフロントエンド開発者にとって、再発見する価値があります。

よくある質問

HTMLTableElement API とは何ですか?なぜ使用すべきですか?

HTMLTableElement API は、JavaScript を通じてテーブル要素を直接操作するためのネイティブブラウザインターフェースです。文字列連結なしでテーブルを構築するための insertRow や insertCell などのメソッドを提供します。XSS 脆弱性を回避し、完全な再レンダリングなしで段階的な更新をサポートし、自動的にセマンティックでアクセシブルなマークアップを生成するため、使用すべきです。

テーブル API を使用してヘッダーセルを追加するにはどうすればよいですか?

テーブル API には専用の insertHeaderCell メソッドがありません。代わりに、createTHead で thead セクションを作成し、行を挿入してから、document.createElement を使用して手動で th 要素を作成し、行に追加します。この回避策は簡単で、scope などのヘッダーセル属性を完全に制御できます。

フレームワークの代わりにネイティブテーブル API を使用すべきなのはいつですか?

バニラ JavaScript プロジェクト、内部ツール、軽量ダッシュボード、またはプログレッシブエンハンスメントのシナリオでは、ネイティブテーブル API を使用してください。React や Vue をすでに使用している場合、それらの仮想 DOM がレンダリングを効率的に処理します。ソートやフィルタリングなどの複雑なテーブル機能については、代わりに TanStack Table のようなヘッドレスライブラリを検討してください。

表形式データに対して、セマンティックテーブルが div ベースのレイアウトより優れているのはなぜですか?

適切な thead、th、tbody 要素を使用するセマンティックテーブルは、スクリーンリーダーが自動的に理解できる組み込みのアクセシビリティを提供します。div ベースのレイアウトは、この機能を再現するために広範な ARIA 属性を必要とし、多くの場合不十分です。セマンティックテーブルは構造化データのための正しい HTML プリミティブであり、アクセシブルにするための労力が少なくて済みます。

Open-source session replay

Complete picture for complete understanding

Capture every clue your frontend is leaving so you can instantly get to the root cause of any issue with OpenReplay — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data.

Star on GitHub12k

We use cookies to improve your experience. By using our site, you accept cookies.