Анимация загрузки (spinner)
CSS-спиннер на чистом CSS без изображений и JS — кружок с вращающимся бортиком через
border+animation.
Задача
Нужно показать индикатор загрузки во время асинхронной операции. Спиннер должен быть лёгким, не требовать JS и легко встраиваться в кнопки и оверлеи.
Решение
Базовый спиннер:
<div class="spinner" role="status" aria-label="Загрузка..."></div>
.spinner {
width: 36px;
height: 36px;
border: 3px solid #e2e8f0; /* светлая подложка */
border-top-color: #3b82f6; /* цветной «бегущий» участок */
border-radius: 50%;
animation: spin 0.8s linear infinite;
}
@keyframes spin {
to { transform: rotate(360deg); }
}
Спиннер внутри кнопки:
<button class="btn btn--loading" disabled>
<span class="btn__spinner"></span>
Сохранение...
</button>
.btn {
display: inline-flex;
align-items: center;
gap: 8px;
padding: 10px 20px;
background: #3b82f6;
color: #fff;
border: none;
border-radius: 6px;
cursor: pointer;
font-size: 0.9rem;
}
.btn--loading { opacity: 0.7; cursor: not-allowed; }
.btn__spinner {
width: 16px;
height: 16px;
border: 2px solid rgba(255,255,255,0.4);
border-top-color: #fff;
border-radius: 50%;
animation: spin 0.8s linear infinite;
flex-shrink: 0;
}
@keyframes spin { to { transform: rotate(360deg); } }
Fullscreen overlay:
<div class="loading-overlay" id="overlay">
<div class="spinner spinner--lg"></div>
</div>
.loading-overlay {
position: fixed;
inset: 0;
background: rgba(255,255,255,0.8);
display: flex;
align-items: center;
justify-content: center;
z-index: 999;
}
.spinner--lg { width: 56px; height: 56px; border-width: 4px; }
const overlay = document.getElementById('overlay');
async function loadData() {
overlay.hidden = false;
try {
await fetchData;
} finally {
overlay.hidden = true;
}
}
Ключевые моменты
border+border-top-color— классический трюк: три стороны серые, одна цветная; вращение даёт эффект спиннера.animation: spin 0.8s linear infinite—linearважен, иначе вращение не будет равномерным.role="status"+aria-label— доступность: screen reader объявит «загрузка».flex-shrink: 0на спиннере в кнопке — предотвращает сжатие при малой ширине кнопки.
Варианты
- Dots spinner (три точки):
@keyframes bounceна трёх<span>с разнойanimation-delay. - SVG spinner:
<circle stroke-dasharray>+ анимацияstroke-dashoffset— более гибкий. - Skeleton — предпочтительнее спиннера для контентных областей; см. Скелетон загрузки.