با استفاده از گروه‌های انتقال نمای تودرتو، از مشکلات بریده شدن (و بیشتر) در انتقال‌های view جلوگیری کنید

تاریخ انتشار: 22 سپتامبر 2025

هنگامی که یک انتقال مشاهده را شروع می کنید، مرورگر به طور خودکار قبل و بعد از عناصر برچسب گذاری شده با یک view-transition-name عکس های فوری می گیرد. این عکس های فوری در درختی از شبه عناصر رندر می شوند. به طور پیش فرض، درخت تولید شده "مسطح" است. این به این معنی است که سلسله مراتب اصلی در DOM از بین رفته است و همه گروه‌های انتقال view گرفته شده خواهر و برادر تحت یک شبه عنصر ::view-transition هستند.

این رویکرد درخت مسطح برای بسیاری از موارد استفاده کافی است، اما موارد استفاده از یک ظاهر طراحی وجود دارد که نمی توان با آن به دست آورد. موارد زیر نمونه هایی از افکت هایی هستند که می توانند جلوه بصری غیرمنتظره ای در یک درخت صاف داشته باشند:

  • برش ( overflow ، clip-path ، border-radius ): برش بر روی فرزندان عنصر تأثیر می گذارد، به این معنی که خواهر و برادرهای گروه انتقالی view نمی توانند یکدیگر را برش دهند.
  • opacity ، mask-image و filter : به طور مشابه، این افکت‌ها به گونه‌ای طراحی شده‌اند که بر روی یک تصویر کاملاً شطرنجی‌شده از درخت کار کنند و بر روی کودکان تأثیر بگذارند، نه اینکه روی هر مورد به‌صورت جداگانه تأثیر بگذارند.
  • تبدیل‌های سه بعدی ( transform-style ، transform ، perspective ): برای نمایش دامنه کامل انیمیشن‌های تبدیل سه‌بعدی، باید سلسله مراتبی حفظ شود.

مثال زیر یک شبه درخت مسطح را نشان می دهد، با عناصری که توسط یک اجداد در درخت DOM بریده شده اند. این عناصر در طول انتقال دید، برش خود را از دست می دهند و در نتیجه جلوه بصری شکسته می شود.

ضبط یک جلوه بریده شکسته در حین اجرای یک انتقال view. متن باید توسط دیالوگ بریده شود، اما اینطور نیست. زمان انیمیشن برای اغراق در افکت کاهش می یابد.

گروه‌های انتقال نمای تودرتو، پسوندی برای مشاهده انتقال‌ها است که به شما امکان می‌دهد شبه عناصر ::view-transition-group درون یکدیگر قرار دهید. هنگامی که گروه‌های انتقال نمایش تودرتو هستند، امکان بازیابی افکت‌هایی مانند بریدن در طول انتقال وجود دارد.

Browser Support

  • کروم: 140.
  • لبه: پشتیبانی نمی شود.
  • فایرفاکس: پشتیبانی نمی شود.
  • سافاری: پشتیبانی نمی شود.

از یک شبه درخت صاف تا یک شبه درخت تو در تو

در دمو زیر می توانید روی آواتار یک شخص کلیک کنید تا اطلاعات بیشتری در مورد آن شخص ببینید. پویانمایی ها توسط یک انتقال نمای همان سند مدیریت می شوند که دکمه کلیک شده را به دیالوگ تبدیل می کند، آواتار و نام را روی صفحه حرکت می دهد و پاراگراف ها را از گفتگو به بالا یا پایین می کشد.

نسخه نمایشی زنده

ضبط نسخه ی نمایشی

ضبط نسخه ی نمایشی (کاهش سرعت)

اگر به دمو دقت کنید متوجه می‌شوید که مشکلی در انتقال وجود دارد: حتی اگر پاراگراف‌های دارای توضیحات فرزندان عنصر <dialog> در DOM هستند، متن در طول انتقال توسط کادر <dialog> s بریده نمی‌شود:

<dialog id="info_bramus" closedby="any">
  <h2><img alt="…" class="avatar" height="96" width="96" src="avatar_bramus.jpg"> <span>Bramus</span></h2>
  <p>Bramus is …</p>
  <p>…</p>
</dialog>

اعمال overflow: clip روی <dialog> نیز کاری انجام نمی دهد.

مشکل روشی است که transitions view می سازد و درخت شبه خود را ارائه می دهد:

  • در شبه درخت، به طور پیش فرض، همه عکس های فوری خواهر و برادر یکدیگر هستند.
  • شبه درخت در یک شبه عنصر ::view-transition رندر می شود که در بالای کل سند رندر می شود.

