Как сделать прелоадер для сайта?

Александр Мальцев
81K
1
Как сделать прелоадер для сайта?
Содержание:
  1. Назначение прелоадера
  2. Как создать прелоадер страницы
  3. Прелоадер на чистом CSS
  4. Прелоадер в виде анимированной svg иконки
  5. Прелоадер с использованием анимированной gif картинки
  6. Вариант прелоадера с использованием jQuery функции fadeOut
  7. Комментарии

В этой статье разберём процесс создания прелоадера для сайта как на чистом CSS, так и с использованием изображений.

Назначение прелоадера

Страница любого сайта или веб-приложения не загружается мгновенно. На загрузку и отображение страницы необходимо некоторое время. При этом страница при её загрузке может видоизменяться. Обычно это происходит при загрузке стилей, шрифтов, картинок. Чтобы этот не привлекательный момент скрыть от пользователя, можно на время загрузки страницы отобразить пользователю какой-нибудь анимированный прелоадер. А после того, как страница полностью загрузится его убрать. Основная цель прелоадера — это улучшить впечатление пользователя о сайте.

Как создать прелоадер страницы

На самом деле создать прелоадер очень просто.

Для этого нужно сразу после открывающего тега body добавить код (HTML структуру прелоадера). С помощью CSS его необходимо настроить так, чтобы он занимал всю область viewport и находился над содержимым страницы. В качестве прелодера обычно используют анимированную картинку (svg, gif), или CSS-анимацию.

В процессе загрузки страницы её контент находится под прелодером. Пользователь видит только анимированную картинку.

После полной загрузки прелоадер необходимо скрыть. Чтобы это осуществить необходимо написать очень маленький скрипт. Это можно выполнить как на чистом JavaScript, так и с использованием библиотеки jQuery.

Прелоадер на чистом CSS

Этапы создания прелодера на чистом CSS:

1. Добавить после открывающего тега body следующий HTML-код:

<div class="preloader">
  <div class="preloader__row">
    <div class="preloader__item"></div>
    <div class="preloader__item"></div>
  </div>
</div>

Элемент .preloader – это контейнер, который будет занимать всю область просмотра и находится над содержимым страницы. .preloader__row и .preloader__item – необходимы для создания CSS-анимации, которую отобразим в центре viewport.

2. Создать следующие стили:

.preloader {
  /*фиксированное позиционирование*/
  position: fixed;
  /* координаты положения */
  left: 0;
  top: 0;
  right: 0;
  bottom: 0;
  /* фоновый цвет элемента */
  background: #e0e0e0;
  /* размещаем блок над всеми элементами на странице (это значение должно быть больше, чем у любого другого позиционированного элемента на странице) */
  z-index: 1001;
}

.preloader__row {
  position: relative;
  top: 50%;
  left: 50%;
  width: 70px;
  height: 70px;
  margin-top: -35px;
  margin-left: -35px;
  text-align: center;
  animation: preloader-rotate 2s infinite linear;
}

.preloader__item {
  position: absolute;
  display: inline-block;
  top: 0;
  background-color: #337ab7;
  border-radius: 100%;
  width: 35px;
  height: 35px;
  animation: preloader-bounce 2s infinite ease-in-out;
}

.preloader__item:last-child {
  top: auto;
  bottom: 0;
  animation-delay: -1s;
}

@keyframes preloader-rotate {
  100% {
    transform: rotate(360deg);
  }
}

@keyframes preloader-bounce {

  0%,
  100% {
    transform: scale(0);
  }

  50% {
    transform: scale(1);
  }
}

.loaded_hiding .preloader {
  transition: 0.3s opacity;
  opacity: 0;
}

.loaded .preloader {
  display: none;
}

Размещение прелоадера над контентом осуществляется посредством задания ему фиксированного позиционирования и CSS-свойства z-index.

3. Вставить сценарий, который будет добавлять к элементу body класс loaded после полной загрузки страницы:

<script>
  window.onload = function () {
    document.body.classList.add('loaded');
  }
