ویژگی تصویر

افکت تایپ ماشینی با CSS

  /  CSS   /  افکت تایپ ماشینی با CSS
بنر تبلیغاتی الف

افکت تایپ ماشینی (typewriter effect) یکی از افکت‌های محبوب در طراحی وب است که متن را به‌صورت حرف به حرف نمایش می‌دهد و حس نوشتن با ماشین‌تحریر یا صفحه‌کلید را القا می‌کند. این افکت معمولاً برای هدرها، صفحه فرود (landing page)، معرفی محصول یا جلب توجه کاربر به متن‌های مهم استفاده می‌شود. در این مقاله به پیاده‌سازی با CSS خالص، بهبودهای عملی، نکات مربوط به فارسی (RTL) و دسترسی‌پذیری خواهیم پرداخت.

روش ساده با CSS خالص (basic CSS-only)

<div class="typewriter">
  <h1 class="text">Hello World</h1>
</div>

.typewriter {
  overflow: hidden;               /* hide overflowing text */  border-right: .12em solid #000; /* cursor */  white-space: nowrap;            /* keep text on one line */  font-family: monospace;         /* consistent character width */  width: 0;                       /* start hidden */  animation: typing 3s steps(11, end), blink .7s step-end infinite;
}

/* Reveal text letter by letter */@keyframes typing {
  from { width: 0; }
  to   { width: 11ch; } /* 11 = number of characters */}

/* Blinking cursor */@keyframes blink {
  50% { border-color: transparent; }
}

توضیح: این کد یک افکت تایپ ساده را با استفاده از animation و تابع timing steps() ایجاد می‌کند. مقدار steps باید برابر تعداد کاراکترها باشد تا افکت حرف‌به‌حرف صحیح نمایش داده شود. از font-family monospace استفاده شده تا واحد ch تقریباً هم‌اندازه یک کاراکتر باشد.

نکات و بهبودهای ضروری

  • برای متن‌های فارسی (RTL) باید direction: rtl; و text-align: right; را اعمال کنید.
  • واحد ch فقط برای فونت‌های monospace قابل اعتمادتر است. برای فونت‌های پروپشنال اختلاف ممکن است باعث بریدگی یا فضای اضافه شود.
  • بهتر است طول نهایی (width) با calc و یک متغیر CSS تعیین شود تا قابل تنظیم باشد: width: calc(var(–chars) * 1ch);
  • استفاده از will-change: width یا transform می‌تواند به روان‌تر شدن انیمیشن کمک کند.

نسخه پیشنهادی با متغیرهای CSS و پشتیبانی RTL

<div class="typewriter" style="--chars: 12;" dir="rtl">
  <h1 class="text">Hello World</h1>
</div>

.typewriter {
  overflow: hidden;
  border-right: .12em solid #000;
  white-space: nowrap;
  font-family: monospace;
  width: 0;
  animation: typing 3s steps(var(--chars), end), blink .7s step-end infinite;
  /* for smoother rendering */  will-change: width;
}

/* Calculate final width */@keyframes typing {
  from { width: 0; }
  to   { width: calc(var(--chars) * 1ch); }
}

توضیح: در این نسخه از متغیر CSS (–chars) استفاده شده تا تعداد کاراکترها را بتوان غیرقابل‌مرتب تنظیم کرد. صفت dir=”rtl” برای متن‌های فارسی تعیین جهت متن را انجام می‌دهد. توجه داشته باشید که برخی مرورگرها ممکن است قبول کردن متغیر در steps() محدودیت داشته باشند؛ در این‌صورت مقدار ثابت در steps() قرار دهید یا از preprocessor استفاده کنید.

دسترس‌پذیری (Accessibility) و بهترین‌روش‌ها

افکت‌های دیداری نباید تجربه کاربران کم‌بینا یا استفاده‌کنندگان صفحه‌خوان را خراب کنند. دو رویکرد پیشنهادی:

  • فرهنگ‌نامه خوانا: متن انیمیشنی را از صفحه‌خوان مخفی کنید و نسخه کامل متن را در یک عنصر offscreen برای صفحه‌خوان قرار دهید (مثلاً با کلاس visually-hidden یا aria-live=”polite”).
  • جایگزین جاوااسکریپت: به جای نمایش حرف‌به‌حرف توسط CSS، متن کامل را یک‌باره به یک live region اضافه کنید تا صفحه‌خوان متن کامل را اعلام کند و کاربران به‌سرعت محتوای اصلی را بشنوند.

