Skeleton Loading в React без Tailwind: как сделать скелетон
Skeleton Loading — это техника отображения заглушек ("скелетов") вместо контента, который ещё загружается. Такая визуализация делает интерфейс более отзывчивым и предсказуемым, снижает восприятие задержки и улучшает пользовательский опыт. В этой статье мы разберём, как реализовать Skeleton UI в React без использования CSS-фреймворков вроде Tailwind.
Почему Skeleton лучше обычного спиннера
Когда пользователь видит крутящийся индикатор загрузки, он не понимает, что конкретно загружается. Skeleton показывает будущую структуру интерфейса — прямоугольники, кружки, полосы, имитирующие текст или аватары. Это даёт понимание, что появится, и визуально ускоряет процесс ожидания.
Создание базового Skeleton-компонента
Создадим простой переиспользуемый компонент, который будет отображать "пульсирующий" блок-заглушку с заданными размерами.
// components/Skeleton.js
import React from 'react';
import './Skeleton.css';
export function Skeleton({ width = '100%', height = '16px', borderRadius = '4px', style = {} }) {
return (
<div
className="skeleton"
style={{
width,
height,
borderRadius,
...style,
}}
></div>
);
}
Создадим CSS-анимацию для эффекта пульсации:
/* Skeleton.css */
.skeleton {
background-color: #e0e0e0;
position: relative;
overflow: hidden;
}
.skeleton::after {
content: '';
position: absolute;
top: 0;
left: -100%;
height: 100%;
width: 100%;
background: linear-gradient(to right, transparent, rgba(255, 255, 255, 0.4), transparent);
animation: shimmer 1.2s infinite;
}
@keyframes shimmer {
100% {
left: 100%;
}
}
Такой компонент можно использовать в любых местах интерфейса. Он не зависит от сторонних библиотек и легко настраивается через props.
Пример использования в карточке пользователя
Теперь создадим компонент, который имитирует карточку пользователя в состоянии загрузки. Здесь мы используем скелетоны для аватара и текстовых блоков:
// components/UserCardSkeleton.js
import React from 'react';
import { Skeleton } from './Skeleton';
export function UserCardSkeleton() {
return (
<div style={{ display: 'flex', alignItems: 'center', padding: '12px', border: '1px solid #ccc', borderRadius: '8px', marginBottom: '8px' }}>
<Skeleton width="48px" height="48px" borderRadius="50%" style={{ marginRight: '16px' }} />
<div style={{ flex: 1 }}>
<Skeleton width="60%" height="16px" style={{ marginBottom: '8px' }} />
<Skeleton width="40%" height="14px" />
</div>
</div>
);
}
В этом примере компонент UserCardSkeleton
отображает пульсирующую серую заглушку для аватара и двух строк текста. Такие блоки хорошо передают структуру будущего контента и не перегружают интерфейс.
Подключение в компонент с состоянием загрузки
Теперь подключим скелетон в основной компонент, который получает данные пользователя. Пока данные загружаются — показываем UserCardSkeleton
, после — полноценную карточку:
import React, { useEffect, useState } from 'react';
import { UserCardSkeleton } from './UserCardSkeleton';
export function UserCard() {
const [user, setUser] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
fetch('/api/user')
.then(res => res.json())
.then(data => {
setUser(data);
setLoading(false);
});
}, []);
if (loading) return <UserCardSkeleton />;
return (
<div style={{ display: 'flex', alignItems: 'center', padding: '12px', border: '1px solid #ccc', borderRadius: '8px' }}>
<img
src={user.avatar}
alt={user.name}
style={{ width: '48px', height: '48px', borderRadius: '50%', marginRight: '16px' }}
/>
<div>
<p style={{ fontWeight: 'bold', margin: 0 }}>{user.name}</p>
<p style={{ color: '#666', margin: 0 }}>{user.email}</p>
</div>
</div>
);
}
Здесь мы эмулируем API-запрос с задержкой. Пока данные не пришли, отображается компонент UserCardSkeleton
, который занимает нужное место и помогает избежать "прыжков" интерфейса при появлении настоящих данных.
Заключение
Skeleton-загрузки — это современный способ обработки ожидания данных в UI. Они улучшают восприятие скорости, делают интерфейс более профессиональным и визуально стабильным. Вы можете реализовать их вручную с помощью CSS-анимаций или использовать готовые библиотеки, если нужна гибкость и расширенные возможности.
Настроить мониторинг за 30 секунд
Надежные оповещения о даунтаймах. Без ложных срабатываний