افکت شکست نور پسزمینه با CSS view()
خلاصهٔ کاملتر
نویسنده اول مشکل روش قدیمی رو توضیح میده. برای ساختن حس شکست نور، معمولاً یه تصویر پسزمینهٔ یکسان با background-attachment: fixed هم به المان پسزمینه و هم به کارت داخلش داده میشه و یه جابهجایی کوچیک تو یکیشون اون حس عدسی رو میسازه. ایراد کار اینه که تصویر نسبت به ویوپورت جا میگیره، نه نسبت به خود المان. یعنی برای اینکه تصویر درست بشینه باید ابعاد و مهمتر از اون موقعیت المان روی صفحه رو تو CSS بدونی، که تو یه لایوت ریسپانسیو کار سختیه.
راهحل مقاله استفاده از view() هست، یعنی همون تایملاینی که میزان دیدهشدن یه المان رو داخل نزدیکترین اسکرولکانتینرش دنبال میکنه. اگه خود المان پسزمینه رو به یه اسکرولکانتینر تبدیل کنی (فقط با overflow: hidden)، بچههاش میتونن پسزمینهشون رو بر اساس موقعیتشون داخل همون کانتینر جابهجا کنن. نکتهٔ جالب اینه که برای این ترفند اصلاً لازم نیست چیزی واقعاً اسکرول بشه.
کارت پسزمینه رو از کانتینر inherit میکنه و دو انیمیشن روش سوار میشه: یکی برای محور افقی و یکی برای عمودی. سه شرط مهمه: تایمینگ باید linear باشه تا پیشروی انیمیشن ثابت بمونه، animation-range باید contain باشه تا لبههای کانتینر مرجع بمونن، و چون view() هر بار فقط یه جهت رو مدیریت میکنه، برای x و y دو تایملاین جدا لازمه.
#card {
background: inherit;
animation: pos-x linear, pos-y linear;
animation-timeline: view(x), view(y);
animation-range: contain;
}چیزی که انیمیت میشه خودِ background-position کارته. با این دو کیفریم، دقیقاً همون تکه از تصویر کانتینر که کارت روش نشسته میشه پسزمینهٔ کارت.
@keyframes pos-x {
from { background-position-x: 100%; }
}
@keyframes pos-y {
from { background-position-y: 100%; }
}تا اینجا تصویر فقط همتراز شده و هنوز خبری از شکست نور نیست. خود افکت با یه تغییر کوچیک ساخته میشه: یا background-size کارت رو با calc کمی کوچیکتر از کانتینر میکنی، یا مقدار کیفریمها رو از ۱۰۰٪ به ۸۵٪ میبری تا تصویر داخل کارت کمی آفست بشه. بعدش میشه لایههای blur و سایه و skew رو هم روش گذاشت تا گلسمورفیسم کاملتری در بیاد. چون پایهٔ کار view() هست، اگه کارت واقعاً اسکرول بشه پسزمینهش هم خودکار بهروز میمونه.
نکات کلیدی:
- view() میزان دیدهشدن یه المان رو داخل نزدیکترین اسکرولکانتینرش دنبال میکنه.
- overflow: hidden کافیه تا کانتینر اسکرولکانتینر بشه؛ اسکرول واقعی لازم نیست.
- هر تایملاین view() فقط یه محور رو پوشش میده، پس برای x و y دو انیمیشن جدا لازمه.
- تایمینگ linear و animation-range: contain شرط همترازی درستن.
- افکت شکست نور با کوچیککردن background-size یا آفستدادن به background-position ساخته میشه.
- روش قدیمی با background-attachment: fixed تصویر رو به ویوپورت میچسبونه و تو لایوت ریسپانسیو دردسر داره.




