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

В этой статье разберём процесс создания прелоадера для сайта как на чистом 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');
});
Кнопка отправки со спиннером
Рассмотрим создание формы, работающей через AJAX. При её отправке будем переводить кнопку type="submit"
в состояние disabled
и показывать спиннер. Спиннер будем отображать до тех пор пока не прийдет ответ от сервера. Тем самым спиннер будет указывать что действие все ещё выполняется и оно не завершено.

1. Отправка формы с использованием XMLHttpRequest:
<style>
@keyframes spinner-border {
100% {
transform: rotate(360deg);
}
}
.submit-spinner {
display: inline-block;
width: 1rem;
height: 1rem;
vertical-align: -0.125em;
border: 0.2em solid currentColor;
border-right-color: transparent;
border-radius: 50%;
-webkit-animation: .75s linear infinite spinner-border;
animation: .75s linear infinite spinner-border;
}
.submit-spinner_hide {
display: none;
}
</style>
<!-- Форма -->
<form action="#" method="post" id="user">
...
<button type="submit"><span class="submit-spinner submit-spinner_hide"></span> Отправить</button>
</form>
<script>
function sendForm() {
const xhr = new XMLHttpRequest();
xhr.open('POST', document.forms.user.action);
xhr.responseType = 'json';
xhr.onload = () => {
document.forms.user.querySelector('[type="submit"]').disabled = false;
document.forms.user.querySelector('.submit-spinner').classList.add('submit-spinner_hide');
if (xhr.status !== 200) {
return;
}
const response = xhr.response;
}
xhr.onerror = () => {
document.forms.user.querySelector('[type="submit"]').disabled = false;
document.forms.user.querySelector('.submit-spinner').classList.add('submit-spinner_hide');
};
document.forms.user.querySelector('[type="submit"]').disabled = true;
document.forms.user.querySelector('.submit-spinner').classList.remove('submit-spinner_hide');
xhr.send(new FormData(document.forms.user));
}
// при отправке формы
document.forms.user.addEventListener('submit', (e) => {
e.preventDefault();
sendForm();
});
</script>
2. Отправка формы с использованием Fetch:
async function sendForm() {
try {
document.forms.user.querySelector('[type="submit"]').disabled = true;
document.forms.user.querySelector('.submit-spinner').classList.remove('submit-spinner_hide');
let response = await fetch(document.forms.user.action, {
method: 'post',
body: new FormData(document.forms.user)
});
document.forms.user.querySelector('[type="submit"]').disabled = false;
document.forms.user.querySelector('.submit-spinner').classList.add('submit-spinner_hide');
if (response.ok) {
let result = await response.json();
}
}
catch (error) {
document.forms.user.querySelector('[type="submit"]').disabled = false;
document.forms.user.querySelector('.submit-spinner').classList.add('submit-spinner_hide');
console.log(error);
}
}
// при отправке формы
document.forms.user.addEventListener('submit', (e) => {
e.preventDefault();
sendForm();
});
Здравствуйте, у меня на сайте для кнопок отправить и в корзину не срабатывает прелоадер https://i.imgur.com/4fSkhRk.png , можете подсказать, как сделать чтоб сработало? использовал код - 1. Отправка формы с использованием XMLHttpRequest:, id="user" у form обязательно надо установить?
У меня у форм везде стоит класс ajax он и отвечает за аякс запросы, может как то через него можно изменить код и получить данные? мне надо при успехе убирать класс .vise у кнопок
Добрый день! Не знаю как у вас реализовано, можно, например, добавить в ваш класс генерацию события. А потом отдельно его обрабатывать и удалять в нём нужный класс. Или добавить эту логику в класс. Вариантов реализации этой задачи можно придумать много. Делайте так как вам это удобнее.
Спасибо за отличную статью!!!
Заметил что прелоадер исчезает в момент перехода между страницами.В принципе Вы уже отвечали на похожий вопрос
Вот Ваш ответ:Только я сначала сам сделал похожий вариант, а потом увидел Ваш пример)
И добавил прозрачности фону, так понятнее что страница не исчезла.Теперь прелоадер крутится и когда отправляется запрос и когда загружается новая страница!
Пожалуйста! Рад, что она помогла.
Подумал, зачем ловить клик по ссылке, а почему-бы не ловить событие перезагрузки страницы?
вместо клика по ссылке событиеОтличный прелоадер!
Подскажите пожалуйста – как сделать так что прелоадер работал и намобильном разрешении сайта? На мобильном разрешении его нет. На десктоп разрешении «Прелоадер в виде анимированной svg иконки» работает отлично.
Нужен прелодер, который будеть ждать ответа от http сервиса, метод «post». пост возвращает ссылку на сайт, куда и должна перейти страница после получения ответа. просто обработка данных может идти очень долго.
Тут всё просто.
1. Когда вы отправляете данные на сервер удаляете класс loaded:
2. Когда получаете ответ от сервера:
Вот на примере кнопки: preloader-clean-css-3
Скрытие прелоадера выполняется после полной загрузки страницы, для этого используется событие load:
При этом само скрытие прелоадера осуществляется плавно посредством CSS перехода:
500ms — это время, через которое с момента начала перехода удаляется класс loaded_hiding и добавляется loaded. Оно нужно только для обеспечения плавности скрытия прелоадера. Вместо этого можно просто использовать transitionend, чтобы выполнить манипуляции с этими классами после окончания перехода.
Пример с использованием transitionend: preloader-01
Сделала так, чтобы скроллбар скрывался при загрузке прелоадера, воспользовавшись написанным в комментариях советом, но при появлении скроллбара сдвигается весь уже загруженный контент.
Какие-то безкостыльные способы решения этой проблемы быть могут?
margin-right: calc(-1 * (100vw — 100%)) уже пробовала. Этот способ мне не подходит, ибо контент вылезает за пределы экрана, а гугл-роботу не докажешь, что используется «overflow: hidden». Уже неделю не могу понять почему гугл-робот не хочет признать мой сайт оптимизированным для мобильных.
Вопрос, как в последнем варианте (в анимации с тремя синими шарами) вставить вместо шаров изображение, чтоб оно также вращалось и крутилось? Интересно попробовать для практики.
itchief.ru/examples/lab.php?topic=javascript&file=preloader-with-jquery
Спасибо вам за информацию по установке прелоадера с gif. Всё работает по вашему коду чётко.
Хотел уточнить только один момент — перед загрузкой прелоадера (иногда!) у меня появляется контент (текст) шапки сайта. Буквально на долю секунды моргнёт. Браузер — гугл хром. Можно как то убрать кодом этот момент? Чтобы не появлялся контент перед прелоадером.
1. Добавить в CSS следующее:
2. Добавить класс hide-scroll-y к body:
3. Удалить данный класс у body после загрузки страницы:
Буду вникать) Пока не выходит у меня. Надо изучать все это дело. Сохранил у себя ваш ответ. Вернусь к нему позже, как буду уже понимать что к чему
Я с кодом никогда не был знаком. Я делаю лендинг на Тильде. В основном все в конструкторе есть, можно и без кода обойтись. Но недавно распробовал CSS — вещь! А с JS уже сложнее все, тут уже темный лес — надо изучать)
Выбираю блок «Т123» для написания кода.
У меня 4 блока таких:
— В первом код для прелоадера
— Во втором стили (JQuery) разных элементов на сайте (отступы, размеры, формы и т.д.)
— В третьем ссылка для кнопки (записаться) для виджета Yclients
— В четвертом стили для полосы прокрутки.
Вот чтобы вставить этот код на скрытие скроллбара на время работы прелоадера. Мне надо в новом блоке все прописывать или вписать эти коды в первый блок с кодом прелоадера?
по 1 пункту я понимаю куда вставить стиль — ок
по 2 пункту тут уже сложно с троеточиями, куда его размещать я не понял
по 3 я понял — уже готовый скрипт
$(window).on('load', function() {
$('.preloader').fadeOut().end().delay(2000).fadeOut('slow');
});
Вопрос такой, используя код gif, что именно надо вставить, чтобы был своя гифка? Я так понял в background надо вставить, но что именно? Ссылку на imgur моей гиф или что?
А как сделать так, чтобы прелоадер скрывался при загрузке определенной части страницы.
Например, На странице используются гуглова рекаптча и АПИ Яндекс карт.
Иногда подкгрузка этих ресурсов и построение карт занимает время.
Можно-ли спрятать прелоадер когда загрузилось все, кроме например карт,
Можно, например, после того как HTML был полностью загружен и пройден парсером (не дожидаясь окончания загрузки CSS, изображений и т.д.):
Или на загрузку какого-то другого ресурса.
заменить $(window).load на $(window).on('load', function(){...preloader...})
Вдруг кому-то пригодится :)
В этом файле необходимо найти следующее место:
В beforeLoad нужно добавить код для показа прелоадера, а в afterLoad — код для его скрытия.
Или можно даже с помощью CSS. Т.к. к элементу #mse2_mfilter добавляется класс loading когда идёт загрузка контента.
Но в этом случае блок #before-load нужно расположить в #mse2_mfilter.
Как я понимаю на этой строке и всё завязано?
Будет также:
Только изначально #before-load должен быть скрыт:
В коде да, реализовано через изменение уровня прозрачности элемента.
Результат mFilter2 определяется с помощью элемента #mse2_results. Он расположен в чанке tpl.mFilter2.outer:
В этом случае оборачиваем результат и помещаем в него элемент #before-load:
[[mFilter2?
&tplOuter=`tpl.mFilter2.outer1`
]]
Заранее спасибо
Все работает!