Від автора: в майбутній статті про галерею я хотів би застосувати до зображень техніку прогресивного поліпшення, щоб створити живу, доступну презентацію високої якості.
Курка чи яйце
JavaScript не може гарантувати стовідсоткове приховування HTML-зображень до їх завантаження: якщо скрипт буде виконаний не вчасно, користувач може помітити спалахи на екрані – зображення завантажується і тільки потім ховається за допомогою JS. Якщо ж зображення завантажуються виключно через JS, а скрипти відключені або не спрацювали, тоді користувач побачить голу сторінку.
Зазвичай для вирішення цієї проблеми використовують комбінацію старих та нових технік: прозорий фільтр у форматі GIF розміром 1х1 px розміщується в атрибуті src, а справжнє зображення data – атрибуті.
Потім JS замінює старе значення на нове, часто це робиться за події прокрутки:
var lazy = document.getElementsByClassName(‘lazy’);
for(var i=0; i
Контент всередині тега noscript відображається лише у випадку, якщо JS не підтримується. Якщо JS працює, то GIF фільтри замінюються нормальними зображеннями, а контент noscript ігнорується. Тим не менш, у цього підходу є два мінуси:
Контент на сторінці повторюється два рази (перший в атрибуті data-src, другий в тезі noscript), що ускладнює роботу з кодом.
Немає фолбэка на випадок якщо JS підтримується, але в коді є помилка: контент noscript відображатися не буде, а зображення не заміняться на нормальні, т. е. сторінка залишиться порожня.
Інший спосіб
На вихідних я придумав інший спосіб. Він відмінно працює з одним припущенням, якщо браузера підтримує CSS анімацію. Я завантажував зображення на сторінку, але залишав їх невидимими, якщо JS був активний.
Зображення на сторінці розміщуються як зазвичай: у нашому випадку я обернув їх у блок DIV з двома класами; атрибут alt я залишив порожнім для спрощення коду:
Зображень встановлено властивість 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.5 s; }
…
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, анімація буде запущена відразу ж. Тим не менш, веб-сторінки, спроектовані за сучасними стандартами продуктивності, повинні нормально працювати. Сподіваюся, даний метод був вам корисний.