Pre-loader для сайта

Пример прелоадера для страницы сайта

В данной статье мы рассмотрим, как показать информацию о процессе загрузки сайта до самой загрузки каких-либо скриптов и полного HTML документа.

Наша задача каким-то образом показать элемент на странице, до загрузки чего бы то ни было тяжелого вроде скриптов, как минимум полной загрузки <body>, а потом отследить загрузку и убрать этот элемент. На первый взгляд это кажется противоречащим самому себе. Как показать что-то, до загрузки части документа, который как раз и содержит визуальную информацию и убрать после?

Однако есть один момент. Теги <html>, <head> читаются раньше, плюс в CSS есть псевдоэлементы, нас интересует ::before.

Псевдоэлементы ::before, ::after — это часть селекторов CSS, которые используют для вставки содержимого, которого нет в исходном коде.

Решение

  1. Добавляем стилизованный псевдоэлемент ::before на тег <html> с нужным нам элементом-прелоадером;
  2. Отлавливаем в JS момент загрузки страницы (2 варианта). Убираем отображение загрузки, с помощью добавления класса конца загрузки тегу <html>.

Подробное описание

Рассмотрим пример добавление прелоадера на примере нашего сайта.

Добавляем в <head>, напрямую или через файл, стили:

html::before {
  background-size: 150px !important;
  opacity: 1;
  content: "";
  display: block;
  position: fixed;
  z-index: 999;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: url("/logo-animate.svg") no-repeat center, #fff;
  transition: opacity 0.3s ease-in;
}

html.loaded::before {
  opacity: 0;
  pointer-events: none;
}

Здесь видно, что в нашем случае content — пустая строка. Мы позиционируем по центру background с SVG лоадером, растягивая слой на весь экран, а так же выставляя большой z-index, что позволит нам скрывать постепенную загрузку/отображение элементов. Плюс небольшая анимация перехода.

/logo-animate.svg - background с SVG лоадером
Файл /logo-animate.svg

Далее у нас есть 2 варианта работы с JS, мы можем поймать события:

  • DOMContentLoaded – браузер полностью загрузил HTML, было построено DOM-дерево, но внешние ресурсы, такие как картинки <img> и стили, могут быть ещё не загружены;
  • load – браузер загрузил HTML и внешние ресурсы (картинки, стили и т.д.).

Выбор за Вами, понятно, что первое событие будет раньше и Вы можете даже добавить дополнительный этап загрузки, между DOMContentLoaded и load соответственно. Мы же остановимся на load:

window.addEventListener("load", () => {
  document.documentElement.classList.add("loaded");
});

setTimeout(()=>{ 
    if(!document.documentElement.classList.contains("loaded"))
       document.documentElement.classList.add("loaded");
}, 10000);

Объекту window добавляем событие load, по которому добавляем класс окончания загрузки на тег <html> (в JS к нему можно обращаться как к documentElement).

Так же, для очень медленных соединений, мы посчитали необходимым снимать loader (setTimeout) через 10 сек, после загрузки скрипта, если DOM дерево по каким-то причинам будет очень долго строиться и отображаться. Что-бы показать хоть какой-то процесс или возможно наличие обрыва соединения.

Упаковка в plugin WordPress

Для удобства управления, все вышеописанное можно упаковать в плагин WP. Например такой код позволит подключить стилевой и скриптовый файлы:

<?php
/*
Plugin Name: Easy Page Preloader
Plugin URI: http://consultapp.ru/pre-loader-for-site/
Description: Adding a preloader to the pages. No conflicts with SEO. You can set your own logo.
Version: 1.0
Author: Dmitry Egorov
Author URI: http://consultapp.ru/
License: GPLv2
*/

//********************************************************************
//*************************** PLUGIN CORE ****************************
//********************************************************************

function ca_epl(){
        wp_enqueue_style( 'html-loader', plugins_url( '/style.css', __FILE__ ) );
        wp_enqueue_script( 'html-loader-script', plugins_url( '/script.js', __FILE__ ), array(), '1.0.1', true );
}
add_action('wp_enqueue_scripts', 'ca_epl');

Заключение

В статье мы рассмотрели, как с помощью прсевдоэлемента ::before добавленного к тегу <html> добавить preloader на страницу, и отключать его по событию load на объекте window.