به طور خاص برای این دمو، درخت DOM به شکل زیر است:

html
  ├─ ::view-transition
  │  ├─ ::view-transition-group(card)
  │  │  └─ ::view-transition-image-pair(card)
  │  │     ├─ ::view-transition-old(card)
  │  │     └─ ::view-transition-new(card)
  │  ├─ ::view-transition-group(name)
  │  │  └─ ::view-transition-image-pair(name)
  │  │     ├─ ::view-transition-old(name)
  │  │     └─ ::view-transition-new(name)
  │  ├─ ::view-transition-group(avatar)
  │  │  └─ ::view-transition-image-pair(avatar)
  │  │     ├─ ::view-transition-old(avatar)
  │  │     └─ ::view-transition-new(avatar)
  │  ├─ ::view-transition-group(paragraph1.text)
  │  │  └─ ::view-transition-image-pair(paragraph1.text)
  │  │     └─ ::view-transition-new(paragraph1.text)
  │  └─ ::view-transition-group(paragraph2.text)
  │     └─ ::view-transition-image-pair(paragraph2.text)
  │        └─ ::view-transition-new(paragraph2.text)
  ├─ head
  └─ body
        └─ …

از آنجا که شبه‌های ::view-transition-group(.text) برادران بعدی شبه ::view-transition-group(card) هستند، در بالای کارت نقاشی می‌شوند.

برای داشتن کلیپ ::view-transition-group(card) ::view-transition-group(.text) ، شبه های ::view-transition-group(.text) باید فرزندان ::view-transition-group(card) باشند. برای این کار، view-transition-group استفاده کنید که به شما امکان می دهد یک "گروه والد" را برای یک شبه عنصر تولید شده ::view-transition-group() اختصاص دهید.

برای تغییر گروه والد دو گزینه دارید:

  • در والد، view-transition-group را contain قرار دهید تا شامل همه فرزندان با view-transition-name باشد.
  • در همه کودکان، view-transition-group روی view-transition-name والد تنظیم کنید. همچنین می توانید nearest برای هدف قرار دادن نزدیکترین گروه اجداد استفاده کنید.

بنابراین برای این دمو، برای استفاده از گروه‌های انتقال نمای تودرتو، کد به صورت زیر در می‌آید:

button.clicked,
dialog {
  view-transition-group: contain;
}

یا

button.clicked,
dialog *,
  view-transition-group: nearest;
}

با قرار دادن این کد، شبه های ::view-transition-group(.text) اکنون در داخل شبه ::view-transition-group(card) قرار می گیرند. این کار در یک شبه اضافی ::view-transition-group-children(…) انجام می شود که همه شبه های تو در تو را با هم نگه می دارد:

html
  ├─ ::view-transition
  │  ├─ ::view-transition-group(card)
  │  │  ├─ ::view-transition-image-pair(card)
  │  │  │  ├─ ::view-transition-old(card)
  │  │  │  └─ ::view-transition-new(card)
  │  │  └─::view-transition-group-children(card)
  │  │    ├─ ::view-transition-group(paragraph1.text)
  │  │    │  └─ ::view-transition-image-pair(paragraph1.text)
  │  │    │     └─ ::view-transition-new(paragraph1.text)
  │  │    └─ ::view-transition-group(paragraph2.text)
  │  │       └─ ::view-transition-image-pair(paragraph2.text)
  │  │          └─ ::view-transition-new(paragraph2.text)
  │  ├─ ::view-transition-group(name)
  │  │  └─ ::view-transition-image-pair(name)
  │  │     ├─ ::view-transition-old(name)
  │  │     └─ ::view-transition-new(name)
  │  └─ ::view-transition-group(avatar)
  │     └─ ::view-transition-image-pair(avatar)
  │        ├─ ::view-transition-old(avatar)
  │        └─ ::view-transition-new(avatar)
  ├─ head
  └─ body
        └─ …

در نهایت، برای اینکه ::view-transition-group(card) شبه پاراگراف ها را برش دهید، overflow: clip بر روی ::view-transition-group-children(card) pseudo:

::view-transition-group-children(card) {
  overflow: clip;
}

نتیجه به شرح زیر است:

نسخه نمایشی زنده

ضبط نسخه ی نمایشی

ضبط نسخه ی نمایشی (کاهش سرعت)

