آموزش ساخت افکت تایپرایتر (Typewriter) روان و بینقص با استفاده از انیمیشنهای CSS
رفیق برنامهنویس، دنبال راهی هستی که متنهات توی سایتت جون بگیرن و بازدیدکنندهها رو میخکوب کنن؟ افکت تایپرایتر همون چیزیه که نیاز داری! این افکت نه تنها جذابیت بصری فوقالعادهای به وبسایتت میده، بلکه میتونه توجه کاربر رو به محتوای اصلی جلب کنه و تجربه کاربری رو بهبود ببخشه. و نگران نباش، لازم نیست چرخ رو از اول اختراع کنی. ما اینجا هستیم تا مرحله به مرحله، بدون حتی یک خط جاوااسکریپت و فقط با جادوی CSS، این افکت رو بسازیم. همین حالا سری به گنجینه کدهای آماده CSS ما بزن و ببین چطور میتونی این افکت و کلی افکت باحال دیگه رو توی پروژههات به کار ببری. برای هر سوال یا نیاز به راهنمایی بیشتر هم، یه زنگ بزن، من هستم!
نقشه راه افکت تایپرایتر: یک نگاه سریع

🎯 هدف:
- نمایش متن کاراکتر به کاراکتر.
- ایجاد مکاننما (Caret) چشمکزن.
🛠️ ابزارها:
- HTML: ساختار متن.
- CSS: قلب انیمیشن.
⚙️ مراحل اصلی:
- تعیین طول نهایی متن (
width). - مخفی کردن سرریز (
overflow: hidden). - انیمیشن تایپ (
@keyframes typing) برایwidth. - انیمیشن مکاننما (
@keyframes blink-caret) برایborder-right.
💡 نکات کلیدی:
- تابع
steps()برای حرکت پلهای. - خاصیت
animation-fill-mode: forwards. - واحد
chبرای اندازهگیری کاراکتر.
نتیجه: یک رابط کاربری پویا، جذاب و کاربرپسند!
مقدمهای بر افکت تایپرایتر: چرا و چگونه؟

افکت تایپرایتر یا همان “ماشین تحریر”، چیزی فراتر از یک جلوه بصری ساده است. این افکت به محتوای تو زندگی میبخشد و آن را از حالت ایستا خارج میکند. حتماً دیدهای که در وبسایتهای مدرن، هدرها یا پیامهای کلیدی به جای اینکه یکباره ظاهر شوند، حرف به حرف یا کلمه به کلمه نوشته میشوند. این کار نه تنها ظاهر سایت رو حرفهایتر میکنه، بلکه به لحاظ روانشناسی هم روی کاربر اثر میگذارد. کاربران ناخودآگاه جذب این نوع انیمیشنها میشوند، زیرا حس کنجکاویشان برانگیخته شده و منتظر تکمیل شدن پیام میمانند. این یعنی افزایش زمان ماندگاری کاربر در صفحه (Dwell Time) و نرخ تعامل (Engagement Rate) که هر دو سیگنالهای مثبت سئو هستند.
ساخت این افکت با جاوااسکریپت هم امکانپذیره، اما هدف ما در این آموزش، پیادهسازی اون با CSS خالص است. چرا CSS؟ چون سبکتر، سریعتر، و در بسیاری از موارد برای چنین افکتهای بصری، کارآمدتر است. با CSS میتونیم به سادگی و بدون نیاز به سربار جاوااسکریپت، یک تجربه روان و بهینه ایجاد کنیم. کلید اصلی این کار، ترکیب هوشمندانه ویژگیهایی مثل overflow: hidden، واحد ch (برای عرض کاراکترها) و تابع steps() در Keyframesهای CSS است. این تابع steps() به انیمیشن میگوید که به جای حرکت نرم و پیوسته، در چندین “گام” مشخص حرکت کند که دقیقاً حس تایپ کردن حرف به حرف رو ایجاد میکند.
پایه و اساس: HTML ساختاریافته برای افکت

