От автора: в будущей статье про галерею я хотел бы применить к изображениям технику прогрессивного улучшения, чтобы создать живую, доступную презентацию высокого качества.
Курица или яйцо
JavaScript не может гарантировать стопроцентное сокрытие HTML-изображений до их загрузки: если скрипт будет выполнен не вовремя, пользователь может заметить вспышки на экране – изображение загружается и только потом прячется с помощью JS. Если же изображения загружаются исключительно через JS, а скрипты отключены или не сработали, тогда пользователь увидит голую страницу.
Обычно для решения этой проблемы используют комбинацию из старых и новых техник: прозрачный фильтр в формате GIF размером 1х1 px размещается в атрибуте src, а настоящее изображение в data- атрибуте.
1 |
<img src="1x1.gif" class="lazy" data-src="real-image.jpg" alt> |

JavaScript. Быстрый старт
Изучите основы JavaScript на практическом примере по созданию веб-приложения
Узнать подробнееПотом JS заменяет старое значение на новое, часто это делается по событию прокрутки:
1 2 3 4 |
var lazy = document.getElementsByClassName('lazy'); for(var i=0; i<lazy.length; i++){ lazy[i].src = lazy[i].getAttribute('data-src'); } |
Однако проблема блокирования JS до сих пор не решена. Для ее решения можно поместить настоящее изображение в тег noscript:
1 2 3 |
<noscript> <img src="real-image.jpg" alt> </noscript> |
Контент внутри тега noscript отображается только в случае, если JS не поддерживается. Если JS работает, то GIF фильтры заменяются нормальными изображениями, а контент noscript игнорируется. Тем не менее, у данного подхода есть два минуса:
Контент на странице повторяется два раза (первый в атрибуте data-src, второй в теге noscript), что усложняет работу с кодом.
Нет фолбэка на случай если JS поддерживается, но в коде есть ошибки: контент noscript отображаться не будет, а изображения не заменятся на нормальные, т.е. страница останется пустая.
Другой способ
На выходных я придумал другой способ. Он отлично работает с одним допущением, если браузера поддерживает CSS анимацию. Я загружал изображения на страницу, но оставлял их невидимыми, если JS был активен.
Изображения на странице размещаются как обычно: в нашем случае я обернул их в блок DIV с двумя классами; атрибут alt я оставил пустым для упрощения кода:
1 2 3 4 5 6 7 8 |
<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:

JavaScript. Быстрый старт
Изучите основы JavaScript на практическом примере по созданию веб-приложения
Узнать подробнее
1 2 3 4 |
.shuffle img { width: 33%; opacity: 0; } |
К изображениям также прицеплена анимация, которая сделает прозрачность равной 1 через 1 секунду: недостаточно, чтобы кто-то заметил, но достаточно, чтобы JS подхватил работу:
1 2 3 4 5 6 7 8 |
@keyframes reveal { to { opacity: 1; } } .reveal img { animation: reveal 1s 1s forwards; } |
Анимацию можно сделать более изощренной, добавив последовательное плавное появление в CSS:
1 2 3 4 |
.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. После этого анимация не сработает:
1 2 |
var reveal = document.querySelector(".reveal"); reveal.classList.remove("reveal"); |
Изображения в ссылках все еще доступны скрипту:
1 |
var revealedImages = reveal.querySelectorAll("img"), |
…т.е. изображения загрузятся, но будут скрыты, пока их не покажут с помощью JS. В теории можно не задавать opacity:0 через CSS, а делать изображения невидимыми напрямую из JS:
1 2 3 |
Array.prototype.forEach.call(revealedImages, function(photo) { photo.style.display = "none"; }) |
Данный подход немного рискованный. Для его работы ничто не должно блокировать JavaScript.
Результат
Если JS не поддерживается, или не сработал код, изображения с анимацией плавно появятся через секунду – от JS версии почти не отличается (появление можно сделать последовательным, если добавить CSS). Если JS работает, изображения будут скрыты до тех пор, пока скрипт не изменит их.
Я тестировал демо с помощью инструмента понижения скорости соединения до 2G, код работал отлично. Единственное, что мне не нравится в CSS, это то, как он выбирает время: если хоть что-то помешало выполнению JavaScript, анимация будет запущена сразу же. Тем не менее, веб-страницы, спроектированные по современным стандартам производительности, должны нормально работать. Надеюсь, данный метод был вам полезен.

JavaScript. Быстрый старт
Изучите основы JavaScript на практическом примере по созданию веб-приложения
Узнать подробнее
JavaScript. Быстрый старт
Изучите основы JavaScript на практическом примере по созданию веб-приложения
Смотреть