شبه ::view-transition-group-children فقط زمانی وجود دارد که از گروه های تودرتو استفاده شود. اندازه آن به جعبه حاشیه عنصر اصلی است و یک حاشیه شفاف با همان شکل و ضخامت حاشیه به عنوان عنصری که عنصر شبه card در مثال قبلی ایجاد کرده است، داده می شود.

برش و موارد دیگر

گروه‌های انتقال نمای تودرتو در مکان‌هایی غیر از جلوه‌های برش استفاده می‌شوند. مثال دیگر افکت های سه بعدی است. در نسخه ی نمایشی زیر گزینه ای برای چرخاندن کارت به صورت سه بعدی در حین انتقال وجود دارد.

html:active-view-transition-type(open) {
    &::view-transition-old(card) {
        animation-name: rotate-out;
    }
    &::view-transition-new(card) {
        animation-name: rotate-in;
    }
}
html:active-view-transition-type(close) {
    &::view-transition-old(card) {
        animation-name: rotate-in;
    }
    &::view-transition-new(card) {
        animation-name: rotate-out;
    }
}

بدون گروه‌های انتقال نمای تودرتو، آواتار و نام همراه با کارت نمی‌چرخند.

نسخه نمایشی زنده

ضبط نسخه ی نمایشی

ضبط نسخه ی نمایشی (کاهش سرعت)

با قرار دادن آواتار و شبه نام ها در داخل کارت، می توان جلوه سه بعدی را بازیابی کرد. اما این تنها کاری نیست که باید انجام دهید. علاوه بر چرخاندن شبه های ::view-transition-old(card) و ::view-transition-new(card) ، باید کارت ::view-transition-group-children(card) را نیز بچرخانید.

html:active-view-transition-type(open) {
    &::view-transition-group-children(card) {
        animation: rotate-in var(--duration) ease;
        backface-visibility: hidden;
    }
}
html:active-view-transition-type(close) {
    &::view-transition-group-children(card) {
        animation: rotate-out var(--duration) ease;
        backface-visibility: hidden;
    }
}

نسخه نمایشی زنده

ضبط نسخه ی نمایشی

ضبط نسخه ی نمایشی (کاهش سرعت)

دموهای بیشتر

در مثال زیر از گروه‌های انتقال نمای تودرتو استفاده می‌شود تا اطمینان حاصل شود که کارت‌ها توسط اسکرول اجدادشان بریده می‌شوند. می‌توانید با استفاده از کنترل‌های موجود، استفاده از گروه‌های انتقال نمای تودرتو را روشن یا خاموش کنید.

نسخه نمایشی زنده

ضبط نسخه ی نمایشی

نکته جالب در مورد این نسخه نمایشی این است که همه شبه‌های ::view-transition-group(.card) درون شبه اجداد ::view-transition-group(cards) قرار می‌گیرند و بریده می‌شوند. #targeted-card حذف شده است زیرا انیمیشن ورود/خروج آن نباید توسط ::view-transition-group(cards) بریده شود.

/* The .cards wrapper contains all children */
.cards {
  view-transition-name: cards;
  view-transition-group: contain;
}

/* Contents that bleed out get clipped */
&::view-transition-group-children(cards) {
  overflow: clip;
}

/* Each card is given a v-t-name and v-t-class */
.card {
  view-transition-name: match-element;
  view-transition-class: card;
}

/* The targeted card is given a unique name (to style the pseudo differently)
   and shouldn't be contained by the ::view-transition-group-children(cards) pseudo */
#targeted-card {
  view-transition-name: targeted-card;
  view-transition-group: none;
}

خلاصه

انتقال نمای تو در تو به شما اجازه می دهد تا برخی از توپولوژی درخت DOM را هنگام ساخت عناصر شبه حفظ کنید. این کار انواع افکت‌هایی را که قبلاً با انتقال view امکان‌پذیر نبود، باز می‌کند، که برخی از آنها را در اینجا توضیح دادیم.

تودرتو، مدل نحوه ایجاد انتقال‌های view را تغییر می‌دهد و قرار است برای ایجاد جلوه‌های پیشرفته استفاده شود. همانطور که اشاره شد، انتقال دید با محدوده عنصر نیز می‌تواند زیرمجموعه‌ای از افکت‌ها را با یک مدل ساده‌تر انجام دهد. ما شما را تشویق می کنیم که هر دو ویژگی را امتحان کنید تا تصمیم بگیرید که کدام یک به بهترین وجه با نیازهای شما مطابقت دارد.