ساخت افکت نور حرکت افقی با CSS
افکت نور حرکت افقی (horizontal light sweep یا shimmer) یکی از جلوههای محبوب در طراحی وب است که باعث میشود عناصر صفحه مثل دکمهها، کارتها یا متنها زندهتر به نظر برسند. در این مقاله به صورت گامبهگام چند روش مختلف برای ایجاد این افکت با CSS، نکات بهینهسازی و دسترسی (accessibility) میپردازیم.
چرا از افکت نور حرکت افقی استفاده کنیم؟
- جلب توجه به عناصر مهم (CTA، بنرها).
- ایجاد حس تعامل و پویا بودن بدون جاوااسکریپت.
- قابل ترکیب با سایر افکتها مانند سایه و گرادیانت.
روش پایه: استفاده از pseudo-element و گرادیان
<!-- HTML -->
<button class="shimmer-btn">Buy Now</button>
/* CSS */.shimmer-btn{
position: relative;
overflow: hidden;
padding: 12px 24px;
border: none;
background: #0b74de;
color: white;
font-weight: 600;
border-radius: 6px;
}
.shimmer-btn::before{
content: "";
position: absolute;
top: -50%;
left: -30%;
width: 40%;
height: 200%;
background: linear-gradient(90deg, rgba(255,255,255,0) 0%, rgba(255,255,255,0.6) 50%, rgba(255,255,255,0) 100%);
transform: rotate(20deg);
animation: shimmer 1.6s linear infinite;
}
@keyframes shimmer{
0% { transform: translateX(-150%) rotate(20deg); }
100% { transform: translateX(350%) rotate(20deg); }
}توضیح: در این مثال از یک pseudo-element (::before) با گرادیان سفید شفاف استفاده شده تا هالهٔ نور به صورت مورب از چپ به راست حرکت کند. با استفاده از transform و translateX انیمیشن بهصورت روان اجرا میشود. overflow: hidden از خارج شدن هاله جلوگیری میکند.
بهینهسازی برای عملکرد
برای حفظ کارایی، بهتر است از پراپرتیهایی استفاده کنید که GPU را فعال میکنند و repaint سنگین ایجاد نمیکنند.
.shimmer-btn::before{
will-change: transform;
backface-visibility: hidden;
/* بقیهی سبکها همانند قبل */}توضیح: will-change به مرورگر اعلام میکند که transform قرار است تغییر کند؛ این کار میتواند باعث اختصاص منابع GPU شود و انیمیشن را روانتر کند. backface-visibility و استفاده از transform بهجای تغییر موقعیت با left/top کمک میکند تا repaint کمتر رخ دهد.
افکت نور برای متن (شیمِر متن)
<h1 class="shimmer-text">Loading...</h1>
/* CSS */.shimmer-text{
font-size: 48px;
font-weight: 700;
background: linear-gradient(90deg, #444 40%, #fff 50%, #444 60%);
background-size: 200% 100%;
-webkit-background-clip: text;
background-clip: text;
color: transparent;
animation: text-shimmer 1.8s linear infinite;
}
@keyframes text-shimmer{
0% { background-position: -100% 0; }
100% { background-position: 200% 0; }
}توضیح: این روش از background-clip: text و گرادیان متحرک استفاده میکند تا هالهٔ نور روی متن کشیده شود. رنگ متن transparent است و گرادیان جای آن را پر میکند. background-size بزرگ شده تا حرکت قابل مشاهده باشد.
استفاده از mask و SVG برای کنترل دقیقتر
برای مواردی که نیاز به کنترل شکل یا محدودهٔ افکت داریم، میتوان از mask یا SVG استفاده کرد. بهعنوان مثال، برای کارتهایی با گوشههای گرد یا شکل پیچیده مناسب است.
<div class="card">
<div class="card-inner">Content</div>
</div>
/* CSS */.card{
position: relative;
width: 300px;
height: 180px;
background: #222;
border-radius: 12px;
overflow: hidden;
}
.card::after{
content: "";
position: absolute;
inset: 0;
background: linear-gradient(90deg, rgba(255,255,255,0) 0%, rgba(255,255,255,0.18) 50%, rgba(255,255,255,0) 100%);
transform: translateX(-150%) rotate(10deg);
animation: sweep 1.6s linear infinite;
mask-image: radial-gradient(circle at center, black 60%, transparent 100%);
}
@keyframes sweep{
0% { transform: translateX(-150%) rotate(10deg); }
100% { transform: translateX(250%) rotate(10deg); }
}توضیح: در این نمونه از mask-image برای محدود کردن ناحیهٔ افکت استفاده شده تا هالهٔ نور فقط در یک محدوده مشخص نمایش داده شود. این روش به خصوص برای طراحیهای غیرمستطیلی مفید است.
پیشبینی برای کاربران با reduced motion
مهم است که برای کاربرانی که motion را محدود کردهاند، انیمیشن را غیرفعال یا ساده کنیم.
@media (prefers-reduced-motion: reduce){
.shimmer-btn::before,
.shimmer-text,
.card::after {
animation: none;
background: none; /* یا یک استایل جایگزین استاتیک */ }
}توضیح: این کوئری رسانهای کاربرانی که motion را غیرفعال کردهاند تشخیص میدهد و از ایجاد حرکت ناخواسته جلوگیری میکند. همیشه به دسترسی توجه کنید.
موارد استفاده و نکات کاربردی
- دکمههای مهم (CTA): جلب توجه بدون اغراق.
- Placeholderهای بارگذاری: شبیهسازی loading shimmer برای محتواهایی که هنوز بارگذاری نشدهاند.
- متنهای برجسته: استفاده از background-clip برای تایپوگرافی اثرگذار.
جدول مقایسه تکنیکها
| روش | مزایا | معایب |
|---|---|---|
| pseudo-element + gradient | ساده، سازگاری بالا | نیاز به tuning برای سازگاری با اندازهها |
| background-clip: text | ایدهآل برای متن | در مرورگرهای قدیمی متن fallback نیاز دارد |
| mask/SVG | کنترل دقیق روی شکل | پیچیدگی بالاتر |
نکات پیشرفته و خطاهای رایج
- از تغییرات large layout (مثل changing left/top) پرهیز کنید و ترجیحا از transform استفاده کنید.
- مراقب ترکیب با blend-modeها باشید؛ گاهی میتواند رنگها را ناخواسته تغییر دهد.
- برای تصاویر پسزمینه، gradient را در یک pseudo-element اعمال کنید تا محتوای اصلی دستنخورده بماند.
نمونه نهایی بهینه شده
<button class="shimmer-btn optimized">Subscribe</button>
.optimized::before{
content:"";
position:absolute;
inset: -20% -40% -20% -40%;
background: linear-gradient(90deg, rgba(255,255,255,0) 0%, rgba(255,255,255,0.5) 50%, rgba(255,255,255,0) 100%);
transform: translateX(-100%) rotate(15deg);
animation: shimmer 1.4s linear infinite;
will-change: transform;
pointer-events: none;
}توضیح: در این نسخه inset باعث میشود pseudo-element منابع کمتری مصرف کند و اندازهٔ آن طوری تنظیم شده که حرکت خارج از مرزها بهتر نمایش داده شود. pointer-events: none از گرفتن کلیک جلوگیری میکند. will-change و transform برای بهبود عملکرد هستند.
خلاصه: با ترکیب گرادیان، pseudo-elementها، transform و رعایت دسترسی میتوانید افکت نور حرکت افقی زیبا و بهینهای بسازید. همیشه تست روی دستگاههای واقعی، توجه به کاهش حرکت و جلوگیری از repaintهای سنگین را فراموش نکنید.
آیا این مطلب برای شما مفید بود ؟




