İç içe yerleştirilmiş görünüm geçişi grupları kullanarak görünüm geçişlerinde kırpma sorunlarını (ve daha fazlasını) önleme

Yayınlanma tarihi: 22 Eylül 2025

Görünüm geçişi başlattığınızda tarayıcı, view-transition-name ile etiketlenmiş öğelerin öncesi ve sonrası anlık görüntülerini otomatik olarak alır. Bu anlık görüntüler, sözde öğelerden oluşan bir ağaçta oluşturulur. Oluşturulan ağaç varsayılan olarak "düz" olur. Bu durumda, DOM'daki orijinal hiyerarşi kaybolur ve yakalanan tüm görünüm geçişi grupları tek bir ::view-transition sözde öğesi altında kardeş öğeler olur.

Bu düz ağaç yaklaşımı birçok kullanım alanı için yeterli olsa da bazı stil kullanım alanlarında bu yaklaşımla istenen sonuç elde edilemez. Aşağıda, düz ağaçta beklenmedik görsel etkilere neden olabilecek efektlere örnekler verilmiştir:

  • Kırpma (overflow, clip-path, border-radius): Kırpma, öğenin alt öğelerini etkiler. Bu nedenle, görünüm geçişi grubu kardeşleri birbirini kırpamaz.
  • opacity, mask-image ve filter: Benzer şekilde, bu efektler de her öğeyi ayrı ayrı etkilemek yerine, ağacın tamamen rasterleştirilmiş bir görüntüsünde çalışacak şekilde tasarlanmıştır ve alt öğeleri etkiler.
  • 3D dönüştürmeler (transform-style, transform, perspective): 3D dönüştürme animasyonlarının tamamını görüntülemek için belirli bir hiyerarşinin korunması gerekir.

Aşağıdaki örnekte, DOM ağacındaki bir üst öğe tarafından kırpılan öğeleri içeren düz bir sözde ağaç gösterilmektedir. Bu öğeler, görünüm geçişi sırasında kırpma özelliğini kaybederek bozuk bir görsel efekt oluşturur.

Görünüm geçişi çalışırken bozuk bir kırpma efektinin kaydı. Metin, iletişim kutusu tarafından kırpılmalıdır ancak kırpılmıyor. Efekti abartmak için animasyon süresi yavaşlatılır.

İç içe görünüm geçişi grupları, görünüm geçişlerinin bir uzantısıdır ve ::view-transition-group sözde öğelerini iç içe yerleştirmenize olanak tanır. Görünüm geçişi grupları iç içe yerleştirildiğinde, geçiş sırasında kırpma gibi efektleri geri yüklemek mümkündür.

Browser Support

  • Chrome: 140.
  • Edge: not supported.
  • Firefox: not supported.
  • Safari: not supported.

Düz bir sahte ağaçtan iç içe yerleştirilmiş bir sahte ağaca

Aşağıdaki demoda, bir kişinin avatarını tıklayarak o kişi hakkında daha fazla bilgi edinebilirsiniz. Animasyonlar, tıklanan düğmeyi iletişim kutusuna dönüştüren, avatarı ve adı ekranda hareket ettiren ve iletişim kutusundaki paragrafları yukarı veya aşağı kaydıran aynı belge görünümü geçişiyle işlenir.

Canlı Demo

Demo Kaydı

Demo Kaydı (Yavaşlatılmış)

Demoya yakından bakarsanız geçişle ilgili bir sorun olduğunu görürsünüz: Açıklama içeren paragraflar DOM'daki <dialog> öğesinin alt öğeleri olsa da metin, geçiş sırasında <dialog> öğesinin kutusu tarafından kırpılmaz:

<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 simgesini <dialog> üzerinde uygulamak da herhangi bir işlem yapmaz.

Sorun, görünüm geçişlerinin sözde ağaçlarını oluşturma ve oluşturma şeklinden kaynaklanmaktadır:

  • Sözde ağaçta, varsayılan olarak tüm anlık görüntüler birbirinin kardeşidir.
  • Sözde ağaç, dokümanın tamamının üzerinde oluşturulan bir ::view-transition sözde öğesinde oluşturulur.

Bu demo için DOM ağacı aşağıdaki gibi görünür:

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) sözde sınıfları, ::view-transition-group(card) sözde sınıflarının kardeşleri olduğu için kartın üzerine çizilir.