</script>

Этот скрипт очень резко скрывает прелоадер. Чтобы этот процесс улучшить, а именно выполнить это с анимацией можно использовать вместо вышеприведённого сценария этот:

<script>
  window.onload = function () {
    document.body.classList.add('loaded_hiding');
    window.setTimeout(function () {
      document.body.classList.add('loaded');
      document.body.classList.remove('loaded_hiding');
    }, 500);
  }
</script>
Демо прелоадера

Прелоадер в виде анимированной svg иконки

Процесс создания прелоадера в виде анимированной svg иконки не будет сильно отличаться от примера с использованием CSS-анимации.

1. Создадим HTML-разметку прелоадера и разместим её сразу же после открывающего тега body:

<div class="preloader">
  <svg class="preloader__image" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
    <path fill="currentColor"
      d="M304 48c0 26.51-21.49 48-48 48s-48-21.49-48-48 21.49-48 48-48 48 21.49 48 48zm-48 368c-26.51 0-48 21.49-48 48s21.49 48 48 48 48-21.49 48-48-21.49-48-48-48zm208-208c-26.51 0-48 21.49-48 48s21.49 48 48 48 48-21.49 48-48-21.49-48-48-48zM96 256c0-26.51-21.49-48-48-48S0 229.49 0 256s21.49 48 48 48 48-21.49 48-48zm12.922 99.078c-26.51 0-48 21.49-48 48s21.49 48 48 48 48-21.49 48-48c0-26.509-21.491-48-48-48zm294.156 0c-26.51 0-48 21.49-48 48s21.49 48 48 48 48-21.49 48-48c0-26.509-21.49-48-48-48zM108.922 60.922c-26.51 0-48 21.49-48 48s21.49 48 48 48 48-21.49 48-48-21.491-48-48-48z">
    </path>
  </svg>
</div>

В качестве svg можно использовать любое другое изображение.

2. Добавим CSS:

.preloader {
  position: fixed;
  left: 0;
  top: 0;
  right: 0;
  bottom: 0;
  overflow: hidden;
  /* фоновый цвет */
  background: #e0e0e0;
  z-index: 1001;
}

.preloader__image {
  position: relative;
  top: 50%;
  left: 50%;
  width: 70px;
  height: 70px;
  margin-top: -35px;
  margin-left: -35px;
  text-align: center;
  animation: preloader-rotate 2s infinite linear;
}

@keyframes preloader-rotate {
  100% {
    transform: rotate(360deg);
  }
}

.loaded_hiding .preloader {
  transition: 0.3s opacity;
  opacity: 0;
}

.loaded .preloader {
  display: none;
}

3. Поместим на страницу следующий сценарий:

<script>
  window.onload = function () {
    document.body.classList.add('loaded_hiding');
    window.setTimeout(function () {
      document.body.classList.add('loaded');
      document.body.classList.remove('loaded_hiding');
    }, 500);
  }
</script>

Этот сценарий на чистом JavaScript. Но его можно написать с использованием библиотеки jQuery.

В этом случае он будет выглядеть следующим образом:

