بازگشت به بلاگ

داخل preserve-3d، دیگر z-index وجود ندارد

چهار کارت با z-index مرتب، و یک شکل سه‌بعدی که از وسط‌شان رد می‌شد. مشکل اندازه نبود، عمق بود.

در هدر همین سایت، چهار سطح محصول دور یک نشان سه‌بعدی می‌چرخند. هر سطح z-index خودش را داشت: ۳، ۴، ۵، ۶. نشان هیچ z-indexی نداشت. طبق شهود، باید همه‌شان روی نشان می‌نشستند.

نمی‌نشستند. بازوهای نشان از وسط کارت‌ها رد می‌شد و متن‌شان را می‌بُرید.

چرا z-index کار نکرد

وقتی یک والد transform-style: preserve-3d دارد، فرزندانش دیگر در یک صفحهٔ دوبعدی روی هم چیده نمی‌شوند. مرورگر آن‌ها را در فضای سه‌بعدی مرتب می‌کند و اجازه می‌دهد همدیگر را قطع کنند. z-index در آن مرتب‌سازی حرفی برای گفتن ندارد.

نشان ما ۲۲ درجه حول محور Y روی جعبه‌ای ۴۸۰ پیکسلی چرخیده بود:

۴۸۰ ÷ ۲ × sin(۲۲°) ≈ ۹۰ پیکسل

یعنی لبه‌هایش تا حدود ۹۰ پیکسل به سمت بیننده جلو می‌آمدند، در حالی که کارت‌ها روی z = 0 بودند. برخورد، اجتناب‌ناپذیر بود.

چیزی که جواب نداد

اول نشان را کوچک کردیم — ۷۶٪ اندازهٔ قبل. تیغه‌ها همچنان از روی رسید و کارت مدیا رد می‌شدند. منطقی است: کوچک‌کردن عرض، عمق را عوض نمی‌کند.

چیزی که جواب داد

کل نشان را عقب بردیم، بیشتر از عمیق‌ترین بازویش:

.x-depth {
  position: absolute;
  inset: 0;
  transform: translateZ(-160px) scale(1.145);
  transform-style: preserve-3d;
}

آن scale تزئینی نیست. پرسپکتیو والد 1100px است، پس هر چیزی که ۱۶۰ پیکسل عقب برود به نسبت 1100 / (1100 + 160) کوچک دیده می‌شود. ضرب در معکوسش، 1260 / 1100 = 1.145، اندازهٔ دیده‌شده را دقیقاً برمی‌گرداند سر جایش.

نکتهٔ آخر: این ترنسفرم روی یک لایهٔ جداست، نه روی خود نشان. چون GSAP خود نشان را انیمیت می‌کند و ماتریس سه‌بعدی موجود را به مؤلفه‌هایش تجزیه می‌کند — یک translateZ در CSS از آن تجزیه سالم بیرون نمی‌آید.