راهنمای تعاملی برای انتقال CSS • Josh W. Comeau

دنیای انیمیشن های وب به جنگلی گسترده از ابزارها و فناوری ها تبدیل شده است. کتابخانههایی مانند GSAP و Framer Motion و React Spring به ما کمک کردند تا حرکت را به DOM اضافه کنیم.
با این حال، اساسی ترین و حیاتی ترین بخش، انتقال ساده CSS است. این اولین ابزار انیمیشنی است که اکثر توسعه دهندگان فرانت اند یاد می گیرند و یک اسباب بازی است. حتی خستهترین و خستهترین کهنهکارهای انیمیشن هنوز اغلب به سراغ این ابزار میروند.
این نخ دارای عمق شگفت انگیزی است. در این آموزش، کمی بیشتر در مورد انتقال های CSS و نحوه استفاده از آنها برای ایجاد انیمیشن های شاداب و زیبا می آموزیم.
عنصر اصلی که برای ایجاد یک انیمیشن به آن نیاز داریم مقداری CSS است که تغییر می کند.
در اینجا نمونه ای از دکمه ای است که در حالت انتظار حرکت می کند، بدون انیمیشن:
کد زمین بازی
نتیجه
این قطعه استفاده می کند :hover شبه کلاس برای تعیین یک اعلان CSS اضافی هنگامی که ماوس کاربر روی دکمه ما قرار می گیرد، مانند onMouseEnter رویداد در جاوا اسکریپت
برای انتقال عنصر به بالا، از آن استفاده می کنیم transform: translateY(-10px). تا زمانی که بتوانیم استفاده کنیم margin-top برای آن transform: translate ابزار بهتری برای کار است. بعدا خواهیم دید چرا
به طور پیش فرض، تغییرات CSS فورا اتفاق می افتد. در یک چشم به هم زدن، دکمه ما به یک موقعیت جدید از راه دور منتقل می شود! این با دنیای طبیعی، جایی که همه چیز به تدریج اتفاق می افتد، ناسازگار است.
ما می توانیم به مرورگر دستور دهیم که درون یابی می کنم از یک ایالت به ایالت دیگر با نام مناسب transition دارایی:
کد زمین بازی
نتیجه
transition می تواند تعدادی مقدار بگیرد، اما تنها دو مورد مورد نیاز است:
-
نام خاصیتی که می خواهیم متحرک سازی کنیم
-
مدت زمان انیمیشن
اگر قصد دارید چندین ویژگی را متحرک کنید، می توانید لیستی جدا شده با کاما به آنها ارسال کنید:
.btn {
transition:
transform 250ms,
opacity 400ms;
}
.btn:hover {
transform: scale(1.2);
opacity: 0;
}
وقتی به یک عنصر می گوییم که از یک موقعیت به موقعیت دیگر حرکت کند، مرورگر باید بفهمد که هر قاب “در بین” چگونه باید باشد.
به عنوان مثال: فرض کنید یک عنصر را برای مدت 1 ثانیه از چپ به راست حرکت می دهیم. انیمیشن روان باید با سرعت 60 فریم در ثانیه اجرا شودفریم در ثانیه، تعداد دفعاتی که عنصر در هر ثانیه دوباره ترسیم می شود، به این معنی که ما باید 60 موقعیت جداگانه بین شروع و پایان داشته باشیم.
بیایید با قرار دادن آنها در فاصله مساوی شروع کنیم:
روی من کلیک کن
برای روشن شدن آنچه در اینجا می گذرد: هر دایره محو شده یک لحظه از زمان را نشان می دهد. همانطور که دایره از چپ به راست حرکت می کند، این فریم هایی هستند که به کاربر نشان داده شده اند. مثل یک فلیپ بوک است.
در این انیمیشن از a تابع زمان خطی. این بدان معنی است که عنصر با سرعت ثابت حرکت می کند. دایره ما در هر فریم به همان میزان حرکت می کند.
چندین توابع همگام سازی در CSS در دسترس ما هستند. ما می توانیم مشخص کنیم که با کدام یک استفاده کنیم transition-timing-function دارایی:
.btn {
transition: transform 250ms;
transition-timing-function: linear;
}
یا میتوانیم آن را مستقیماً به آن ارسال کنیم transition اموال مختصر:
.btn {
transition: transform 250ms linear;
}
linear این به ندرت بهترین انتخاب است – در نهایت، تقریباً هیچ چیز در دنیای واقعی به آن سمت حرکت نمی کندشاید پرینترهای سه بعدی نزدیکترین آنها باشند؟ اما اگر کسی به ما بگوید که مثل یک چاپگر سه بعدی می رقصیم، احتمالاً ناراحت می شویم. بنابراین ما نباید آن را هدف قرار دهیم.. انیمیشنهای خوب دنیای طبیعی را تقلید میکنند، بنابراین باید به دنبال چیزی ارگانیکتر باشیم!
بیایید گزینه های خود را بررسی کنیم.
پیوند به این عنوانتسکین دادن
ease-out او مانند یک گاو وحشی شارژ می کند، اما انرژی اش تمام می شود. از این گذشته، او مانند یک لاک پشت خواب آلود حرکت می کند.
سعی کنید با خط زمانی تمیز کنید. توجه داشته باشید که حرکت در چند فریم اول چقدر شدید است و در پایان چقدر ظریف می شود.
اگر بخواهیم جابجایی عنصر را در طول زمان رسم کنیم، به شکل زیر خواهد بود:
چه زمانی استفاده می کنید ease-out? بیشتر زمانی استفاده می شود که چیزی خارج از صفحه نمایش وارد می شود (مثلاً یک مدال ظاهر می شود). این اثر را ایجاد می کند که چیزی از دور آمده و در مقابل کاربر مستقر شده است.
پیوند به این عنوانسهولت ورود
ease-in، که جای تعجب نیست که برعکس آن است ease-out. کند شروع می شود و سرعت آن افزایش می یابد:
همانطور که دیدیم، ease-out برای چیزهایی که خارج از صفحه قابل مشاهده هستند مفید است. ease-inالبته برای برعکس مفید است: حرکت دادن چیزی به خارج از محدوده دید.
این ترکیب زمانی مفید است که چیزی مانند مودال وارد و خارج از ویوپورت شود. به زودی نحوه ترکیب ویژگی های همگام سازی را بررسی خواهیم کرد.
به این توجه کنید ease-in تقریباً به طور انحصاری برای انیمیشن هایی که با یک عنصر خارج از صفحه یا نامرئی پایان می یابند مفید است. در غیر این صورت، توقف ناگهانی می تواند ناراحت کننده باشد.
پیوند به این عنوانسهولت ورود و خروج
بعدی، ease-in-out. این ترکیبی از دو تابع زمانی قبلی است:
این تابع زمان است متقارن. شتاب و شتاب برابر دارد.
من این منحنی را برای هر چیزی که در یک حلقه اتفاق میافتد بسیار مفید میدانم (مثلاً محو شدن عنصر درون و بیرون، بارها و بارها).
این یک گام بزرگ به جلو است linear، اما قبل از اینکه همه چیز را به هم بزنید، اجازه دهید یک گزینه دیگر را بررسی کنیم.
پیوند به این عنوانسبکی
اگر میخواهم با نویسندگان CSS وقتی صحبت از انتقال به میان میآید، انتخاب کنم، همین است ease بد نام گذاری شده است اصلاً توصیفی نیست; به معنای واقعی کلمه همه ویژگیهای همگامسازی از یک نوع راحتی هستند!
آن غرغر به کنار، ease عالی است بر خلاف ease-in-out، متقارن نیست. ویژگی های یک خیز کوتاه و یک زیاد از تاخیر
ease مقدار پیش فرض است – اگر تابع زمانی را مشخص نکنید، ease عادت می کند راستش را بخواهید، این به نظر من درست است. ease در اکثر موارد یک گزینه عالی است. اگر عنصری حرکت کند و وارد ویوپورت نشود یا از آن خارج نشود، ease معمولا انتخاب خوبی است
پیوند به این عنوانمنحنی های سفارشی
اگر گزینه های داخلی ارائه شده با نیازهای شما مطابقت ندارند، می توانید منحنی کاهش سفارشی خود را با استفاده از عملکرد همگام سازی Cubic Bezier تعریف کنید!
.btn {
transition: transform 250ms cubic-bezier(0.1, 0.2, 0.3, 0.4);
}
تمام مقادیری که تاکنون دیدهایم در واقع فقط از پیش تعیین شده برای این کار هستند cubic-bezier تابع 4 عدد مورد نیاز است که نشان دهنده 2 نقطه کنترل است.
منحنی های Bezier واقعاً منظم هستند، اما فراتر از محدوده این آموزش است. ما آنها را در انیمیشن های کاملاً جدید خود به طور عمیق بررسی می کنیم دوره(در برگه جدید باز می شود)، اگر می خواهید حتی عمیق تر بروید!
ابزارهایی مانند Easing جادوگر(در برگه جدید باز می شود) بیایید با استفاده از امکانات مختلف تجسم و سفارشی سازی کنیم cubic-bezier تابع هنگامی که یک منحنی تسکین پیدا کردید که از آن راضی هستید، روی “Copy to Clipboard” کلیک کنید و آن را در CSS خود قرار دهید!
شما همچنین می توانید از این مجموعه زمان های طولانی انتخاب کنید توابع(در برگه جدید باز می شود). البته مراقب باشید: برخی از گزینههای عجیبتر در CSS کار نمیکنند.