نمونه کد بهبود یافته برای دسترسی

<!-- Visual animated text (hidden from screen readers) -->
<div class="typewriter" aria-hidden="true">
  <h1 class="text">Hello World</h1>
</div>

<!-- Screen reader friendly text (offscreen) -->
<div class="sr-only" aria-hidden="false">Hello World</div>

/* .sr-only: place offscreen but accessible */.sr-only {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

توضیح: این الگو متن انیمیشنی را از صفحه‌خوان مخفی می‌کند (aria-hidden=”true”) و متن کامل را به‌صورت offscreen برای ابزارهای کمکی قابل‌دسترس نگه می‌دارد. به این ترتیب هم تجربه دیداری حفظ می‌شود و هم دسترسی‌پذیری رعایت می‌گردد.

اگر می‌خواهید متن برای صفحه‌خوان نیز حرف‌به‌حرف اعلام شود

معمولاً بهتر است صفحه‌خوان متن کامل را یک‌باره بخواند؛ صدای حرف‌به‌حرف ممکن است آزاردهنده باشد. اما اگر نیاز دارید می‌توان از JS استفاده کرد تا کنترل دقیق‌تر روی زمان‌بندی و aria-live داشته باشید.

// JavaScript progressive reveal (accessible approach example)
const text = "Hello World";
const el = document.querySelector('.js-type');
const sr = document.querySelector('.js-live'); // aria-live region

let i = 0;
const interval = 80;
const timer = setInterval(() => {
  el.textContent = text.slice(0, ++i);
  // Update live region only when finished (announce full sentence)
  if (i === text.length) {
    sr.textContent = text; // screen reader will announce
    clearInterval(timer);
  }
}, interval);

توضیح: این اسکریپت متن را بصری حرف‌به‌حرف نمایش می‌دهد اما تنها پس از اتمامِ نمایش متن کامل را در یک منطقه aria-live قرار می‌دهد تا صفحه‌خوان متن را یک‌باره اعلام کند. این روش تجربه بهتری برای کاربران صفحه‌خوان ایجاد می‌کند.

عملکرد و نکات حرفه‌ای

  • برای انیمیشن‌های ساده CSS بهترین عملکرد را دارند؛ از جاوااسکریپت فقط وقتی لازم است استفاده کنید.
  • در media query مربوط به prefers-reduced-motion افکت را غیرفعال کنید تا کاربران با حساسیت به حرکت مشکلی نداشته باشند.
  • برای متن‌های داینامیک یا طول‌های متفاوت، محاسبه تعداد کاراکترها در زمان تولید (با build step یا JS) دقیق‌تر است.

مثال prefers-reduced-motion

@media (prefers-reduced-motion: reduce) {
  .typewriter {
    animation: none;
    width: auto; /* show full text */    border-right: none;
  }
}

توضیح: این قاعده از نظر دسترسی مهم است و به کاربرانی که حرکت را ترجیح نمی‌دهند امکان می‌دهد بدون انیمیشن متن را ببینند.

نتیجه‌گیری و موارد کاربرد

افکت تایپ ماشینی با CSS یک راه ساده و مؤثر برای افزایش جذب دیداری است. با رعایت نکات مربوط به RTL، انتخاب فونت مناسب، بهبودهای CSS و توجه به دسترسی‌پذیری می‌توان افکتی حرفه‌ای و کاربرپسند ساخت. در پروژه‌های تولیدی، بهتر است برای متن فارسی از جهت‌دهی مناسب و تست روی مرورگرها و دستگاه‌های مختلف اطمینان حاصل کنید.

روشمزایامعایب
CSS-onlyساده، سریع، بدون JSمحدودیت در دقت برای فونت‌های پروپشنال و دسترسی
CSS + JS (مجهز)دسترسی بهتر، کنترل دقیق‌ترپیچیدگی بیشتر، نیاز به اسکریپت

آیا این مطلب برای شما مفید بود ؟

خیر
بله
موضوعات شما در انجمن: