Lazy load media
На сьогодні сайти дуже переповнені різного роду контентом як відео, так і зображеними. Постає питання як це все вірно показувати.
В більшості випадків ніхто не задумується над цим, але коли постає питання швидкості завантаження сторінки, де кожна секунда важлива, кидають погляд в сторону відкладеного завантаження контенту.
Логіка така - навіщо показувати картинки чи відео під час завантаження сторінки (якщо цього не потрібно), до моменту коли це реально потрібно.
Наприклад картинки внизу сайту нам не потрібно завантажувати разом зі всією сторінкою, до моменту поки користувач не бачить місце це вона має бути.
Реалізуємо невеликий js скрипт, що буде завантажувати картинки не разом зі сторінкою, а після.
Для цього замінимо
<img src="/image.jpg" />
на
<img data-src="/image.jpg" />
Та приєднаємо скрипт. Все просто, знаходимо всі картинки і якщо data-src беремо url та вставляємо в src
document.querySelectorAll('img').forEach(item=>{
if (item.dataset.src){
item.src = item.dataset.src
item.removeAttribute('data-src')
}
})
Аналогічно можливо зробити для video, iframe.
Але це сильно просто і не дуже ефективно. Реалізуймо підвантаження коли елемент попадає в зону видимості скриптом, якому потрібно передати елемент, що шукаємо.
function isInViewport(el) {
const rect = el.getBoundingClientRect();
return (
rect.top >= 0 &&
rect.left >= 0 &&
rect.bottom <= (window.outerHeight || document.documentElement.clientHeight) &&
rect.right <= (window.innerWidth || document.documentElement.clientWidth)
);
}
Тепер зберемо все разом, і реалізуємо активацію при пролистуванні
Кінцевий варіант для картинок відео та iframe буде виглядати так.
(function (){
/**
* isInViewport
* @param el
* @returns {boolean}
*/
function isInViewport(el) {
const rect = el.getBoundingClientRect();
return (
rect.top >= 0 &&
rect.left >= 0 &&
rect.bottom <= (window.outerHeight || document.documentElement.clientHeight) &&
rect.right <= (window.innerWidth || document.documentElement.clientWidth)
);
}
document.addEventListener('scroll', LLoad, {
passive: true
});
/**
*
* @constructor
*/
function LLoad() {
document.querySelectorAll('video,source,iframe').forEach(item => {
if (item.dataset.src && isInViewport(item)) {
item.src = item.dataset.src
item.removeAttribute('data-src')
}
})
}
LLoad()
})()
Приклад на Сodepen
Та бувають випадки коли контент встановлений як фон блоку. Тому так само можемо замінити контент фону. Перед цим додавши url контенту в дата параметр типу data-bg та додавши клас lazy-bg
<div data-bg="/image.jpg" class="lazy-bg"></div>
Додамо зміни в скрипт:
(function (){
/**
* isInViewport
* @param el
* @returns {boolean}
*/
function isInViewport(el) {
const rect = el.getBoundingClientRect();
return (
rect.top >= 0 &&
rect.left >= 0 &&
rect.bottom <= (window.outerHeight || document.documentElement.clientHeight) &&
rect.right <= (window.innerWidth || document.documentElement.clientWidth)
);
}
document.addEventListener('scroll', LLoad, {
passive: true
});
/**
*
* @constructor
*/
function LLoad() {
document.querySelectorAll('img,video,source,iframe,.lazy-bg').forEach(item => {
if (item.dataset.src && isInViewport(item)) {
item.src = item.dataset.src
item.removeAttribute('data-src')
}
/**
* Replace bg
*/
if (item.dataset.bg && isInViewport(item)){
let src = item.dataset.bg
item.style.background = `url("${src}")`;
item.style.backgroundPosition = 'center center';
item.style.backgroundSize = 'cover';
}
})
}
LLoad()
})()