JavaScriptのscroll
イベントは、スクロール操作が発生したときにトリガーされるイベントです。主にページや要素のスクロール位置を取得したり、スクロールに応じた動的な処理を実装する際に利用されます。今回は、scroll
イベントの基本的な使い方から、パフォーマンスを考慮した実装方法までをまとめていきたいと思います。
scroll
イベントは、以下の場合に発生します。
- ユーザーがスクロール操作を行ったとき。
- JavaScriptでプログラム的にスクロールが発生したとき。
window
オブジェクト- スクロール可能なHTML要素(例:
<div>
や<section>
)
注意点として、scroll
イベントはバブリング(親要素への伝播)しません。
次の例では、ページのスクロール位置を取得して表示します。
See the Pen scroll() by tones (@tonescodedesign) on CodePen.
JavaScript
const indicator = document.getElementById('scrollIndicator');
window.addEventListener('scroll', () => {
const scrollY = window.scrollY;
indicator.textContent = `スクロール位置: ${scrollY}px`;
});
HTML
<div class="indicator" id="scrollIndicator">スクロール位置: 0px</div>
CSS
body {
height: 2000px;
}
.indicator {
position: fixed;
top: 10px;
left: 10px;
background: rgba(0, 0, 0, 0.7);
color: white;
padding: 5px 10px;
border-radius: 5px;
}
このコードでは、window.scrollY
を使用してページの垂直方向のスクロール位置を取得しています。
スクロール位置に応じて、現在表示されているセクションをナビゲーションでハイライトさせる例です。
See the Pen scroll() by tones (@tonescodedesign) on CodePen.
JavaScript
const navLinks = document.querySelectorAll('nav a');
window.addEventListener('scroll', () => {
let currentSection = '';
document.querySelectorAll('section').forEach(section => {
const sectionTop = section.offsetTop;
const sectionHeight = section.clientHeight;
if (window.scrollY >= sectionTop - sectionHeight / 2) {
currentSection = section.getAttribute('id');
}
});
navLinks.forEach(link => {
link.classList.remove('active');
if (link.dataset.target === currentSection) {
link.classList.add('active');
}
});
});
HTML
<nav>
<a href="#section1" data-target="section1">セクション1</a>
<a href="#section2" data-target="section2">セクション2</a>
<a href="#section3" data-target="section3">セクション3</a>
</nav>
<section id="section1" class="section1">セクション1</section>
<section id="section2" class="section2">セクション2</section>
<section id="section3" class="section3">セクション3</section>
CSS
body {
margin: 0;
}
nav {
position: fixed;
top: 0;
width: 100%;
background: #333;
color: #fff;
padding: 10px;
}
nav a {
color: #fff;
margin: 0 10px;
text-decoration: none;
}
nav a.active {
text-decoration: underline;
}
section {
height: 100vh;
padding: 20px;
}
.section1 { background: lightcoral; }
.section2 { background: lightblue; }
.section3 { background: lightgreen; }
スクロールに応じて新しいコンテンツをロードする例です。
See the Pen Untitled by tones (@tonescodedesign) on CodePen.
JavaScript
const container = document.getElementById('container');
const loading = document.getElementById('loading');
let isLoading = false;
const loadMoreContent = () => {
if (isLoading) return;
isLoading = true;
loading.style.display = 'block';
// モックとして、2秒後に新しいコンテンツを追加
setTimeout(() => {
for (let i = 0; i < 5; i++) {
const newItem = document.createElement('div');
newItem.className = 'content';
newItem.textContent = `新しいアイテム ${container.children.length + 1}`;
container.appendChild(newItem);
}
loading.style.display = 'none';
isLoading = false;
}, 2000);
};
window.addEventListener('scroll', () => {
if (window.innerHeight + window.scrollY >= document.body.offsetHeight - 100) {
loadMoreContent();
}
});
HTML
<div id="container">
<div class="content">アイテム1</div>
<div class="content">アイテム2</div>
<div class="content">アイテム3</div>
</div>
<div id="loading">読み込み中...</div>
CSS
.content {
padding: 10px;
border-bottom: 1px solid #ddd;
}
#loading {
text-align: center;
padding: 20px;
}
- パフォーマンスへの配慮:
scroll
イベントも頻繁に発生するため、パフォーマンスに影響を与える可能性があります。デバウンスやスロットリングを活用して処理の頻度を制限することをおすすめします。 - CSSとの組み合わせ: 簡単な視覚効果であれば、CSSの
scroll-behavior
やposition: sticky
を使用することで、JavaScriptを使用せずに実現できる場合があります。 - イベントリスナーの解除: メモリリークを防ぐため、不要になったイベントリスナーは
removeEventListener
で解除しましょう。
scroll
イベントは、ページや要素のスクロール操作に反応して動的な処理を実現する便利なイベントです。ただし、頻発するためパフォーマンスに注意が必要です。デバウンスやスロットリングを取り入れることで、実用的で効率的なコードを書くようにしましょう。