ساخت Countdown Timer با CSS
شمارش معکوس (Countdown Timer) ابزار متداولی در وبسایتها و اپلیکیشنهاست؛ برای لانچ محصول، زمانبندی رویداد، پیشنهادات زماندار و نمایش بارگزاری. در این مقاله با روشهای مختلف ساخت Countdown Timer با تمرکز بر CSS آشنا میشویم: از راهکارهای CSS-only (محدود ولی سبک) تا پیادهسازی حرفهای با ترکیب CSS + JavaScript که در عمل کاربردیتر است.
چرا فقط CSS؟ و چه محدودیتهایی دارد
CSS-only مناسب انیمیشنهای زمانبندی ثابت است؛ یعنی وقتی مدت زمان معین (مثلاً 10 ثانیه یا 2 دقیقه) را میدانیم و نیاز به یک نشاندهنده بصری داریم. اما اگر بخواهیم تا تاریخ مشخصی در آینده دقیقاً بشماریم (مثلاً تا 2026-01-01)، یا شمارش هنگام ریفرش صفحه باقی بماند، یا امکان pause/resume و همگامسازی با سرور نیاز باشد، حتماً باید از JavaScript یا سرور کمک بگیریم.
موارد استفاده
- بارگذاری یا splash screen با طول ثابت
- نمایش پایان زمان یک پیشنهاد (فقط بصری برای مدت ثابت)
- آموزش و دموهای تعاملی که نیاز به زمانبندی ساده دارند
- پیشنیاز برای پیادهسازیهای پیچیدهتر با JS
نمونه 1 — Countdown ساده فقط با CSS (نمایش بصری طول ثابت)
<!-- HTML -->
<div class="css-only-countdown" aria-hidden="true">
<div class="bar">
<div class="fill"></div>
</div>
<div class="label">10s</div>
</div>
/* CSS */.css-only-countdown{width:220px;font-family:system-ui,Segoe UI,Roboto,'Helvetica Neue',Arial}
.bar{width:100%;height:18px;background:#eee;border-radius:10px;overflow:hidden;margin-bottom:8px}
.fill{height:100%;background:linear-gradient(90deg,#4caf50,#2196f3);width:100%;
animation: shrink 10s linear forwards}
.label{text-align:center;color:#333;font-weight:600}
@keyframes shrink{from{width:100%}to{width:0%}}توضیح: کد فوق یک نوار پیشرفت (progress bar) را با انیمیشنی تعریف میکند که عرض عنصر .fill از 100% به 0% طی 10 ثانیه کاهش مییابد. متن “10s” صرفاً نمایش بصری است و خودِ مقدار زمانی بهصورت داینامیک تغییر نمیکند. این روش برای حالتهایی که مدت ثابتی داریم مناسب است اما شمارش عددی واقعی یا همگامسازی با ساعت را انجام نمیدهد.
چرا این روش ممکن است کافی نباشد
- مقدار متنی ثابت است؛ پس نباید از آن برای اعلام دقیق زمان به کاربران استفاده کنید.
- قابلیت pause/resume یا همگامسازی با سرور وجود ندارد.
- در صورت رفرش صفحه، انیمیشن از ابتدا شروع میشود.
روش پیشنهادی — Countdown واقعی با CSS برای استایل و JavaScript برای منطق
ترکیب CSS برای ظاهر و انیمیشن و JavaScript برای محاسبه دقیق زمان، بهترین نتیجه را میدهد: قابل دسترس، دقیق، قابل توقف و همگام شونده.
<!-- HTML -->
<div id="countdown" class="countdown" role="timer" aria-live="polite">
<div class="part"><span class="num" data-unit="days">0</span><span class="label">روز</span></div>
<div class="part"><span class="num" data-unit="hours">0</span><span class="label">ساعت</span></div>
<div class="part"><span class="num" data-unit="minutes">0</span><span class="label">دقیقه</span></div>
<div class="part"><span class="num" data-unit="seconds">0</span><span class="label">ثانیه</span></div>
</div>
/* CSS */.countdown{display:flex;gap:12px;font-family:system-ui,Arial;padding:8px;background:#fff;border-radius:8px;align-items:center}
.part{background:#f5f7fb;padding:10px 12px;border-radius:6px;text-align:center;min-width:64px}
.num{display:block;font-size:1.3rem;font-weight:700;color:#111}
.label{display:block;font-size:0.8rem;color:#666;margin-top:4px}توضیح: ساختار HTML چهار قسمت برای روز/ساعت/دقیقه/ثانیه دارد. CSS ظاهر کارت و تایپوگرافی را تنظیم میکند؛ اما بروزرسانی مقادیر با JavaScript انجام میشود (کد JS در ادامه).
// JavaScript
(function(){
// هدف: شمارش معکوس تا تاریخ مشخص
const target = new Date('2025-12-31T23:59:59Z'); // نمونه
const el = document.getElementById('countdown');
const units = { days:86400000, hours:3600000, minutes:60000, seconds:1000 };
function update(){
const now = new Date();
let diff = Math.max(0, target - now);
for(const key of ['days','hours','minutes','seconds']){
const val = Math.floor(diff / units[key]);
el.querySelector(`[data-unit="${key}"]`).textContent = String(val).padStart(2,'0');
diff -= val * units[key];
}
if (target - now <= 0) {
clearInterval(timer);
// امکان اضافه کردن رفتار پایان: نمایش پیام یا فعالسازی چیزی
}
}
update();
const timer = setInterval(update, 1000);
})();توضیح: این قطعه JavaScript هر ثانیه اختلاف زمانی بین زمان اکنون و target را محاسبه و به چهار بخش تبدیل میکند، سپس مقدار عناصر DOM مربوطه را با padStart به صورت دو رقمی بهروزرسانی میکند. در پایان که زمان به صفر رسید، اینتروال متوقف میشود و میتوان رفتار دلخواه را اجرا کرد.
جدول مقایسه: CSS-only vs CSS+JS
| ویژگی | CSS-only | CSS + JavaScript |
|---|---|---|
| دقت زمانی | پایین (فقط مدت ثابت) | بالا (قابل همگامسازی) |
| قابلیت تعاملی | خیر | بله (pause, resume, sync) |
| پیچیدگی | کم | متوسط |
| دسترسی (a11y) | ضعیف | قابل بهبود (aria/live) |
نکات حرفهای و بهینهسازی
- برای دسترسپذیری از aria-live و role=”timer” استفاده کنید تا صفحهخوانها تغییر زمان را اطلاع دهند.
- اگر نیاز به شمارش تا زمان سرور دارید، از API سرور زمان فعلی را بگیرید تا اختلاف ساعت کلاینت مشکلساز نشود.
- برای صرفهجویی در منابع، اگر تب مرورگر غیر فعال است، requestAnimationFrame را جایگزین setInterval نکنید؛ اما میتوانید با Page Visibility API اقدام به توقف/شروع کنید.
- برای انیمیشنهای صاف از CSS transitions یا transform استفاده کنید و از properties سنگین مثل width یا box-shadow کمتر استفاده کنید.
دسترسی و بینالمللیسازی
برای نمایش اعداد فارسی، از فرمتکنندههای جاوااسکریپت یا جایگزینی متن استفاده کنید. همچنین برچسبها را قابل ترجمه نگه دارید و زمانها را به فرمت منطقی منطقه زمانی کاربر تبدیل کنید.
جمعبندی
اگر هدف شما نمایش یک نشاندهنده بصری با مدت ثابت است، CSS-only ساده و سبک است. اما در بیشتر پروژههای واقعی که نیاز به دقت، تعامل و همگامسازی دارند، بهترین راه ترکیب CSS برای ظاهر و JavaScript برای منطق زمان است. نکته مهم رعایت دسترسی و هماهنگی زمان با سرور در سناریوهای حساس است.
در صورت تمایل میتوانم یک نسخه کامل و آماده برای استفاده (فایلهای مجزا، پکیج کوچک CSS و JS و قابلیت pause/resume و callback هنگام پایان) برای شما آماده کنم.
آیا این مطلب برای شما مفید بود ؟





