Facebook did a survey and they found user perception changed because of 1 icon: the loading indicator.
-
Using their own indicator (vertical bars), people blamed loading performance on Facebook's mobile app.
-
Using an iOS-styled indicator, people attributed loading performance on the Apple operating system.
User experience is easily influenced and has broad implications on your program's credibility!
- For pages that change quickly, i.e. social media feeds, single player games
- For heavy assets and slower paced sites, i.e. image galleries, leisurely displays
- Buffers, i.e. infinite scrolling, multiplayer games
Eager loading is reliant on the client side, while lazy-loading is reliant on the server.
Placeholder can be an image or any HTML element (styled div, svg)
- Server-sided image processing: images shrunk to 200kb
- Blur CSS on client side to hide pixelation
- Deliver shrunk image, pre-load full image
- Render full image and remove blur
If images are dynamically loaded, varied image sizes means that additional code is needed to make the placeholder scalable, otherwise image dimension changes are jarring and disrupt the content flow of elements.
A condition to send network request is when an element, such as a placeholder, intersects the viewport. Documentation
new IntersectionObserver observer(callback, options);
observer.observe(element)
function(entries, observer) {
entries.forEach(entry => {
if (entry.isIntersecting) {
// do stuff
}
}
}
Example: color change on scroll
let myImg = new Image();
myImg.onload = function() {
// replace placeholder
// add image element
document.body.appendChild(myImg);
}
myImg.src = “/location/mountain.png”
- The
onload
event must be defined before settingsrc
Images in JavaScript have a 'complete' property:
myImg.complete
returns true after onload
A function that is deferred every time an input is triggered soon enough. It sets a timer, and when called again, clears and resets the timer. The function runs when the timer finishes.
Most common exmaple is live search, where a search submits the value after the user finishes typing.
let helloWorld = function(){alert("Hello World)};
searchBar.onkeyup = debounce(helloWorld, 1000); //1000 ms
function debounce(callback, wait) {
var timeout;
return () => {
clearTimeout(timeout);
timeout = setTimeout(() => callback(...arguments), wait);
};
};
Variables declared inside a function are limited to the function scope and disappear after the function runs. However, you can keep an inner variable persistent by using it in a nested function (known as a closure). Because every function is stored in a reference, the variables used in a function are also referenced and not garbage collected unless the function is also discarded.
In the debounce function, we need to keep a reference of the same timer, otherwise we'd be creating new timers every time someone presses a key.
arguments
is a reserved keyword that contains the arguments of the function. The ...
array spread syntax from ES6 copies contents of the array and applies them to the function.
arrayClone = [...arrayOriginal];
myFunction.apply(null, args)
equivalent to myFunction(...args)
- Semantic UI framework to create placeholders
- InsersectionObserver on an invisible div at the bottom of the page
- Live search with debounce
Google Chrome developers hinted towards adding the attribute to the browser.
<img loading=”lazy” src=... />
https://www.youtube.com/watch?v=ZBvvCdhLKdw
For now, we still need to implement lazy-loading for backwards compatibility.