JavaScript Intersection Observer Quiz
Answer 35 questions covering observers and targets, threshold/rootMargin tuning, lazy-loading patterns, visibility detection, cleanup best practices, entry properties, performance wins vs scroll events, and common use cases like infinite scroll, animations, and analytics.
Question 1
What roles do the observer and target elements play in Intersection Observer?
Question 2
Why is Intersection Observer preferred over manually listening to scroll events for element visibility?
Question 3
What prints?
const target = document.createElement('div')
const observer = new IntersectionObserver((entries) => {
entries.forEach((entry) => console.log(entry.isIntersecting))
})
observer.observe(target)
console.log(observer.root)
Question 4
What does the threshold option represent?
Question 5
What prints?
const observer = new IntersectionObserver(() => {}, {
rootMargin: '10px 20px',
threshold: [0, 1]
})
console.log(observer.rootMargin, observer.thresholds)
Question 6
How does rootMargin influence intersection detection?
Question 7
What prints?
const img = document.createElement('img')
img.dataset.src = 'photo.jpg'
const observer = new IntersectionObserver((entries, obs) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
entry.target.src = entry.target.dataset.src
obs.unobserve(entry.target)
console.log('loaded', entry.target.src)
}
})
})
observer.observe(img)
img.getBoundingClientRect = () => ({ top: 0, bottom: 100, left: 0, right: 100, width: 100, height: 100 })
observer.root = document.documentElement
Question 8
Why unobserve targets after lazy loading images?
Question 9
What prints?
const target = document.createElement('div')
const observer = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
console.log(entry.time < performance.now())
})
})
observer.observe(target)
Question 10
Which entry property reports how much of the target is visible?
Question 11
What prints?
const target = document.createElement('section')
const observer = new IntersectionObserver((entries) => console.log(entries.length))
observer.observe(target)
observer.disconnect()
observer.observe(target)
console.log(observer.takeRecords())
Question 12
Why call disconnect() on component unmount?
Question 13
What prints?
const target = document.createElement('div')
const observer = new IntersectionObserver((entries) => {
const entry = entries[0]
console.log(entry.boundingClientRect === target.getBoundingClientRect())
})
observer.observe(target)
Question 14
Which property indicates whether the target is currently intersecting the root?
Question 15
Why does Intersection Observer avoid forced synchronous layout?
Question 16
How do batched intersection callbacks improve performance?
Question 17
What prints?
const nav = document.createElement('nav')
const observer = new IntersectionObserver((entries) => {
if (!entries[0].isIntersecting) {
nav.classList.add('sticky')
} else {
nav.classList.remove('sticky')
}
})
observer.observe(document.querySelector('header'))
console.log(nav.classList.contains('sticky'))
Question 18
Which configuration suits triggering animations near the viewport?
Question 19
What prints?
const observer = new IntersectionObserver((entries) => {
entries.forEach((entry) => console.log(entry.target.dataset.id, entry.intersectionRatio))
}, { threshold: [0, 0.25, 0.5, 0.75, 1] })
const section = document.createElement('section')
section.dataset.id = 'hero'
observer.observe(section)
Question 20
Why is Intersection Observer useful for infinite scroll?
Question 21
Why is Intersection Observer good for analytics?
Question 22
What prints?
const target = document.createElement('div')
const observer = new IntersectionObserver((entries, obs) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
console.log('intersecting once')
obs.unobserve(entry.target)
}
})
})
observer.observe(target)
observer.observe(target)
console.log(observer.takeRecords().length)
Question 23
What prints?
const target = document.createElement('div')
target.getBoundingClientRect = () => ({ top: -50, bottom: 50, left: 0, right: 100, width: 100, height: 100 })
const observer = new IntersectionObserver((entries) => {
entries.forEach((entry) => console.log(entry.intersectionRect.height))
})
observer.observe(target)
Question 24
When would you set a non-null root element?
Question 25
What prints?
const root = document.createElement('div')
root.style.overflow = 'auto'
root.style.height = '200px'
const target = document.createElement('div')
const observer = new IntersectionObserver((entries) => {
console.log(entries[0].rootBounds === root.getBoundingClientRect())
}, { root })
observer.observe(target)
Question 26
Why call takeRecords() before disconnecting?
Question 27
What prints?
const observer = new IntersectionObserver((entries) => {
entries.forEach((entry) => console.log(entry.target === entry.target.ownerDocument.querySelector('#watched')))
})
const el = document.createElement('div')
el.id = 'watched'
observer.observe(el)
Question 28
What prints?
const observer = new IntersectionObserver((entries) => {
entries.forEach((entry) => console.log(entry.rootBounds?.top))
}, { root: document.documentElement, rootMargin: '50px' })
observer.observe(document.createElement('div'))
Question 29
Why might you use different thresholds for hero banners vs advertisements?
Question 30
How does a single observer handle multiple targets?
Question 31
What prints?
class VisibilityWatcher {
constructor(target) {
this.target = target
this.observer = new IntersectionObserver(this.handle.bind(this))
this.observer.observe(target)
}
handle(entries) {
if (!entries[0].isIntersecting) return
console.log('visible once')
this.observer.unobserve(this.target)
}
}
new VisibilityWatcher(document.createElement('div'))
Question 32
When do multiple entries appear in a single callback?
Question 33
Why limit observers per page?
Question 34
What prints?
const observer = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
if (entry.intersectionRatio > 0) {
observer.disconnect()
console.log('triggered')
}
})
})
const target = document.createElement('div')
observer.observe(target)
observer.observe(target)
console.log(observer.takeRecords().length)
Question 35
Why document Intersection Observer thresholds and margins for teammates?