::view-transition-group(card) klibi ::view-transition-group(.text) için ::view-transition-group(.text) sözde öğeleri, ::view-transition-group(card) öğesinin alt öğeleri olmalıdır. Bunun için, oluşturulan bir ::view-transition-group() sözde öğesine "üst grup" atamanıza olanak tanıyan view-transition-group özelliğini kullanın.

Üst grubu değiştirmek için iki seçeneğiniz vardır:

  • view-transition-name içeren tüm alt öğeleri içermesi için üst öğede view-transition-group özelliğini contain olarak ayarlayın.
  • Tüm alt öğelerde view-transition-group değerini üst öğenin view-transition-name değerine ayarlayın. En yakın üst grubu hedeflemek için nearest simgesini de kullanabilirsiniz.

Bu nedenle, bu demoda iç içe görünüm geçişi gruplarını kullanmak için kod şu şekilde olur:

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

Alternatif seçenek:

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

Bu kod yerleştirildiğinde, ::view-transition-group(.text) sözde sınıfları artık ::view-transition-group(card) sözde sınıfının içine yerleştirilir. Bu işlem, tüm iç içe yerleştirilmiş sözde sınıfları bir arada tutan ek bir ::view-transition-group-children(…) sözde sınıfında yapılır:

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
        └─ …

Son olarak, ::view-transition-group(card) sözde öğesinin paragrafları kırpması için overflow: clip sözde öğesini ::view-transition-group-children(card) sözde öğesine uygulayın:

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

Sonuç şöyledir:

Canlı Demo

Demo Kaydı

Demo Kaydı (Yavaşlatılmış)

::view-transition-group-children sahtesi yalnızca iç içe yerleştirilmiş gruplar kullanıldığında bulunur. Orijinal öğenin border-box'ına göre boyutlandırılır ve sözde öğeyi oluşturan öğeyle (önceki örnekteki card) aynı şekle ve kenarlık kalınlığına sahip şeffaf bir kenarlık verilir.

Kırpma ve daha fazlası

İç içe yerleştirilmiş görünüm geçişi grupları, kırpma efektleri dışında yerlerde kullanılır. 3D efektler de başka bir örnektir. Aşağıdaki demoda, geçiş sırasında kartı 3D olarak döndürme seçeneği vardır.

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;
    }
}

İç içe görünüm geçişi grupları olmadan, avatar ve ad kartla birlikte dönmez.

Canlı Demo

Demo Kaydı

Demo Kaydı (Yavaşlatılmış)

Avatar ve ad takma adları kartın içine yerleştirerek 3D efekt geri yüklenebilir. Ancak yapmanız gereken tek şey bu değil. ::view-transition-old(card) ve ::view-transition-new(card) sahtelerini döndürmenin yanı sıra ::view-transition-group-children(card) sahtesini de döndürmeniz gerekir.

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;
    }
}

Canlı Demo

Demo Kaydı

Demo Kaydı (Yavaşlatılmış)

Daha fazla demo

Aşağıdaki örnekte, kartların üst öğe kaydırıcı tarafından kırpıldığından emin olmak için iç içe görünüm geçişi grupları kullanılmaktadır. İç içe yerleştirilmiş görünüm geçişi gruplarının kullanımını, sağlanan kontrolleri kullanarak etkinleştirebilir veya devre dışı bırakabilirsiniz.

Canlı Demo

Demo Kaydı

Bu demoyla ilgili ilginç nokta, tüm ::view-transition-group(.card) sözde öğelerinin, üst öğe ::view-transition-group(cards) sözde öğesinin içine yerleştirilip bu öğe tarafından kırpılmasıdır. #targeted-card animasyonu, giriş/çıkış animasyonu ::view-transition-group(cards) tarafından kırpılmaması gerektiğinden hariç tutulur.

/* 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;
}

Özet

İç içe görünüm geçişleri, sözde öğeleri oluştururken DOM ağacının topolojisinin bir kısmını korumanıza olanak tanır. Bu, görüntüleme geçişleriyle daha önce mümkün olmayan çeşitli efektlerin kullanılmasını sağlar. Bu efektlerden bazılarını burada açıkladık.

İç içe yerleştirme, görünüm geçişlerinin oluşturulma modelini değiştirir ve gelişmiş efektler oluşturmak için kullanılır. Belirtildiği gibi, öğe kapsamlı görünüm geçişleri de daha basit bir modelle efektlerin bir alt kümesini gerçekleştirebilir. İhtiyaçlarınıza en uygun olanı belirlemek için her iki özelliği de denemenizi öneririz.