هنگام شروع کار با منحنیهای سفارشی Bezier، ایجاد منحنی که طبیعی به نظر میرسد ممکن است دشوار باشد. با این حال، با کمی تمرین، شگفت انگیز است بیانگر ابزار
قبلاً اشاره کردیم که انیمیشن ها باید با سرعت 60 فریم در ثانیه اجرا شوند. با این حال، وقتی حساب را انجام میدهیم، متوجه میشویم که این بدان معناست که مرورگر تنها 16.6 میلی ثانیه برای ترسیم هر فریم دارد. واقعا زمان زیادی نیست. برای مرجع، حدود 100 میلیثانیه تا 300 میلیثانیه طول میکشد تا پلک بزنیم!
اگر انیمیشن ما از نظر محاسباتی بیش از حد گران باشد، جذاب و لکنت به نظر می رسد. قاب ها ناپدید می شوند زیرا دستگاه نمی تواند آن را مدیریت کند.
این را خودتان با بهینه سازی کنترل فریم در ثانیه جدید تجربه کنید:
در عمل، عملکرد ضعیف اغلب به شکل متغیر فریم ها، بنابراین یک شبیه سازی کامل نیست.
اجرای انیمیشن یک منطقه شگفت آور عمیق و جالب است که بسیار فراتر از محدوده این آموزش مقدماتی است. اما بیایید موارد کاملاً حیاتی را که باید بدانید را پوشش دهیم:
-
برخی از ویژگی های CSS برای متحرک سازی بسیار گران تر از بقیه هستند. برای مثال،
heightیک ملک بسیار گران قیمت است زیرا روی چیدمان تأثیر می گذارد. هنگامی که ارتفاع یک عنصر کوچک می شود، یک واکنش زنجیره ای ایجاد می کند. تمام خواهر و برادرهای او نیز باید برای پر کردن فضا به سمت بالا حرکت کنند! -
سایر خواص مانند
background-color، برای متحرک سازی کمی گران هستند. آنها بر روی طرح تأثیر نمی گذارند، اما نیاز به یک لایه رنگ جدید روی هر قاب دارند که ارزان نیست. -
دو ملک –
transformوopacity– برای متحرک سازی بسیار ارزان هستند. اگر یک انیمیشن در حال حاضر در حال تغییر ویژگی مانندwidthیاleft، می تواند باشد به طور قابل توجهی بهبود یافته است با انتقال آن بهtransform(اگرچه همیشه نمی توان دقیقاً به همان اثر دست یافت). -
به یاد داشته باشید که انیمیشن های خود را در پایین ترین دستگاهی که سایت/برنامه شما هدف قرار داده است آزمایش کنید. ماشین توسعه شما احتمالا چندین برابر سریعتر از آن است.
اگر علاقه مند به یادگیری بیشتر در مورد پیاده سازی انیمیشن هستید، من در React Rally در مورد این موضوع صحبت کردم. به عمق این موضوع می رود:
https://www.youtube.com/watch?v=DNGGzwmfouU
پیوند به این عنوانشتاب سخت افزاری
بسته به مرورگر و سیستم عامل خود، ممکن است در برخی از نمونه های قبلی متوجه نقص کمی عجیبی شده باشید:

