Альтернативный метод скрытой загрузки изображений техникой прогрессивного улучшения

Альтернативный метод скрытой загрузки изображений техникой прогрессивного улучшения

От автора: в будущей статье про галерею я хотел бы применить к изображениям технику прогрессивного улучшения, чтобы создать живую, доступную презентацию высокого качества.

Курица или яйцо

JavaScript не может гарантировать стопроцентное сокрытие HTML-изображений до их загрузки: если скрипт будет выполнен не вовремя, пользователь может заметить вспышки на экране – изображение загружается и только потом прячется с помощью JS. Если же изображения загружаются исключительно через JS, а скрипты отключены или не сработали, тогда пользователь увидит голую страницу.

Обычно для решения этой проблемы используют комбинацию из старых и новых техник: прозрачный фильтр в формате GIF размером 1х1 px размещается в атрибуте src, а настоящее изображение в data- атрибуте.

<img src="1x1.gif" class="lazy" data-src="real-image.jpg" alt>

Потом JS заменяет старое значение на новое, часто это делается по событию прокрутки:

var lazy = document.getElementsByClassName('lazy');
for(var i=0; i<lazy.length; i++){
 lazy.src = lazy.getAttribute('data-src');
}

Однако проблема блокирования JS до сих пор не решена. Для ее решения можно поместить настоящее изображение в тег noscript:

<noscript>
    <img src="real-image.jpg" alt>
</noscript>

Контент внутри тега noscript отображается только в случае, если JS не поддерживается. Если JS работает, то GIF фильтры заменяются нормальными изображениями, а контент noscript игнорируется. Тем не менее, у данного подхода есть два минуса:

Контент на странице повторяется два раза (первый в атрибуте data-src, второй в теге noscript), что усложняет работу с кодом.

Нет фолбэка на случай если JS поддерживается, но в коде есть ошибки: контент noscript отображаться не будет, а изображения не заменятся на нормальные, т.е. страница останется пустая.

Другой способ

На выходных я придумал другой способ. Он отлично работает с одним допущением, если браузера поддерживает CSS анимацию. Я загружал изображения на страницу, но оставлял их невидимыми, если JS был активен.

Изображения на странице размещаются как обычно: в нашем случае я обернул их в блок DIV с двумя классами; атрибут alt я оставил пустым для упрощения кода:

<div class="shuffle reveal">
    <img src="umbrellas.jpg" alt>
    <img src="shopping-at-night.jpg" alt>
    <img src="lanterns.jpg" alt>
    <img src="outdoor-dining.jpg" alt>
    <img src="blade-runner.jpg" alt>
    <img src="square-umbrellas.jpg" alt>
</div>

Изображениям задано свойство opacity 0:

.shuffle img { 
  width: 33%; 
  opacity: 0; 
}

К изображениям также прицеплена анимация, которая сделает прозрачность равной 1 через 1 секунду: недостаточно, чтобы кто-то заметил, но достаточно, чтобы JS подхватил работу:

@keyframes reveal {
  to { 
    opacity: 1; 
  }
}
.reveal img { 
  animation: reveal 1s 1s forwards; 
}

Анимацию можно сделать более изощренной, добавив последовательное плавное появление в CSS:

.reveal img:nth-child(1) { animation-delay: .5s; }
.reveal img:nth-child(2) { animation-delay: 1s; }
.reveal img:nth-child(3) { animation-delay: 1.5s; }
...

JavaScript

Скрипт находит элементы с классом reveal при помощи querySelector и удаляет их с помощью метода classList. После этого анимация не сработает:

var reveal = document.querySelector(".reveal");
reveal.classList.remove("reveal");

Изображения в ссылках все еще доступны скрипту:

var revealedImages = reveal.querySelectorAll("img"),

…т.е. изображения загрузятся, но будут скрыты, пока их не покажут с помощью JS. В теории можно не задавать opacity:0 через CSS, а делать изображения невидимыми напрямую из JS:

Array.prototype.forEach.call(revealedImages, function(photo) { 
      photo.style.display = "none";
})

Данный подход немного рискованный. Для его работы ничто не должно блокировать JavaScript.

Результат

Если JS не поддерживается, или не сработал код, изображения с анимацией плавно появятся через секунду – от JS версии почти не отличается (появление можно сделать последовательным, если добавить CSS). Если JS работает, изображения будут скрыты до тех пор, пока скрипт не изменит их.

Я тестировал демо с помощью инструмента понижения скорости соединения до 2G, код работал отлично. Единственное, что мне не нравится в CSS, это то, как он выбирает время: если хоть что-то помешало выполнению JavaScript, анимация будет запущена сразу же. Тем не менее, веб-страницы, спроектированные по современным стандартам производительности, должны нормально работать. Надеюсь, данный метод был вам полезен.

JavaScript&jQuery с нуля до профи

Пройдите пошаговый видеокурс по JavaScript&jQuery

Научиться

Метки:

Комментарии Вконтакте:

Комментарии Facebook:

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Можно использовать следующие HTML-теги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Я не робот.

Spam Protection by WP-SpamFree