انیمیشن ورود و خروج فقط با sibling-index()
خلاصهٔ کاملتر
تو این مقاله نویسنده سراغ همون مسئلهای میره که کریس تو یه سری مقالهٔ جداگانه بررسی کرده بود — انیمیشن ورود و خروج المنتها — ولی این بار با یه راهحل کاملاً CSS که حتی به view transition هم نیاز نداره. تنها جاوااسکریپتی که تو کاره، همونیه که المنت رو به DOM اضافه یا ازش حذف میکنه. نویسنده تأکید میکنه که فعلاً فقط Chrome و Edge این قابلیتها رو کامل پشتیبانی میکنن.
هستهٔ ترفند تابع sibling-index() ه که ایندکس یه المنت رو بین همنیاهاش برمیگردونه. معمولاً این ایندکس رو ثابت فرض میکنیم، ولی اگه المنتی اضافه یا حذف بشه، ایندکسها با ساختار جدید HTML بهروز میشن. مثلاً تو یه کانتینر با چهار div، اگه دومی حذف بشه، ایندکس سومی و چهارمی میشه ۲ و ۳. حالا کافیه همین ایندکس رو داخل یه property بذاری و روش transition تعریف کنی تا تغییرش تبدیل به انیمیشن بشه.
پیادهسازی پایهش واقعاً کوتاهه — همهٔ المنتها با grid-area: 1/1 روی هم قرار میگیرن و بعد بر اساس ایندکسشون جابهجا میشن:
.container div {
grid-area: 1/1;
width: 150px;
translate: calc((sibling-index() - 1)*160px);
transition: .4s;
}وقتی المنتی حذف یا اضافه میشه، ایندکسها بهروز، مقدارهای translate دوباره محاسبه و به لطف transition جابهجایی نرم اجرا میشه. برای دموی اصلی هم نویسنده فقط یه @starting-style اضافه کرده که افکت ورود المنت تازه رو کنترل میکنه — اینجا با ترکیب شفافیت و جابهجایی از چپ، ولی میتونه هر چیزی باشه:
ul > li {
grid-area: 1/1;
translate: 0 calc((sibling-index() - 1)*(100% + var(--g)));
transition: .5s;
@starting-style {
opacity: 0;
transform: translatex(-80%);
}
}نویسنده خودش ایرادهای روش رو هم میشمره. چون از translate برای جانمایی استفاده شده، عملاً با محتوای خارج از جریان طرفیم و آیتمها از کانتینرشون بیرون میزنن؛ عرض لیست درست درمیاد ولی ارتفاعش نه. ضمناً همهٔ آیتمها باید همارتفاع باشن، که grid-area: 1/1 بهزور این رو تحمیل میکنه: ارتفاع ناحیه برابر بلندترین آیتم میشه و بقیه کشیده میشن. چیدمان نمیشکنه، ولی محدودیت هست.
ایراد سوم مهمتره: این روش در واقع انیمیشن خروج نداره. با حذف یه المنت، بقیه کاملاً مرتب جابهجا میشن ولی خود المنت حذفشده هیچ انیمیشنی نمیگیره. به گفتهٔ نویسنده این خیلی هم ایراد این تکنیک نیست، چون اصلاً مکانیزم بومی CSS معادل @starting-style برای خروج وجود نداره — شاید یه روزی @ending-style بیاد. برای انیمیشن خروج واقعی باید سراغ همون روش view transition رفت.
با این حال نویسنده میگه در برابر شش خط CSS، این ترفند هنوز عالیه و چند نمونهٔ دیگه هم نشون میده: لیستی از آواتارها که با sibling-count() و واحد cqw طوری محاسبه میشن که هرچقدر تعدادشون زیاد بشه باز داخل کانتینر جا بشن و روی هم بیفتن؛ نسخهٔ دایرهای همون که بهجای translate از offset و circle() استفاده میکنه؛ و یه گرید که با دونستن عرض کانتینر و اندازهٔ آیتم، مختصات سطر و ستون هر آیتم رو با round() و mod() حساب میکنه.
تو مثال گرید یه امتیاز اضافه هم هست: علاوه بر انیمیشن موقع اضافه و حذف، تغییر اندازهٔ صفحه هم انیمیشن نرم میگیره. نویسنده حتی مشکل ارتفاع رو با گذاشتن یه div مخفی بهعنوان آخرین فرزند گرید دور زده تا کانتینر به اندازهٔ همهٔ المنتها رشد کنه — که نشون میده بسته به کاربرد، برای بیشتر ایرادهای این روش میشه راهحل پیدا کرد.
نکات کلیدی:
- sibling-index() با اضافه یا حذفشدن المنتها بهروز میشه و همین تغییر، با transition، تبدیل به انیمیشن میشه
- همهٔ آیتمها با grid-area: 1/1 روی هم میشینن و با ایندکسشون جابهجا میشن
- @starting-style افکت ورود المنت تازه رو میسازه؛ معادلی برای خروج فعلاً وجود نداره
- ایرادها: محتوای خارج از جریان، اجبار به همارتفاعبودن آیتمها و نبود انیمیشن خروج
- با sibling-count()، cqw، round() و mod() میشه همین ایده رو به چیدمان دایرهای و گریدی هم برد
- فعلاً فقط Chrome و Edge پشتیبانی کامل دارن




