We love Preact for its tiny size and capabilities which makes it an ideal choice for smaller web applications.
Making this visibility test more efficient is what
IntersectionObserver
was designed for, and it’s landed in Chrome 51 (which is, as of this writing, the beta release).IntersectionObservers
let you know when an observed element enters or exits the browser’s viewport.
To know more about Intersection Observer please check out the awesome article written by Surma on Google Web Fundamentals
Most of the modern browsers support Intersection Observer out of the box.
Update: Check latest support details
If you still need support for older browsers and IE there is a well written and documented polyfill available on Github in the w3c repo, find the link below.
To enable lazy loading for images the best approach is to create an Image component in Preact and use the same instead of the img
tag.
import { h, Component } from 'preact';
import classy from 'classnames';
export default class Image extends Component {
state = {
src: 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7',
dataSrc: false,
loaded: false
}
inview(entries, observer){
entries.forEach(entry => {
if(entry.intersectionRatio){
entry.target.addEventListener('load', this.loading.bind(this));
entry.target.src = entry.target.getAttribute("data-src");
observer.unobserve(entry.target);
}
})
}
loading(event){
if(event.target.complete) this.setState({
loaded: true
});
}
componentDidMount(){
this.setState({
dataSrc: this.props.src,
loaded: false
});
const observer = new IntersectionObserver(this.inview.bind(this));
observer.observe(this.element);
}
render() {
return (
<div className="image-container">
<div className={classy({loader: true, hidden: this.state.loaded})}>
<img src="assets/img/loading.svg" />
</div>
<img src={this.state.src} data-src={this.state.dataSrc} ref={element => this.element = element} />
</div>
);
}
}
SCSS for .image-container
.image-container{
position: relative;
.loader{
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
&.hidden {
display: none;
}
}
}
Uses of the Image component
<Image src={data.image} />
The following happens when you use the Image component instead of the img
tag.
inview
method as a callback..image-container
.image-container
is in-view it sets the state with loaded property to trueLazy loading can make the app load fast and provide a better user experience.
Google Develover Expert — WebTechnologies and Angular | Principal Architect at Naukri.com | Entrepreneur | TechEnthusiast | Speaker