Hi. In this post, I'll give some information about IntersectionObserver API.
Before we start, I should say this IE11 doesn't support this API. You can check which browsers support on the CanIUse.
Why?
There are many libraries that helping lazy loading operations. I know, but this API native. You may don't want to use external libraries etc.
In a project, we had many images and many list items. Because of that images, the page was loading in 10-15 seconds. This was terrible for us and our customers, visitors etc.
We found some solutions like server-side pagination. But this wasn't a good solution for our project. Because customers didn't want to reload the page.
In order to solve the problem, we found Verlok's lazyload library. But we also found IntersectionObserver API. Anyway, we decided to use IntersectionObserver API. We're using IntersectionObserver today. Okay, I'll show how.
HTML && CSS Codes
In this example, we'll use the Bootstrap 4's Card component. We also use the button component for tracking the index. Default index will be 0(zero).
<div class="container">
<div class="row">
<div class="col-md-12 card-container">
</div>
</div>
<div class="row">
<div class="col-md-12 load-more-container">
<button data-index="0" class="btn btn-primary btn-block load-more">Load More</button>
</div>
</div>
</div>
And the CSS will be like this. Just a little bit margin. Our cards look more pretty now.
.load-more-container {
margin-top: 15px;
}
.card {
margin-bottom: 15px;
}
JavaScript Codes
I'll create a class. You may want to create a function. This depends on you. The class will start like this. Its name will be LazyLoad.
class LazyLoad {
constructor() {
this.btn = document.querySelector(".load-more")
this.cardContainer = document.querySelector('.card-container')
this.BASE_URL = 'https://picsum.photos/list'
}
}
We will API server for the images.
In this example, we always call all the images from this server. Because I couldn't find any pagination.
Then, I'll create a function called load.
load() {
fetch(this.BASE_URL)
.then(resp => resp.json())
.then(obj => {
let start = (this.btn.dataset.index == 0) ? parseInt(this.btn.dataset.index) : parseInt(this.btn.dataset.index) + 1
let end = start + 5
let arr = obj.slice(start, end)
if(arr.length > 0) {
let cards = '';
arr.forEach(f => {
cards += `
<div class="card">
<div class="card-body">
<h5 class="card-title">${f.author}</h5>
<img src="https://picsum.photos/458/354/?image=${f.id}" alt="">
</div>
</div>
`
})
this.cardContainer.insertAdjacentHTML('beforeend',cards)
this.btn.dataset.index = end
}
})
}
With this function, we will create fetch requests. We will also create HTML content thanks to template literals to put them to .card-container
.
And the last thing, we will create a function called init. The function will be like this;
init() {
const container = document.querySelector(".load-more-container")
let observer = new IntersectionObserver(entries => {
entries.forEach(entry => {
const { isIntersecting } = entry
if(isIntersecting) {
this.load()
//observer = observer.disconnect()
}
}, {
root: container
})
})
observer.observe(container)
}
In the above code, when the element intersecting with the user' viewport codes will be run. IntersectionObserver gives two arguments. The first argument will be a callback. The second argument will be options. In this example, we have only root
options.
The callback that receives one or more intersection entries. And observer will be observing the container we created.
observer.observe(container)
Using observer = observer.disconnect()
you will stop observing operations. Which means, more load functionality will not work.
Before Finishing
If you want to a real example, I've created an example on the CodePen. You can check it how it works.
Resources
I hope this post will help you with your projects.
Thanks for reading!
Top comments (5)
Very simple and effective, thanks!
You're welcome :)
Very interesting, I love how there's always new web APIs to learn about!
I started doing this recently, a great and simple native api. I also use it for other lazy parts such as iframes or Instagram feeds
Great examples! Can't wait to use this myself