ساخت Skeleton Loading با CSS
Skeleton loading یا اسکلتی بارگذاری، یک الگوی رابط کاربری است که به جای نمایش یک لودر چرخان، نمایی از اسکلت صفحه را به کاربر نشان میدهد تا حس سرعت و پایداری بارگذاری را افزایش دهد. این روش مخصوصاً برای صفحات محتوا-محور (مانند فیدها، پروفایلها یا کارتهای محصول) بسیار موثر است زیرا پیشنمایش ساختار محتوا را قبل از دریافت داده کامل نمایش میدهد.
چرا از Skeleton به جای Spinner استفاده کنیم؟
- ادراک سرعت بالاتر: کاربر ساختار نهایی را زودتر میبیند.
- کاهش جابجایی عناصر: هنگام بارگذاری دادهها، کمتر رفتار پرشدار خواهیم داشت.
- قابلیت سفارشیسازی آسان با CSS و ترکیب با حالت تاریک.
المانهای اصلی یک Skeleton خوب
- ابعاد و فاصله مشابه محتوای واقعی
- رنگ و کنتراست ملایم (برای جلوگیری از پرت توجه شدن)
- حرکت ظریف (shimmer) که بهصورت اختیاری و مطابق prefers-reduced-motion باشد
- دسترسیپذیری: استفاده از ARIA مانند
aria-busyو پنهانسازی محتوای واقعی تا هنگام آماده شدن
مثال پایه: HTML و CSS ساده
<div class="card-skeleton">
<div class="avatar"></div>
<div class="lines">
<div class="line short"></div>
<div class="line"></div>
<div class="line long"></div>
</div>
</div>
.card-skeleton{
display:flex;
gap:12px;
align-items:flex-start;
padding:12px;
width:320px;
background:#fff;
border-radius:8px;
box-shadow:0 1px 3px rgba(0,0,0,0.06);
}
.card-skeleton .avatar{
width:56px;
height:56px;
border-radius:50%;
background:#e9e9ef;
flex:0 0 56px;
}
.card-skeleton .lines{
flex:1;
}
.card-skeleton .line{
height:12px;
background:#e9e9ef;
margin-bottom:10px;
border-radius:6px;
}
.card-skeleton .line.short{ width:40%; }
.card-skeleton .line.long{ width:90%; }این کد یک کارت اسکلتی ساده میسازد: آواتار دایرهای و سه خط متن. رنگ پسزمینه با سایه ملایم تعیین شده تا شبیه فضای محتوا باشد. این پیادهسازی هیچ انیمیشنی ندارد و مناسب زمانی است که میخواهیم ساده و سریع نمایش دهیم.
اضافه کردن افکت Shimmer (درخشش)
.card-skeleton .line{
position:relative;
overflow:hidden;
background:#e9e9ef;
}
.card-skeleton .line::after{
content:"";
position:absolute;
top:0;
left:-150%;
height:100%;
width:150%;
background:linear-gradient(90deg, rgba(255,255,255,0) 0%, rgba(255,255,255,0.6) 50%, rgba(255,255,255,0) 100%);
animation:shimmer 1.2s linear infinite;
}
@keyframes shimmer{
to { left:100%; }
}
/* احترام به ترجیح کاربر برای کاهش حرکت */@media (prefers-reduced-motion: reduce){
.card-skeleton .line::after{
animation:none;
}
}در این نسخه از یک pseudo-element (::after) استفاده شده تا گرادیان متحرک (shimmer) روی خطوط اجرا شود. با prefers-reduced-motion مطمئن میشویم که کاربران حساس به حرکت تجربهی مناسبتری داشته باشند.
نسخه پیشرفته: استفاده از CSS Variables و حالت تاریک
:root{
--skeleton-bg: #e9e9ef;
--skeleton-highlight: rgba(255,255,255,0.6);
--skeleton-duration: 1.2s;
}
[data-theme="dark"]{
--skeleton-bg: #2a2a2f;
--skeleton-highlight: rgba(255,255,255,0.04);
}
.skel{
background:var(--skeleton-bg);
position:relative;
overflow:hidden;
}
.skel::after{
content:"";
position:absolute;
inset:0;
background:linear-gradient(90deg, transparent 0%, var(--skeleton-highlight) 50%, transparent 100%);
transform:translateX(-100%);
animation:sk-anim var(--skeleton-duration) linear infinite;
}
@keyframes sk-anim{ to{ transform:translateX(100%); } }در این نسخه از متغیرهای CSS برای تغییر آسان رنگها و زمان انیمیشن استفاده شده و پشتیبانی از تم تاریک با تغییر تنها متغیرها امکانپذیر است. این الگو قابل اعمال روی هر عنصر با کلاس skel است.
دسترسیپذیری و جایگزینی با محتوای واقعی
برای دسترسپذیر بودن باید هنگام بارگذاری از ARIA استفاده کنیم و محتوای واقعی را تا زمان آماده شدن پنهان کنیم. نمونهای از الگوی تعویض:
<div id="profile" aria-busy="true">
<!-- skeleton -->
<div class="profile-skeleton">...</div>
<!-- real content, initially hidden -->
<div class="profile-content" hidden>...</div>
</div>
<script>
fetch('/api/profile').then(r=>r.json()).then(data=>{
document.querySelector('.profile-skeleton').remove();
const content = document.querySelector('.profile-content');
// fill content with data...
content.hidden = false;
document.getElementById('profile').setAttribute('aria-busy', 'false');
});
</script>در این مثال، از aria-busy برای اطلاعرسانی به تکنولوژیهای کمکی استفاده شده و عناصر واقعی تا زمان پر شدن دادهها با hidden پنهان ماندهاند. هنگام دریافت داده، اسکلت حذف و محتوای واقعی نمایش داده میشود.
بهینهسازی عملکرد
- انیمیشنها را ساده نگهدارید (فقط از transform/opacity استفاده کنید تا رندر سریع بماند).
- در صورت تعداد زیاد اسکلتها، از تصویربرداری CSS یا SVG برای کاهش DOM استفاده کنید.
- برای لیستهای طولانی از placeholder خطی یا lazy-loading استفاده کنید تا اولین نمایش سریعتر شود.
نمونه جدول مقایسه تنظیمات Skeleton
| ویژگی | پیشنهاد | توضیح |
|---|---|---|
| رنگ | #e9e9ef / #2a2a2f | کنتراست ملایم متناسب با تم |
| مدت انیمیشن | 0.8s – 1.5s | کوتاه برای حس طبیعی، نه تند |
| حرکت | linear یا ease | حرکت پیوسته بهتر از توقف و شروع است |
جمعبندی و نکات عملی
Skeleton Loading با CSS یک ابزار قدرتمند برای بهبود تجربه کاربری است. با رعایت اصول ساده مثل شباهت به ساختار نهایی، احترام به تنظیمات حرکت کاربران و بهینهسازی انیمیشنها میتوانید تجربهای سریع و دلپذیر ارائه دهید. ترکیب CSS Variables، حالت تاریک و ARIA باعث میشود اسکلت شما هم زیبا و هم قابلدسترس باشد.
اگر میخواهید میتوانم یک کامپوننت اسکلت آماده با قابلیت سفارشیسازی (عرض، ارتفاع، تعداد خطوط و شِیپها) به صورت یک فایل CSS و مثال HTML برای پروژهتان آماده کنم.
آیا این مطلب برای شما مفید بود ؟