به حروف دقت کنید. توجه کنید که چگونه اشکالات جزئی در ابتدا و انتهای انتقال ظاهر می شود، گویی همه چیز سر جای خود قرار می گیرد؟
این به دلیل انتقال بین CPU و GPU کامپیوتر است. بذار توضیح بدم
وقتی یک عنصر را با استفاده از transform و opacity، مرورگر گاهی اوقات سعی می کند این انیمیشن را بهینه کند. به جای شطرنجی کردن پیکسل های هر فریم، همه چیز را به عنوان یک بافت به GPU منتقل می کند. پردازندههای گرافیکی در انجام این نوع تبدیلهای مبتنی بر بافت بسیار خوب هستند و در نتیجه انیمیشن بسیار روان و بسیار کارآمدی دریافت میکنیم. این به “شتاب سخت افزاری” معروف است.
مشکل اینجاست: پردازندههای گرافیکی و پردازندهها چیزها را رندر میکنند به آرامی متفاوت است. وقتی CPU آن را به GPU میدهد و بالعکس، تصویری از تغییر جزئی چیزها دریافت میکنید.
ما می توانیم این مشکل را با افزودن ویژگی CSS زیر برطرف کنیم:
.btn {
will-change: transform;
}
will-change یک ویژگی است که به ما اجازه می دهد به مرورگر اشاره کنیم که عنصر انتخاب شده را متحرک می کنیم و باید برای این مورد بهینه شود.
در عمل، این بدان معنی است که مرورگر به GPU اجازه می دهد تا این عنصر را مدیریت کند تمام وقت. دیگر خبری از انتقال بین CPU و GPU نیست، دیگر خبری از “کلیک کردن در جای خود” نیست.
will-change به ما این امکان را می دهد که آگاه باشیم که کدام عناصر باید شتاب سخت افزاری داشته باشند. مرورگرها منطق غیرقابل درک خود را در مورد این موارد دارند و من ترجیح می دهم آنها را به حال خود رها نکنم.
یکی دیگر از مزایای شتاب سخت افزاری وجود دارد: ما می توانیم از مزایای آن استفاده کنیم رندر زیر پیکسلی.
به این دو جعبه نگاه کنید. وقتی روی آنها نگه میدارید/تمرکز میکنید، به سمت پایین حرکت میکنند. یکی از آنها شتاب سخت افزاری دارد و دیگری نه.
کد زمین بازی
نتیجه
بسته به دستگاه و نمایشگر شما ممکن است کمی مبهم باشد، اما یک جعبه بسیار نرم تر از دیگری حرکت می کند.
خواص مانند margin-top نمیتواند زیرپیکسلها را رندر کند، به این معنی که باید به نزدیکترین پیکسل گرد شوند و یک افکت آبشاری ایجاد کنند. transformدر همین حال، به لطف ترفند ضد aliasing پردازنده گرافیکی، می تواند به راحتی بین پیکسل ها سوئیچ کند.
پیوند به این عنوانحرکت اکشن محور
بیایید دوباره به دکمه بازشو Hello World نگاه کنیم.
همانطور که مطرح است، ما یک انتقال “متقارن” داریم – انیمیشن ورودی مانند انیمیشن خروج است:
-
هنگامی که ماوس روی عنصر قرار می گیرد، 10 پیکسل به مدت 250 میلی ثانیه به سمت بالا حرکت می کند
-
وقتی ماوس دور میشود، عنصر 10 پیکسل به مدت 250 میلیثانیه به پایین حرکت میکند
یک جزئیات کوچک زیبا این است که به هر عمل تنظیمات انتقال خاص خود را بدهید. برای انیمیشنهای شناور، من دوست دارم انیمیشن ورودی را سریع و سریع بسازم، در حالی که انیمیشن خروج میتواند کمی آرامتر و بیحالتر باشد:
کد زمین بازی
نتیجه
یکی دیگر از نمونه های رایج مدال ها است. ممکن است معرفی مدال با یک مفید باشد ease-out انیمیشن و خروج سریعتر ease-in انیمیشن:
این یک جزئیات کوچک است، اما به یک ایده بسیار بزرگتر صحبت می کند.
من معتقدم که اکثر توسعه دهندگان به این فکر می کنند کشورها: به عنوان مثال، می توانید به این وضعیت نگاه کنید و بگویید که یک حالت نگه داشتن و یک حالت پیش فرض داریم. در عوض، چه می شود اگر ما در شرایط فکر کنیم اقدامات? ما بر اساس کاری که کاربر انجام میدهد، متحرک میشویم و به جای حالتها، به رویدادها فکر میکنیم. ما یک انیمیشن با ماوس و یک انیمیشن خارج کردن موس داریم.
توبیاس آلین در پست وبلاگ خود Meaningfun Motion با Action-Driven نشان می دهد که چگونه این ایده می تواند انیمیشن های معنایی سطح بعدی ایجاد کند. انیمیشن(در برگه جدید باز می شود).
پیوند به این عنوانتاخیر
خوب، ما در تلاش خود برای مهارت در انتقال CSS بسیار پیشرفت کرده ایم، اما چند جزئیات نهایی وجود دارد که باید به آنها بپردازیم. بیایید در مورد تاخیرهای انتقال صحبت کنیم.
من معتقدم تقریباً همه قبلاً این تجربه ناامید کننده را داشته اند:

