İç 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

Bir 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. Varsayılan olarak, oluşturulan ağaç "düz"dür. Bu, DOM'daki orijinal hiyerarşinin kaybolduğu ve yakalanan tüm görüntüleme geçiş gruplarının tek bir ::view-transition sözde öğesi altında kardeş olduğu anlamına gelir.

Bu düz ağaç yaklaşımı birçok kullanım alanı için yeterlidir ancak bu yaklaşımla gerçekleştirilemeyen bazı stil kullanım alanları vardır. Aşağıda, düz bir ağaçta beklenmedik bir görsel etkiye sahip olabilecek efekt örnekleri 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 her öğeyi ayrı ayrı etkilemek yerine alt öğeleri etkileyerek bir ağacın tamamen rasterleştirilmiş görüntüsü üzerinde çalışacak şekilde tasarlanmıştır.
  • 3D dönüşümler (transform-style, transform, perspective): 3D dönüşüm 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üntü geçişi sırasında kırpma özelliklerini kaybeder ve bu da bozuk bir görsel efektle sonuçlanır.

Görünüm geçişi sırasında bozuk bir kırpma efektinin kaydı. Metin, iletişim kutusu tarafından kırpılmalıdır ancak kırpılmamıştır. Efekti vurgulamak için animasyon süresi yavaşlatılmıştır.

İç içe yerleştirilmiş görünüm geçiş grupları, ::view-transition-group sözde öğelerini birbirinin içine yerleştirmenize olanak tanıyan görünüm geçişleri için bir uzantıdır. Görüntüleme 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: 140.
  • Firefox: not supported.
  • Safari: not supported.

Düz bir sözde ağaçtan iç içe yerleştirilmiş bir sözde 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ı ekran boyunca hareket ettiren ve iletişim kutusundaki paragrafları yukarı veya aşağı kaydıran aynı doküman görünümü geçişi tarafından 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çıklamayı içeren paragraflar DOM'daki <dialog> öğesinin alt öğeleri olsa da metin, geçiş sırasında <dialog> 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>

<dialog> üzerinde overflow: clip uygulamak da bir işe yaramaz.

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

  • Sözde ağaçta, varsayılan olarak tüm anlık görüntüler birbirinin kardeşidir.
  • Sözde ağaç, tüm dokümanı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 öğeleri, ::view-transition-group(card) sözde öğesinin alt öğeleri olduğundan kartın üzerine boyanır.

::view-transition-group(card) öğesinin ::view-transition-group(.text) öğesini kırpması 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:

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

Bu demoda, iç içe yerleştirilmiş görünüm geç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 sayesinde ::view-transition-group(.text) sözde öğeleri artık ::view-transition-group(card) sözde öğesinin içine yerleştirilir. Bu işlem, tüm iç içe yerleştirilmiş sözde öğeleri bir arada tutan ek bir ::view-transition-group-children(…) sözde öğesinde yapılır:

html
  ├─ ::view-transition
  │  ├─ ::view-transition-group(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-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)
  ├─ head
  └─ body
        └─ …

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

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

Sonuç şu şekildedir:

Canlı Demo

Demo Kaydı

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

::view-transition-group-children sözde öğesi yalnızca iç içe yerleştirilmiş gruplar kullanıldığında mevcuttur. Orijinal öğenin kenarlık kutusuna göre boyutlandırılır ve sözde öğeyi oluşturan öğeyle (önceki örnekte 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ş grupları, kırpma efektleri dışındaki yerlerde kullanılır. Başka bir örnek de 3 boyutlu efektidir. 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 yerleştirilmiş görünüm geçiş grupları olmadan avatar ve ad, kartla birlikte dönmez.

Canlı Demo

Demo Kaydı

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

Avatar ve ad sözde öğelerini kartın içine yerleştirerek 3D efekti geri yüklenebilir. Ancak yapmanız gereken tek şey bu değil. ::view-transition-old(card) ve ::view-transition-new(card) sözde anahtarlarını rotasyona tabi tutmanın yanı sıra ::view-transition-group-children(card) anahtarını da rotasyona tabi tutmanız 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 kaydırıcıları tarafından kırpılmasını sağlamak için iç içe yerleştirilmiş görünüm geçiş grupları kullanılmıştır. İç içe yerleştirilmiş görünüm geçiş gruplarının kullanımını, dahil edilen kontrolleri kullanarak açıp kapatabilirsiniz.

Canlı Demo

Demo Kaydı

Bu demonun ilginç yanı, tüm ::view-transition-group(.card) sözde öğelerinin üst ::view-transition-group(cards) sözde öğesinin içine yerleştirilmesi ve bu öğe tarafından kırpılmasıdır. #targeted-card, giriş/çıkış animasyonunun ::view-transition-group(cards) tarafından kırpılmaması gerektiği için 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 yerleştirilmiş 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 sayede, daha önce görüntüleme geçişleriyle mümkün olmayan çeşitli efektler kullanılabilir. Bunlardan bazılarını burada açıkladık.

İç içe yerleştirme, görüntüleme 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.