قبل از اینکه وارد دنیای پر رمز و راز CSS بشیم، باید یک ساختار HTML ساده و مناسب برای متنمون داشته باشیم. برای افکت تایپرایتر، متن شما باید داخل یک المان <p>، <h1> یا <div> قرار بگیره. مهم اینه که ما به این المان یک class یا id بدیم تا بتونیم با CSS اون رو هدف قرار بدیم. فرض میکنیم میخواهیم یک پیام خوشآمدگویی جذاب رو به نمایش بذاریم.
نمونه HTML:
<!DOCTYPE html>
<html lang="fa">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>افکت تایپرایتر CSS</title>
<link rel="stylesheet" href="style.css"> <!-- فایل CSS رو اینجا لینک میکنیم -->
</head>
<body style="background-color: #f0f2f5; display: flex; justify-content: center; align-items: center; min-height: 100vh; margin: 0;">
<div class="typewriter-container">
<h1 class="typewriter-text">سلام، به دنیای انیمیشنهای CSS خوش آمدید!</h1>
</div>
</body>
</html>
همونطور که میبینی، ما یک div والد با کلاس .typewriter-container داریم و داخلش متن اصلی رو با کلاس .typewriter-text قرار دادیم. این جداسازی به ما کمک میکنه تا استایلها و انیمیشنها رو دقیقتر اعمال کنیم.
جادوی CSS: گام به گام تا انیمیشن
حالا که HTML رو آماده کردیم، وقتشه که با CSS جادو کنیم. بخش عمده کار ما اینجاست و باید با دقت هر خاصیت رو بررسی کنیم. یادت باشه، هر خط کد اینجا دلیل منطقی خودش رو داره.
استایلدهی اولیه متن
برای اینکه افکت تایپرایتر درست کار کنه، باید چندتا پیشنیاز رو برای متن اصلی تعریف کنیم:
font-familyوfont-size: مشخص کردن فونت و اندازه اون برای محاسبه دقیق عرض هر کاراکتر ضروریه.overflow: hidden: این مهمترین خاصیت برای پنهان کردن متنی است که هنوز “تایپ” نشده.white-space: nowrap: مطمئن میشه که متن در یک خط باقی میماند و شکسته نمیشود. (برای سناریوهای چندخطی کمی پیچیدهتر است که بعداً بهش میپردازیم).border-right: این همون مکاننما (Caret) چشمکزنه. به جای استفاده از یک المان جداگانه، از border سمت راست متن استفاده میکنیم.width: 0: در ابتدا، عرض متن رو صفر میکنیم تا هیچ کاراکتری دیده نشه. انیمیشن این عرض رو زیاد میکنه.
CSS اولیه (style.css):
.typewriter-text {
font-family: monospace; /* فونت ثابت برای محاسبه دقیق 'ch' */
font-size: 2em;
color: #333;
white-space: nowrap; /* متن در یک خط بماند */
overflow: hidden; /* پنهان کردن متن اضافی */
border-right: 2px solid #333; /* مکاننما */
width: 0; /* شروع از صفر عرض */
margin: 0 auto; /* مرکز قرار دادن متن */
padding-right: 5px; /* کمی فاصله برای مکاننما */
}
/* برای ریسپانسیو بودن: در موبایل فونت کوچکتر */
@media (max-width: 768px) {
.typewriter-text {
font-size: 1.5em;
}
}
یک نکته مهم: برای واحد ch که بهش نیاز داریم، بهتره از یک font-family با عرض ثابت (monospace) استفاده کنی. این کار محاسبه دقیق عرض رو آسونتر میکنه. اگر فونتهای دیگه رو ترجیح میدی، باید به صورت دستی یا با جاوااسکریپت عرض نهایی رو محاسبه کنی.
افکت تایپ (typing)
حالا نوبت به انیمیشن اصلی، یعنی انیمیشن “تایپ” میرسه. این انیمیشن مسئول افزایش عرض متن از صفر تا عرض کامل اونه.
@keyframes typing: تعریف یک فریم کلیدی جدید به نامtyping.from { width: 0; } to { width: [طول_متن]ch; }: این قسمت میگه که انیمیشن از عرض صفر شروع و تا عرض نهایی متن (به واحدch) ادامه پیدا کنه. عدد[طول_متن]دقیقاً برابر با تعداد کاراکترهای متن توست. برای “سلام، به دنیای انیمیشنهای CSS خوش آمدید!”، حدوداً 40 کاراکتر داریم.animationproperty:[duration]s: مدت زمان انیمیشن (مثلاً 4 ثانیه).steps([char_count], end): اینجاست که جادو اتفاق میافته!steps()انیمیشن رو به گامهای مساوی تقسیم میکنه. تعداد[char_count]باید برابر با تعداد کاراکترهای متن باشه (40 تا).endیعنی تغییر در انتهای هر گام اتفاق بیفته.forwards: مطمئن میشه که بعد از اتمام انیمیشن، المان در حالت نهایی خودش باقی میمونه (یعنی عرض کامل).
افکت مکاننما (caret/blinking cursor)
برای اینکه مکاننما (همون border سمت راست) چشمک بزنه، به یک انیمیشن جداگانه نیاز داریم.
@keyframes blink-caret: یک فریم کلیدی جدید برای چشمک زدن.from, to { border-color: transparent; } 50% { border-color: #333; }: این فریم کلیدی میگه که مکاننما در ابتدا و انتها شفاف باشه و در نیمه انیمیشن، رنگ اصلیش (مشکی) رو داشته باشه. این باعث میشه چشمک بزنه.animationproperty:.75s: مدت زمان هر سیکل چشمک زدن.step-end: مثلsteps(1, end)عمل میکنه، یعنی هر گام فوراً تغییر میکنه.infinite: مکاننما تا ابد چشمک میزنه.
تکمیل انیمیشن با Keyframes
حالا همه چیز رو با هم ترکیب میکنیم. انیمیشن تایپ باید اول اجرا بشه، و بعد از اون، انیمیشن مکاننما شروع به کار کنه.
.typewriter-text {
font-family: monospace;
font-size: 2em;
color: #333;
white-space: nowrap;
overflow: hidden;
border-right: 2px solid #333;
width: 0;
margin: 0 auto;
padding-right: 5px;
/* مدت زمان انیمیشن تایپ بر اساس تعداد کاراکترها و سرعت دلخواهت */
/* طول متن "سلام، به دنیای انیمیشنهای CSS خوش آمدید!" حدود 40 کاراکتره (شامل فاصله و علائم نگارشی) */
/* زمان: 4 ثانیه (0.1s برای هر کاراکتر) */
/* delay: 0 ثانیه */
animation:
typing 4s steps(40, end) forwards, /* انیمیشن تایپ */
blink-caret .75s step-end infinite; /* انیمیشن چشمک زدن مکاننما */
/* تاخیر در شروع انیمیشن (اگر نیاز بود) */
/* animation-delay: 1s; */
}
/* تعریف Keyframes برای انیمیشن تایپ */
@keyframes typing {
from { width: 0; }
to { width: 40ch; } /* عرض نهایی بر اساس تعداد کاراکترها */
}
/* تعریف Keyframes برای انیمیشن چشمک زدن مکاننما */
@keyframes blink-caret {
from, to { border-color: transparent; } /* مکاننما پنهان */
50% { border-color: #333; } /* مکاننما ظاهر */
}
/* برای ریسپانسیو بودن */
@media (max-width: 768px) {
.typewriter-text {
font-size: 1.5em; /* کوچکتر کردن فونت */
/* نیاز به تنظیم مجدد عرض 'to' در keyframes typing اگر تعداد کاراکترها فرق کند */
/* مثلاً اگر متن کوتاهتری برای موبایل نمایش دهیم */
/* در غیر این صورت، 'ch' خودکار با فونت تغییر میکند */
}
}
حالا با این کدها، میتونی یک افکت تایپرایتر روان و جذاب داشته باشی. نکته کلیدی اینه که مدت زمان انیمیشن تایپ (4s) و تعداد گامها (40) باید با هم متناسب باشن. یعنی اگر 40 کاراکتر داریم و میخوایم هر کاراکتر 0.1 ثانیه طول بکشه، کل زمان میشه 4 ثانیه.
برای افکتهای رسپانسیو، باید حواست به font-size و در نتیجه ch unit باشه. معمولاً با تغییر font-size، واحد ch هم خودش رو تغیر میدهد و نیاز به دستکاری مجدد width در @keyframes نیست. اما اگر متن تغییر میکنه، باید دقت کنی.
تکمیلکننده: جاوااسکریپت برای انعطافپذیری بیشتر (اختیاری)
با اینکه تمرکز ما روی CSS خالصه، اما گاهی اوقات نیاز داریم که افکتمون دینامیکتر باشه. مثلاً اگر متن از دیتابیس میآید یا میخواهیم چندین متن مختلف رو به صورت چرخشی نمایش بدیم، CSS به تنهایی جوابگو نیست. اینجا جاوااسکریپت وارد عمل میشه.
جاوااسکریپت میتونه:
- تعداد کاراکترهای متن رو به صورت خودکار محاسبه کنه و
widthنهایی وsteps()رو بر اساس اون تنظیم کنه (با استفاده از CSS Custom Properties). - چندین متن رو به صورت متوالی یا رندوم نمایش بده، یکی بعد از دیگری.
- افکت رو با تعاملات کاربر (مثلاً کلیک روی یک دکمه) شروع یا متوقف کنه.
البته، اضافه کردن جاوااسکریپت کمی پیچیدگی رو به کد اضافه میکنه و از هدف اصلی مقاله ما که CSS خالصه، دور میشه. اما خوبه بدونی که اگر به چنین انعطافپذیری بیشتری نیاز داشتی، گزینههای جاوااسکریپت هم در دسترست هستن.
نکات پیشرفته برای یک افکت بینقص
برای اینکه افکت تایپرایتر تو واقعاً بینقص و کاربردی باشه، باید به چندتا نکته ریز ولی مهم توجه کنی:
مدیریت متن چندخطی
همونطور که گفتیم، white-space: nowrap متن رو روی یک خط نگه میداره. اگر میخوای متن چندخطی داشته باشی، دیگه نمیتونی از این خاصیت استفاده کنی. در این صورت، افکت تایپرایتر با CSS کمی مشکلساز میشه چون width تنها روی یک خط منطقی عمل میکنه. برای متنهای چندخطی، اغلب بهترین راه حل استفاده از جاوااسکریپت است که هر خط رو به صورت جداگانه یا هر کاراکتر رو با تأخیر وارد میکنه.
بهینهسازی برای عملکرد و تجربه کاربری
- تست ریسپانسیو بودن: حتماً افکت رو روی دستگاههای مختلف (موبایل، تبلت، دسکتاپ و حتی تلوزیون) تست کن تا مطمئن بشی به درستی نمایش داده میشه. تغییر
font-sizeدر Media Queries برای صفحههای کوچکتر معمولاً کافیه. - Accessible Design: برای کاربرانی که ممکن است به انیمیشنها حساس باشند یا از ابزارهای کمککننده استفاده کنند، خاصیت
@media (prefers-reduced-motion)رو در نظر بگیر. میتونی انیمیشن رو برای این کاربران غیرفعال کنی.
جدول راهنما: بهینهسازی افکت تایپرایتر
| جنبه بهینهسازی | توضیحات/راه حل |
|---|---|
| عملکرد (Performance) | از خاصیتهای width و border-color استفاده کن که مرورگر به راحتی بهینهسازی میکنه (برخلاف خاصیتهایی مثل left و top). |
| Accessibility | از @media (prefers-reduced-motion: reduce) استفاده کن تا انیمیشن رو برای کاربران حساس به حرکت، غیرفعال کنی. |
| متن دینامیک | اگر متن از منبع خارجی میاد، از جاوااسکریپت برای محاسبه steps() و width (تنظیم CSS Custom Properties) استفاده کن. |
عیبیابی سریع: حل مشکلات رایج
در طول پیادهسازی افکت تایپرایتر ممکنه به چندتا مشکل رایج برخورد کنی. نگران نباش، این راه حلها بهت کمک میکنه:
مشکل ۱: متن ناگهان ظاهر میشود یا بعد از اتمام ناپدید میگردد.
راه حل: این مشکل معمولاً به خاطر عدم استفاده از animation-fill-mode: forwards; در انیمیشن تایپینگ است. این خاصیت تضمین میکنه که المان بعد از اتمام انیمیشن، در حالت نهایی خودش (یعنی با عرض کامل) باقی میمونه.
مشکل ۲: مکاننما چشمک نمیزند یا همیشه ثابت است.
راه حل: مطمئن شو که هم خاصیت border-right رو به متن دادی و هم @keyframes blink-caret رو به درستی تعریف کردی. همچنین، بررسی کن که انیمیشن blink-caret با infinite و step-end اعمال شده باشه.
مشکل ۳: افکت روی موبایل کند یا ناپایدار است.
راه حل: عملکرد انیمیشنها روی دستگاههای با منابع کمتر ممکنه افت کنه. مطمئن شو که از فونتهای بهینه استفاده میکنی. همچنین، میتونی سرعت انیمیشن رو با animation-duration کمی بیشتر کنی یا تعداد steps() رو در صورتی که متن کوتاهتر است، کاهش دهی.
برای رسانی بهتر، از `transform` و `opacity` (که GPU-accelerated هستند) در صورت امکان استفاده کن، هرچند برای این افکت `width` انتخاب بهتری است.
مشکل ۴: متن روی یک خط نمیماند و شکسته میشود.
راه حل: این به خاطر حذف یا عدم اعمال خاصیت white-space: nowrap; است. این خاصیت رو به المان متنیات اضافه کن.
مشکل ۵: واحد ch درست کار نمیکند یا عرض نهایی متن نادرست است.
راه حل: واحد ch بر اساس عرض کاراکتر ‘0’ در فونت فعلی است. اگر از فونتهای متغیر (Proportional Fonts) استفاده کنی، ch ممکنه دقت کافی رو نداشته باشه. بهترین کار اینه که یا از فونت monospace استفاده کنی، یا با استفاده از جاوااسکریپت عرض واقعی متن رو به پیکسل محاصبه کنی و اون رو به عنوان یک CSS Custom Property تنظیم کنی.
پرسشهای متداول (FAQ)
در این بخش به برخی از سوالات رایج در مورد افکت تایپرایتر پاسخ میدهیم:
Q: بهترین راه برای پیادهسازی افکت تایپرایتر چندخطی چیست؟
A: همانطور که اشاره شد، پیادهسازی افکت تایپرایتر چندخطی با CSS خالص چالشبرانگیز است، زیرا خاصیت width و overflow: hidden به طور طبیعی روی یک خط عمل میکنند. بهترین رویکرد برای متنهای چندخطی یا دینامیک، استفاده از جاوااسکریپت است که میتواند هر خط یا حتی هر کلمه را به صورت جداگانه انیمیت کند. میتونی نمونههای کدهای جاوااسکریپت رو برای این کار بررسی کنی.
Q: آیا استفاده از این افکت برای سئو (SEO) مضر است؟
A: خیر، تا زمانی که متن اصلی در HTML شما وجود داشته باشد و مرورگرها و خزندههای موتورهای جستجو بتوانند آن را بخوانند، مشکلی برای سئو پیش نمیآید. این افکت صرفاً یک لایه بصری روی متن اصلی شماست. در واقع، با بهبود تجربه کاربری و افزایش تعامل، ممکن است به صورت غیرمستقیم حتی تأثیر مثبتی بر سئو داشته باشد.
Q: چگونه میتوان سرعت افکت تایپرایتر را کنترل کرد؟
A: سرعت افکت تایپرایتر عمدتاً توسط دو خاصیت در انیمیشن typing کنترل میشود:
animation-duration: این زمان کلی انیمیشن را تعیین میکند.- تعداد گامها در
steps([char_count], end): این تعداد مراحلی است که انیمیشن طی میکند.
با تغییر این دو مقدار میتوانی سرعت تایپ هر کاراکتر را تنظیم کنی. مثلاً برای سریعتر کردن، زمان (duration) را کاهش دهی یا تعداد گامها را ثابت نگه داری.
Q: آیا میتوانم از این افکت برای متنهای فارسی استفاده کنم؟
A: بله، این افکت برای متنهای فارسی نیز کاملاً کاربردی است. واحد ch و خاصیت overflow: hidden بدون مشکل با زبان فارسی کار میکنند. فقط کافی است تعداد کاراکترهای متن فارسی خود را به درستی محاسبه کرده و در steps() و width انیمیشن تایپینگ اعمال کنید.
امیدوارم این آموزش کامل و جامع بهت کمک کرده باشه تا بتونی افکت تایپرایتر مورد نظرت رو با CSS بسازی. فراموش نکن که همیشه میتونی برای الهام گرفتن و پیدا کردن کدهای بیشتر، به سایت fa-tools.ir سر بزنی.
function copyCode(button) {
const pre = button.nextElementSibling;
const code = pre.querySelector(‘code’);
const text = code.innerText;
const textarea = document.createElement(‘textarea’);
textarea.value = text;
document.body.appendChild(textarea);
textarea.select();
document.execCommand(‘copy’);
document.body.removeChild(textarea);
button.textContent = ‘کپی شد!’;
setTimeout(() => {
button.textContent = ‘کپی کد’;
}, 2000);
}
مطالب مرتبط:
- 50 تگ پر استفاده و مهم اچ تی ام ال HTML
- آموزش ساخت شمارندههای (Counters) خودکار با استفاده از ویژگی counter-reset
- کیت طراحی UI
- کدهای CSS برای تغییر شکل و استایلدهی پیشرفته به چکباکسها و رادیوباتنها
- کدهای آماده ساخت تولتیپهای (Tooltip) مدرن و انیمیشنی
- ترفندهای CSS برای مدیریت نمایش متنهای طولانی (Truncate Text)
- کدهای آماده برای طراحی فرمهای مرحلهای (Multi-step Forms)