<script>
  $(window).on('load', function () {
    $('body').addClass('loaded_hiding');
    window.setTimeout(function () {
      $('body').addClass('loaded');
      $('body').removeClass('loaded_hiding');
    }, 500);
  }
</script>
Демо прелоадера

Пример прелоадера с градиентным фоном:

Демо прелоадера

Прелоадер с использованием анимированной gif картинки

В качестве изображения можно использовать не только svg, но и gif картинку.

HTML разметка:

<!-- Прелоадер -->
<div class="preloader">
  <div class="preloader__image"></div>
</div>

CSS для прелоадера:

.preloader {
  position: fixed;
  left: 0;
  top: 0;
  right: 0;
  bottom: 0;
  overflow: hidden;
  background: #fff;
  z-index: 1001;
}

.preloader__image {
  position: relative;
  top: 50%;
  left: 50%;
  width: 64px;
  height: 64px;
  margin-top: -32px;
  margin-left: -32px;
  background: url('preloader.gif') no-repeat 50% 50%; /*расположение (url) изображения gif и др. параметры*/
}

.loaded_hiding .preloader {
  transition: 0.3s opacity;
  opacity: 0;
}

.loaded .preloader {
  display: none;
}
Демо прелоадера

Небольшая коллекция анимированных gif-изображений имеется в этом архиве.

Вариант прелоадера с использованием jQuery функции fadeOut

Пример скрипта нв jQuery для скрытия прелоадере с использованием функции fadeOut:

$(window).on('load', function() {
  $('.preloader').fadeOut().end().delay(400).fadeOut('slow');
});
Демо прелоадера

Комментарии ()

  1. Наталья
    29 мая 2021, 14:03
    Добрый день, это очень простой прелодер. Он скрывается автоматически через 500ms и даже не проверяет загрузилась страничка или нет. Подскажите, пожалуйста, как мне можно проверить загрузились ли картинки в конкретном месте и только потом чтобы он скрылся?
    1. Александр Мальцев
      3 минуты назад
      Здравствуйте!
      Скрытие прелоадера выполняется после полной загрузки страницы, для этого используется событие load:
      window.onload = function () {
        //... 
      }
      
      При этом само скрытие прелоадера осуществляется плавно посредством CSS перехода:
      transition: 0.3s opacity;
      
      500ms — это время, через которое с момента начала перехода удаляется класс loaded_hiding и добавляется loaded. Оно нужно только для обеспечения плавности скрытия прелоадера. Вместо этого можно просто использовать transitionend, чтобы выполнить манипуляции с этими классами после окончания перехода.
      window.onload = function () {
        const $body = document.body;
        const $preloader = $body.querySelector('.preloader');
        function afterTransition() {
          $body.classList.add('loaded');
          $body.classList.remove('loaded_hiding');
          $preloader.removeEventListener('transitionend', afterTransition);
        }
        $body.classList.add('loaded_hiding');
        $preloader.addEventListener('transitionend', afterTransition);
      }
      
      Пример с использованием transitionend: preloader-01
    2. Надежда
      03 апреля 2021, 17:06
      Здравствуйте! Помогите, пожалуйста!
      Сделала так, чтобы скроллбар скрывался при загрузке прелоадера, воспользовавшись написанным в комментариях советом, но при появлении скроллбара сдвигается весь уже загруженный контент.
      Какие-то безкостыльные способы решения этой проблемы быть могут?

      margin-right: calc(-1 * (100vw — 100%)) уже пробовала. Этот способ мне не подходит, ибо контент вылезает за пределы экрана, а гугл-роботу не докажешь, что используется «overflow: hidden». Уже неделю не могу понять почему гугл-робот не хочет признать мой сайт оптимизированным для мобильных.
      1. Александр Мальцев
        05 апреля 2021, 14:44
        Здравствуйте! Попробуйте убрать прелоадер и проверьте без него. Может дело не в этом?
      2. Ден
        03 февраля 2021, 12:54
        Отличная статья, доходчиво, просто…
        Вопрос, как в последнем варианте (в анимации с тремя синими шарами) вставить вместо шаров изображение, чтоб оно также вращалось и крутилось? Интересно попробовать для практики.
        itchief.ru/examples/lab.php?topic=javascript&file=preloader-with-jquery
        1. Сухраб
          25 декабря 2020, 07:04
          Здравствуйте Александр. Вопрос такой. Мой прелоад находится в page1 и когда я нажимаю page2 и возвращаюсь к page1 анимация снова играеть. Что делать чтобы этот анимация играла только при запуске. Заранее спасибо
          1. Александр Мальцев
            25 декабря 2020, 15:17
            Здравствуйте! Не совсем ясно как у вас там это всё связано. Чтобы было понятно, сделайте готовый пример и предоставьте ссылку на него.
          2. Игорь
            11 октября 2020, 16:25
            Здравствуйте!
            Спасибо вам за информацию по установке прелоадера с gif. Всё работает по вашему коду чётко.
            Хотел уточнить только один момент — перед загрузкой прелоадера (иногда!) у меня появляется контент (текст) шапки сайта. Буквально на долю секунды моргнёт. Браузер — гугл хром. Можно как то убрать кодом этот момент? Чтобы не появлялся контент перед прелоадером.
            1. Игорь
              12 октября 2020, 22:58
              Вопрос решил переносом блока с кодом в шапку страницы. (делаю на тильде)
              1. Александр Мальцев
                13 октября 2020, 12:48
                Привет! Отлично!
                1. Игорь
                  13 октября 2020, 15:43
                  Александр, приветствую! А вы знаете как можно убрать scrollbar на время работы прелоадера (2сек)?
                  1. Александр Мальцев
                    14 октября 2020, 15:15
                    Привет! Это можно осуществить следующим образом:
                    1. Добавить в CSS следующее:
                    .hide-scroll-y {
                      overflow-y: hidden;
                    }
                    2. Добавить класс hide-scroll-y к body:
                    ...
                    <bode class="hide-scroll-y">
                    ...
                    
                    3. Удалить данный класс у body после загрузки страницы:
                    <script>
                    window.onload = function () {
                      document.body.classList.add('loaded_hiding');
                      window.setTimeout(function () {
                        document.body.classList.add('loaded');
                        document.body.classList.remove('loaded_hiding');
                        // удаляем класс hide-scroll-y
                        document.body.classList.remove('hide-scroll-y');
                      }, 500);
                    }
                    </script>
                    1. Игорь
                      15 октября 2020, 14:33
                      Спасибо, Александр!

                      Я с кодом никогда не был знаком. Я делаю лендинг на Тильде. В основном все в конструкторе есть, можно и без кода обойтись. Но недавно распробовал CSS — вещь! А с JS уже сложнее все, тут уже темный лес — надо изучать)

                      Выбираю блок «Т123» для написания кода.

                      У меня 4 блока таких:
                      — В первом код для прелоадера
                      — Во втором стили (JQuery) разных элементов на сайте (отступы, размеры, формы и т.д.)
                      — В третьем ссылка для кнопки (записаться) для виджета Yclients
                      — В четвертом стили для полосы прокрутки.

                      Вот чтобы вставить этот код на скрытие скроллбара на время работы прелоадера. Мне надо в новом блоке все прописывать или вписать эти коды в первый блок с кодом прелоадера?

                      по 1 пункту я понимаю куда вставить стиль — ок
                      по 2 пункту тут уже сложно с троеточиями, куда его размещать я не понял
                      по 3 я понял — уже готовый скрипт
                      1. Александр Мальцев
                        18 октября 2020, 13:30
                        Конкретно по Тильде не подскажу, не использовал его.
                        1. Игорь
                          18 октября 2020, 13:46
                          Понял, спасибо!
                      2. Игорь
                        15 октября 2020, 02:37
                        Спасибо за ответ, Александр!

                        Буду вникать) Пока не выходит у меня. Надо изучать все это дело. Сохранил у себя ваш ответ. Вернусь к нему позже, как буду уже понимать что к чему
                        1. Александр Мальцев
                          15 октября 2020, 11:47
                          Да, тут, вроде всё просто. Если не получается, то можете сделать вашу страницу на «codepen.io», и оставить здесь ссылку.
              2. Яна
                18 июля 2020, 13:02
                Подскажите, пожалуйста, почему не получается увеличить время длительности прелоадера до 2 с. Использую ваш скрипт
                $(window).on('load', function() {
                $('.preloader').fadeOut().end().delay(2000).fadeOut('slow');
                });
                1. Александр Мальцев
                  20 июля 2020, 15:14
                  Сделайте через setTimeout:
                  $(window).on('load', function () {
                    window.setTimeout(function () {
                      $('.preloader').fadeOut().end().delay(400).fadeOut('slow');
                    }, 2000);
                  });
                  
                2. Maks
                  09 июля 2020, 13:25
                  Здравствуйте.
                  Вопрос такой, используя код gif, что именно надо вставить, чтобы был своя гифка? Я так понял в background надо вставить, но что именно? Ссылку на imgur моей гиф или что?
                  1. Александр Мальцев
                    09 июля 2020, 14:55
                    Здравствуйте! Нужно вставить путь к своей gif (вместо «preloader.gif»):
                    background: url('preloader.gif') no-repeat 50% 50%;
                    
                  2. Евгений
                    12 января 2020, 15:03
                    Добрый день! Как сделать длительность прелоадера побольше?
                    1. Александр Мальцев
                      14 января 2020, 03:33
                      Здравствуйте! Для этого нужно просто указать вместо 500 любое другое количество миллисекунд. После этого функция, заданная в первом параметре setTimeout, будет запускаться уже не через 500, а другое количество миллисекунд после загрузки страницы.
                    2. Александр
                      26 декабря 2019, 10:04
                      Александр, добрый день.
                      А как сделать так, чтобы прелоадер скрывался при загрузке определенной части страницы.

                      Например, На странице используются гуглова рекаптча и АПИ Яндекс карт.
                      Иногда подкгрузка этих ресурсов и построение карт занимает время.
                      Можно-ли спрятать прелоадер когда загрузилось все, кроме например карт,
                      1. Александр Мальцев
                        27 декабря 2019, 15:05
                        Привет! Такого события нет в JavaScript.
                        Можно, например, после того как HTML был полностью загружен и пройден парсером (не дожидаясь окончания загрузки CSS, изображений и т.д.):
                        document.addEventListener('DOMContentLoaded', function () {
                          document.body.classList.add('loaded_hiding');
                          window.setTimeout(function () {
                            document.body.classList.add('loaded');
                            document.body.classList.remove('loaded_hiding');
                          }, 500);
                        });
                        
                        Или на загрузку какого-то другого ресурса.
                        1. Александр
                          28 декабря 2019, 04:24
                          Понял. Спасибо. Буду экспериментировать
                      2. Uncle_Pasha
                        22 октября 2019, 15:51
                        Кстати, теперь $(window).load deprecated на новых версиях jQuery, у меня возникла подобная проблема при подключении прелоадера по схеме из статьи. Полез на stackoverflow, и нашел решение:

                        заменить $(window).load на $(window).on('load', function(){...preloader...})

                        Вдруг кому-то пригодится :)
                        1. Александр Мальцев
                          26 октября 2019, 13:35
                          Спасибо! В статье для совместимости с jQuery 3.x этот момент изменил.
                        2. Александр
                          17 сентября 2019, 14:31
                          Александр спасибо! Отличное руководство. Скажите, как можно прикрутить прелоадер к mfilter2?
                          1. Александр Мальцев
                            18 сентября 2019, 13:04
                            Для этого нужно внести изменения в файл "\assets\components\msearch2\js\web\default.js". Или лучше сделать его копию и подключить его в системных настройках. Это необходимо чтобы ваши изменения не были затёрты при переустановке компонента или его обновлении.
                            В этом файле необходимо найти следующее место:
                            beforeLoad: function () {
                              $(this.options['wrapper']).addClass(this.options['loading_class']);
                              this.results.css('opacity', 0);
                              $(this.options.pagination_link).addClass(this.options.active_class);
                              this.filters.find('input, select').prop('readonly', true).addClass(this.options.disabled_class);
                            },
                            afterLoad: function () {
                              $(this.options['wrapper']).removeClass(this.options['loading_class']);
                              this.results.css('opacity', 1);
                              this.filters.find('.' + this.options.disabled_class).prop('readonly', false).removeClass(this.options.disabled_class);
                            },
                            
                            В beforeLoad нужно добавить код для показа прелоадера, а в afterLoad — код для его скрытия.

                            Или можно даже с помощью CSS. Т.к. к элементу #mse2_mfilter добавляется класс loading когда идёт загрузка контента.
                            #before-load {
                              display: none;
                            }
                            #mse2_mfilter.loading #before-load {
                              display: block;
                            }
                            
                            Но в этом случае блок #before-load нужно расположить в #mse2_mfilter.
                            1. Александр
                              19 сентября 2019, 02:58
                              Через css получилось, через Js не выходит.
                              1. Александр
                                19 сентября 2019, 02:42
                                Александр спасибо! Пытался реализовать это в js фильтра, но не выходит, если не трудно как в js прописать правильно?
                                Как я понимаю на этой строке
                                this.results.css('opacity', 0);
                                и
                                this.results.css('opacity', 1);
                                всё завязано?
                                1. Александр Мальцев
                                  19 сентября 2019, 11:16
                                  В JavaScript тоже самое, только зачем, если с помощью CSS это можно решить.
                                  Будет также:
                                  beforeLoad: function () {
                                    $('#before-load').addClass('show'); // добавим класс show
                                    ...
                                  },
                                  afterLoad: function () {
                                    $('#before-load').removeClass('show'); // удалим класс show
                                    ...
                                  }
                                  
                                  Только изначально #before-load должен быть скрыт:
                                  #before-load {
                                    ...
                                    display: none;
                                  }
                                  #before-load.show {
                                    display: block;
                                  }
                                  
                                  В коде да, реализовано через изменение уровня прозрачности элемента.
                                  1. Александр
                                    19 сентября 2019, 13:46
                                    Александр, спасибо, Вам, за подробное решение. Не получается только сделать, чтобы этот блок с прелоадером был дочерним «position: relative». Не работает в этом случае, возможно я не много неправильно преподношу, но суть что я не могу использовать «position: relative» чтобы отцентрировать прелоадер в блоке результата mFilter2. Так всё работает.
                                    1. Александр Мальцев
                                      21 сентября 2019, 13:21
                                      В этом случае нужно добавить элемент-обёртку для элемента относительно которого необходимо позиционировать элемент.
                                      Результат mFilter2 определяется с помощью элемента #mse2_results. Он расположен в чанке tpl.mFilter2.outer:
                                      [[mFilter2?
                                        ...
                                        &tplOuter=`tpl.mFilter2.outer`
                                      ]]
                                      
                                      В этом случае оборачиваем результат и помещаем в него элемент #before-load:
                                      <div class="mse2_result_wrapper" style="position: relative;">
                                        <div id="before-load">...</div>
                                        <div id="mse2_results">
                                          [[+results]]
                                        </div>
                                      </div>
                                      

                                      [[mFilter2?
                                      &tplOuter=`tpl.mFilter2.outer1`
                                      ]]
                                      1. Александр
                                        21 сентября 2019, 19:25
                                        Александр Спасибо, всё максимально предельно понятно.
                            2. Петр
                              20 мая 2016, 13:17
                              А как сделать чтобы загрузка работала только в определенном блоке

                              <div class="container">
                              <!-- В этом контейнере каталог товаров -->
                              </div>
                              
                              Заранее спасибо
                              1. Зограб
                                14 апреля 2016, 16:58
                                А можно сделать чтобы он назад всплывал, при нажатии на кнопку например?
                                1. Илья
                                  08 апреля 2016, 04:32
                                  Можно про 3й пункт поподробнее… куда его добавлять? ото прелоадер не скрывается
                                  1. Александр Мальцев
                                    08 апреля 2016, 11:06
                                    Вам необходимо на странице найти строчку, в которой подключается библиотека jQuery и после неё расположить этот скрипт.
                                    <!-- Подключение библиотеки jQuery -->
                                    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
                                    <!-- Располагаем после неё скрипт -->
                                    <script>
                                    $(window).load(function() {
                                      $('#before-load').find('i').fadeOut().end().delay(400).fadeOut('slow');
                                    });
                                    </script>
                                    
                                    1. Илья
                                      12 апреля 2016, 08:11
                                      Благодарю за ответ!
                                      Все работает!
                                  Войдите, пожайлуста, в аккаунт, чтобы оставить комментарий.