Скелетон-экраны — эффект загрузки, улучшающий восприятие интерфейса
Кратко: Скелетон-экраны имитируют структуру контента до его полной загрузки. Они улучшают восприятие скорости, снижают Cumulative Layout Shift (CLS) и повышают удержание пользователей. В статье — пошагово: дизайн макета, HTML/CSS/JS реализация, адаптивность, контроль времени и чек-листы для дизайнеров и разработчиков.
Важно: скелетон-экраны не ускоряют сеть — они управляют ожиданием пользователя и уменьшают визуальные сдвиги.

Проектирование макета страницы

Проектирование макета помогает чётко задать ожидания от интерфейса. Поставьте цель, определите основной каркас страницы, добавьте необходимые экраны и продумайте доступность и адаптивность. Для примера используем простой профиль с обложкой, аватаром, текстом и кнопками действий.
Когда макет готов (на бумаге или в Figma/Adobe XD), переходите к подготовке HTML-структуры.
Базовая структура HTML
Создайте файл index.html и поместите макет внутри родительского
Примечание: подключите style.css и script.js в шапке/внизу index.html.
Skeleton Screen Loading Effect
John Doe
Software Engineer @ Google || Full Stack Developer || Self Taught
Bengaluru, Karnataka, India • Contact info
Основные стили страницы
Задайте глобальные атрибуты: margin, font-family, цвет. Это основа читабельности и контраста для скелетонов.
body {
margin: 0;
font-family: Arial, sans-serif;
color: rgba(255, 255, 255, 0.9);
}Добавляем эффект загрузки (shimmer)
Чтобы создать эффект мерцания, используйте псевдоэлемент ::after у класса skeleton. Он движется слева направо и имитирует сканирующий свет.
.skeleton {
position: relative;
width: max-content;
overflow: hidden;
border-radius: 4px;
background-color: #1e2226 !important;
color: transparent !important;
border-color: #1e2226 !important;
user-select: none;
cursor: default;
}
.skeleton img {
opacity: 0;
}
.skeleton::after {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
transform: translateX(-100%);
background-image: linear-gradient(
90deg,
rgba(255, 255, 255, 0) 0,
rgba(255, 255, 255, 0.2) 20%,
rgba(255, 255, 255, 0.5) 60%,
rgba(255, 255, 255, 0)
);
animation: shimmer 2s infinite;
content: '';
}
@keyframes shimmer {
100% {
transform: translateX(100%);
}
}
Стили для изображений и контейнера
Не забудьте overflow: hidden у блоков с изображениями — это предотвращает нежелательные «выпадения» элементов при скейлинге.
img {
width: 100%;
vertical-align: middle;
}
.profile-container {
width: 95%;
max-width: 780px;
margin: 0 auto;
border-radius: 8px;
margin-top: 32px;
background-color: #1e2226;
overflow: hidden;
position: relative;
}
.cover-img {
width: 100%;
overflow: hidden;
background-color: #1e2226;
aspect-ratio: 4 / 1;
}
.profile-img {
border-radius: 50%;
width: 160px;
height: 160px;
border: 4px solid #000;
background-color: #1e2226;
margin: 0 auto;
position: relative;
overflow: hidden;
bottom: 100px;
}Адаптивность
Используйте media queries для корректного отображения на небольших экранах.
@media (max-width: 560px) {
.profile-img {
width: 100px;
height: 100px;
bottom: 60px;
}
}Стили текста
Скрытые (skeleton) текстовые элементы должны сохранять размеры блоков, чтобы избежать CLS.
.profile-text {
margin-top: -80px;
padding: 0 16px;
}
.profile-text h1 {
margin-bottom: 0;
font-size: 24px;
overflow: hidden;
}
.profile-text p {
margin: 4px 0;
overflow: hidden;
}
.profile-text h5 {
margin-top: 4px;
font-size: 14px;
margin-bottom: 8px;
font-weight: 400;
color: #ffffff99;
overflow: hidden;
}
.profile-text a {
color: #70b5f9;
font-size: 14px;
text-decoration: none;
font-weight: 600;
}
.profile-text a:hover {
color: #70b5f9;
text-decoration: underline;
}Стили CTA
Кнопки действий должны быть заметными и оставаться того же размера в состоянии skeleton, чтобы избежать смещения при подстановке реального контента.
.profile-cta {
padding: 16px 16px 32px;
display: flex;
}
.profile-cta a {
padding: 6px 16px;
border-radius: 24px;
text-decoration: none;
display: block;
}
.message-btn {
background-color: #70b5f9;
color: #000;
}
.more-btn {
color: inherit;
border: 1px solid rgba(255, 255, 255, 0.9);
margin-left: 8px;
}
Отключение эффекта skeleton через JavaScript
Когда реальные данные готовы, удалите класс skeleton. Анимация по умолчанию бесконечна — ограничьте её временем ожидания, например 4000 мс.
Примечание: в реальных приложениях лучше отключать скелетон по событию завершения загрузки (fetch/Promise), а не по таймеру.
const skeletons = document.querySelectorAll('.skeleton')
skeletons.forEach((skeleton) => {
setTimeout(() => {
skeleton.classList.remove('skeleton')
}, 4000)
})
Когда использовать скелетон-экраны и как они работают
Скелетон-экраны полезны, когда структура контента предсказуема: карточки, списки, профили, статьи. Они создают иллюзию скорости, минимизируют визуальные сдвиги и повышают отзывчивость интерфейса. На крупных сайтах (Google, Facebook, Slack) скелетоны распространены именно по этим причинам.
Мини-методология внедрения
- Спроектируйте каркас для каждого ключевого шаблона контента.
- Добавьте класс skeleton ко всем элементам-заменителям.
- Реализуйте CSS-анимацию shimmer и фиксированные размеры блоков.
- Удаляйте класс skeleton по завершении загрузки данных (событие fetch/await), не по таймеру.
- Тестируйте на медленных соединениях и в узких экранах.
Чек-лист: роли и задачи
Для дизайнера
- Определить карточки/блоки, требующие скелетон-заменителя.
- Задать размеры, отступы и порядок элементов (чтобы избежать CLS).
- Подготовить версии для настольных и мобильных макетов.
Для фронтенд-разработчика
- Добавить класс skeleton в шаблоны рендеринга.
- Реализовать CSS-анимацию и обеспечить скрытие реального контента (opacity).
- Отключать skeleton по Promise/response, а не только по таймеру.
- Проверить производительность и отрисовку при отключённом JS.
Ментальные модели и правила, которые работают
- Правило «сохраняй размеры»: всегда резервируйте место под изображение/текст — это предотвращает CLS.
- Правило «по событию, а не по времени»: отключение skeleton по событию загрузки надёжнее таймера.
- Правило «минимального контраста»: скелетоны должны быть нейтральными, не отвлекать от ожидания.
Диаграмма принятия решения
flowchart TD
A[Нужно ли показывать skeleton?]
A -->|Да — структура предсказуема| B[Показывать skeleton]
A -->|Нет — структура неизвестна| C[Показывать индикатор загрузки]
B --> D[Резервировать размеры и отрисовать skeleton]
D --> E[Отключать skeleton по событию загрузки]
C --> F[Использовать спиннер или прогресс-бар]Критерии приёмки
- Скрин: элементы не смещаются при подстановке данных (CLS минимален).
- UX: пользователи видят структуру страницы в первые 200–500 мс (косвенно — субъективно улучшает восприятие).
- Технически: skeleton отключается по успешному завершению запроса, а не исключительно по таймеру.
Тест-кейсы
- Медленное соединение: данные загружаются >2 с — скелетон остаётся до получения ответа.
- Быстрое соединение: данные загружаются <200 мс — скелетон исчезает без заметного мерцания.
- Ошибка загрузки: на ошибке показывать состояние ошибки вместо скелетона.
- JS отключён: структура должна быть минимально читаемой — обеспечить graceful degradation.
Краткий словарь
- Скелетон: визуальный замещающий элемент, повторяющий структуру контента до загрузки.
- Shimmer: анимация мерцания, имитирующая «сканирующий» свет.
- CLS (Cumulative Layout Shift): совокупное смещение макета — метрика визуальной стабильности.
Итог
Скелетон-экраны — недооценённый инструмент улучшения UX: они не ускоряют сеть, но управляют ожиданиями, уменьшают CLS и делают интерфейсы приятнее. Внедряйте их, сохраняя размеры блоков, отключайте по событию загрузки и тестируйте на разных скоростях сети.
Дополнительно: используйте чек-листы из статьи, чтобы сократить баги и обеспечить единообразие между дизайном и реализацией.