こんにちは!フロントエンドの現場で日々コードと格闘しているエンジニアです。
Webサイトを作っていると、「リストの中に数千件のデータを表示したい!」という場面に出くわすことがありますよね。例えば、膨大な商品リストや、過去のメッセージ履歴などです。
「よし、HTMLの `
- ` と `
- ` を使って全部書き出そう!」……そう思って実装した瞬間、ブラウザが重くて固まってしまった経験はありませんか?実はそれ、DOM(ドム)の作りすぎが原因かもしれません。
今日は、そんな「大規模リストのパフォーマンス問題」を解決する魔法のような手法、「仮想スクロール(Windowing)」について、専門用語を抜きにして分かりやすく解説していきますね。
—
なぜ数千件のリストは「重い」のか?
まず、なぜブラウザが悲鳴を上げるのか、イメージしてみましょう。
想像してみてください。あなたは今、1,000ページある分厚い辞書を、机の上に「全ページ開いて」広げようとしています。机(ブラウザのメモリ)はすぐに溢れかえり、あなたは身動きが取れなくなりますよね。これが今のあなたのブラウザの状態です。
ブラウザにとって、HTMLの `
- ` タグを1つ作るというのは、小さな「家」を建てるようなものです。1,000個の家を一度に建てれば、当然、建築コスト(計算量)がかかり、表示が遅くなってしまいます。
仮想スクロール:賢い「窓」の考え方
そこで登場するのが「仮想スクロール」という考え方です。
さっきの辞書の例で言えば、全部広げるのではなく、「今見えている範囲のページだけ」を机に置き、スクロールに合わせてページを入れ替えるんです。これなら、常に机の上には数枚の紙しかないため、ブラウザは驚くほど軽快に動けます。
この「今見えている窓(ウィンドウ)の部分だけを描画する」という手法を、エンジニアの世界では「Windowing(ウィンドウイング)」と呼んだりします。
—
実際にどうやって実装するの?
難しいライブラリを使う前に、まずは「考え方」をコードで見てみましょう。
1. HTML:器を用意する
リスト全体ではなく、「表示される窓」の大きさを決める親要素を用意します。
2. JavaScript:スクロールを監視する
「今、どこを見ているか?」を計算して、中身の `
- ` を入れ替えます。
const container = document.getElementById(‘scroll-container’);
const list = document.getElementById(‘list-content’);// 全データの数(仮に1万件!)
const totalItems = 10000;
const itemHeight = 50; // 1アイテムの高さ// 窓に見える件数だけ計算して表示する関数
function render() {
const scrollTop = container.scrollTop;
const startIndex = Math.floor(scrollTop / itemHeight);
const endIndex = startIndex + 10; // 窓に表示する数(少し多めに!)let html = ”;
for (let i = startIndex; i < endIndex; i++) { html += ` - アイテム番号 ${i}
- ` を一度に管理する必要がなくなり、常に10個程度の要素だけを扱うようになります。まるで魔法のようにサクサク動くはずです。
最後に:完璧を目指さなくていい
現場では、今回紹介したような自前実装に加えて、`React Window` や `TanStack Virtual` といった、この仕組みをより高度に、より安全に実装するための「便利な道具(ライブラリ)」がよく使われます。
でも、まずはこうして「DOMを減らすにはどうすればいいか?」という仕組みの裏側を理解しておくことが、将来的にあなたを助ける大きな武器になります。
「画面が重いな」と思ったら、それはブラウザからの助けを求めるサイン。そんな時は、ぜひこの「窓」の考え方を思い出してみてくださいね。
今日もお疲れ様でした!あなたのWeb制作ライフが、より軽快で楽しいものになりますように。
`;
}
// 今表示されている部分だけDOMを書き換える
list.innerHTML = html;
}
// スクロールするたびに「窓」の中身を更新!
container.addEventListener(‘scroll’, render);
// 最初の一回だけ実行
render();
—
挫折しないためのポイント
このコードを見ると、「えっ、難しそう…」と思うかもしれません。でも、大丈夫です!まずは以下の3つのステップで考えてみてください。
1. 「表示する領域」と「データ全体」を切り離す(箱は小さく、データは巨大に)。
2. スクロール位置から「今のインデックス(何番目か)」を計算する。
3. 必要な分だけ `innerHTML` で書き換える。
これだけで、ブラウザは1,000個の `

コメント