بهعنوان یک توسعهدهنده، احتمالاً میتوانید بفهمید که چرا این اتفاق میافتد: منوی کشویی فقط تا زمانی که در حالت انتظار باشد باز میماند! همانطور که ماوس را به صورت مورب حرکت می دهیم تا یک فرزند انتخاب کنیم، مکان نما ما از محدوده خارج می شود و منو بسته می شود.
این مشکل را می توان کاملاً زیبا و بدون نیاز به متوسل شدن به JS حل کرد. می توانیم استفاده کنیم transition-delay!
.dropdown {
opacity: 0;
transition: opacity 400ms;
transition-delay: 300ms;
}
.dropdown-wrapper:hover .dropdown {
opacity: 1;
transition: opacity 100ms;
transition-delay: 0ms;
}
transition-delay به ما این امکان را می دهد که وضعیت موجود را برای مدت کوتاهی حفظ کنیم. در این حالت زمانی که کاربر موس خود را به بیرون حرکت می دهد .dropdown-wrapperبرای 300 میلی ثانیه هیچ اتفاقی نمی افتد. اگر ماوس آنها مجدداً در این پنجره 300 میلیثانیه وارد آیتم شود، انتقال هرگز اتفاق نمیافتد.
بعد از 300 میلی ثانیه، transition به طور معمول شروع می شود و پس از 400 میلی ثانیه کشویی محو می شود.
پیوند به این عنوانبال زدن محکوم به فنا
هنگامی که یک عنصر در حالت شناور به سمت بالا یا پایین حرکت می کند، باید بسیار مراقب باشیم که به طور تصادفی یک “فلیکر عذاب” را معرفی نکنیم:
هشدار: این GIF شامل یک سوسو زدن است که به طور بالقوه می تواند باعث تشنج در افراد مبتلا به صرع حساس به نور شود.
شما ممکن است متوجه تأثیر مشابهی در برخی از دموهای این صفحه شده باشید!
مشکل زمانی رخ می دهد که ماوس نزدیک مرز عنصر باشد. افکت نگه داشتن آیتم را از زیر ماوس خارج میکند، که باعث میشود دوباره زیر ماوس بیفتد، که باعث میشود جلوه نگه داشتن دوباره فعال شود… چند بار در ثانیه.
چگونه این را حل کنیم؟ ترفند تقسیم بندی است ماشه از اثر. در اینجا یک مثال سریع آورده شده است:
کد زمین بازی
نتیجه
مال ما حالا یه بچه جدید اومده .background. این محدوده شامل تمام سبک های آرایشی (رنگ پس زمینه، فونت و غیره) است.
وقتی ماوس را روی دکمه ساده جین میچرخانیم، باعث میشود کودک از بالا نگاه کند. با این حال، دکمه هنوز است.
بدون نظر دادن را امتحان کنید outline تا ببینید دقیقا چه خبر است!
وقتی یک انیمیشن خوش ساخت را در وب می بینم، با خوشحالی و شادی واکنش نشان می دهم. با این حال، مردم متفاوت هستند و برخی از افراد متفاوت هستند زیاد واکنش های مختلف: حالت تهوع و ضعف.
من قبلاً در مورد پیروی از “حرکت با اولویت کاهش یافته” نوشته ام، یک تنظیم در سطح سیستم عامل که کاربران می توانند برای بیان ترجیح حرکت کمتر آن را تغییر دهند. بیایید با غیرفعال کردن انیمیشنها برای افرادی که آن را درخواست میکنند، آن درسها را در اینجا اعمال کنیم:
@media (prefers-reduced-motion: reduce) {
.btn {
transition: none;
}
}
این ترفند کوچک به این معنی است که انیمیشن ها بلافاصله برای کاربرانی که به تنظیمات برگزیده سیستم خود رفته اند و یک کادر را علامت زده اند فعال می شود.
به عنوان توسعه دهندگان فرانت اند، ما مسئولیت خاصی داریم تا اطمینان حاصل کنیم که محصولاتمان آسیبی نمی بینند. این گام سریعی است که میتوانیم برای آسانتر و ایمنتر کردن سایتها/برنامههای خود برداریم.
انتقال CSS اساسی است، اما این بدان معنا نیست که آنها آسان هستند. عمق شگفت انگیزی در آنها وجود دارد. حتی در این پست طولانی وبلاگ، مجبور شدم برخی چیزها را حذف کنم تا قابل کنترل بمانم!
انیمیشن های وب مهم تر از آن چیزی هستند که بیشتر توسعه دهندگان می دانند. یک انتقال واحد در اینجا یا آنجا باعث ایجاد یا شکستن این تجربه نمی شود، اما می افزاید. به طور کلی، انیمیشنهایی که به خوبی اجرا شدهاند، میتوانند تأثیر شگفتانگیزی بر تجربه کلی کاربر داشته باشند.
انتقال می تواند به یک برنامه احساس “واقعی” بدهد. آنها میتوانند بازخورد ارائه دهند و به شیوهای عمیقتر از کپی کردن به تنهایی ارتباط برقرار کنند. آنها می توانند نحوه استفاده از محصولات شما را به مردم آموزش دهند. آنها می توانند باعث شادی شوند.
اگر این پست وبلاگ برای شما مفید بود، یک خبر عالی برای شما دارم: من به تازگی دوره جدید انیمیشن خود را منتشر کردم!

من در 18 ماه گذشته روی این دوره کار کرده ام، و این نقطه اوج همه چیزهایی است که در مورد انیمیشن ها و تعاملات در تقریباً دو دهه توسعه وب آموخته ام. علاوه بر CSS، ما از JavaScript، SVG و Canvas برای ایجاد انواع افکت های جدید و چشم نواز استفاده می کنیم. اگر تا به حال فکر کرده اید که چگونه یک انیمیشن در این وبلاگ ایجاد کردم، شانس بسیار خوبی وجود دارد که در دوره آموزشی به آن بپردازیم. ✨
در اینجا می توانید اطلاعات بیشتری کسب کنید:
در نهایت، هیچ درس تعاملی بدون a کامل نمی شود حالت Sandbox! با تمام تنظیمات قبلی (و چند مورد جدید!) بازی کنید و با این ویجت باز مقداری هنر مولد ایجاد کنید:
آخرین به روز رسانی از
5 مه 2026




