بازنویسی یه دموی ۲۰۱۴ با CSS امروزی
خلاصهٔ کاملتر
کریس کویر تعریف میکنه که به یکی از دموهای خودش از سال ۲۰۱۴ برخورده: یه اینپوت سرچ که موقع اسکرول به بالای صفحه میچسبه و استایلش هم عوض میشه تا برای منوی همبرگری جا باز کنه. اون موقع نه position: sticky بود و نه راهی برای تشخیص حالت چسبیده، برای همین همهچی روی دوش جاوااسکریپت بود.
مشکل اصلی نسخهٔ قدیمی خودِ جاوااسکریپت نیست، شیوهٔ پیادهسازیشه: یه کالبک روی رویداد scroll که با هر تکون اسکرول صدها بار اجرا میشه، هر بار به DOM دست میزنه و محاسبه میکنه — اون هم با jQuery نسخهٔ ۲.۱.۳.
قدم اول اینه که کل اون جاوااسکریپت دور ریخته میشه و کار چسبیدن به position: sticky سپرده میشه. برای تشخیص حالت چسبیده هم عنصر والد به یه کانتینر از نوع scroll-state تبدیل میشه و بعد با کوئری scroll-state(stuck: top) میشه استایل حالت چسبیده رو نوشت:
.search-area {
container-type: scroll-state;
container-name: sticky-search;
position: sticky;
top: 0;
@container scroll-state(stuck: top) {
search {
/* استایل حالت چسبیده */
}
}
}یه گیر کلاسیک اینجا هست که نویسنده بهش اشاره میکنه: استایلهای کانتینر کوئری رو نمیشه روی خودِ کانتینر نوشت، پس به یه فرزند نیاز داری. برای همین بهجای از عنصر استفاده کرده که هم اون فرزند رو بهش میده و هم یه لندمارک ARIA مجانی.
تیکهٔ بعدی، جای منوی همبرگریه. عنصر position: fixed رو نمیشه نسبت به یه عنصر دلخواه جای داد و ترفندهایی مثل زدن transform روی والد هم به نظر نویسنده معاملهٔ بدیه. راهحل امروزی، anchor positioningه: روی والد یه anchor-name تعریف میکنی و بعد عنصر ثابت رو دقیقاً نسبت به همون لنگر میچینی.
.menu-icon {
position: fixed;
position-anchor: --wrap;
top: calc(anchor(top) + 12px);
right: calc(anchor(right) + 25px);
}آخرین نکتهٔ نویسنده هم دربارهٔ خود آیکونه: دموی قدیمی از کاراکتر ☰ استفاده میکرد که به نظرش عادت بدیه، و بهتره جاش داخل یه با aria-label بذاری تا هم مارکآپ درستتری داشته باشی هم کنترل بیشتری روی شکل آیکون.
نکات کلیدی:
- لیسنر روی رویداد scroll با هر اسکرول صدها بار اجرا میشه؛ کانتینر کوئری این هزینه رو حذف میکنه
- container-type: scroll-state بهعلاوهٔ scroll-state(stuck: top) یعنی تشخیص حالت چسبیده بدون جاوااسکریپت
- استایل کانتینر کوئری روی خود کانتینر کار نمیکنه، پس به یه عنصر فرزند نیاز داری
- عنصر هم اون فرزند رو میده هم یه لندمارک ARIA مجانی
- anchor positioning جای ترفندهای transform رو برای چیدن عنصر fixed میگیره




