Gepubliceerd: 22 september 2025
Wanneer je een weergaveovergang start, maakt de browser automatisch momentopnamen van de elementen met de tag ` view-transition-name vóór en na de overgang. Deze momentopnamen worden weergegeven in een boomstructuur van pseudo-elementen. Standaard is de gegenereerde boomstructuur 'plat'. Dit betekent dat de oorspronkelijke hiërarchie in de DOM verloren gaat en dat alle vastgelegde weergaveovergangsgroepen onder één enkel pseudo-element ::view-transition vallen.
Deze platte boomstructuur is voldoende voor veel toepassingen, maar er zijn bepaalde stylingmogelijkheden die er niet mee gerealiseerd kunnen worden. De volgende voorbeelden illustreren effecten die een onverwacht visueel effect kunnen hebben in een platte boomstructuur:
- Clipping (
overflow,clip-path,border-radius): clipping heeft invloed op de kinderen van het element, wat betekent dat sibling-elementen in een view transition group elkaar niet kunnen clippen. -
opacity,mask-imageenfilter: deze effecten zijn eveneens ontworpen om te werken op een volledig gerasterde afbeelding van een boom, waarbij ze de kinderen beïnvloeden in plaats van elk item afzonderlijk. - 3D-transformaties (
transform-style,transform,perspective): om het volledige scala aan 3D-transformatie-animaties weer te geven, moet een bepaalde hiërarchie worden aangehouden.
Het volgende voorbeeld toont een platte pseudo-boom, met elementen die worden afgesneden door een voorouder in de DOM-boom. Deze elementen verliezen hun afsnijding tijdens de overgang tussen weergaven, wat resulteert in een verstoord visueel effect.
Geneste weergaveovergangsgroepen is een uitbreiding op weergaveovergangen waarmee u pseudo-elementen van het ::view-transition-group in elkaar kunt nesten. Wanneer weergaveovergangsgroepen genest zijn, is het mogelijk om effecten zoals clipping tijdens de overgang te herstellen.
Browser Support
Van een platte pseudo-boom naar een geneste pseudo-boom
In de volgende demo kunt u op de avatar van een persoon klikken om meer informatie over die persoon te bekijken. De animaties worden afgehandeld door een overgang binnen hetzelfde document, waarbij de aangeklikte knop verandert in het dialoogvenster, de avatar en naam over het scherm bewegen en de alinea's in het dialoogvenster omhoog of omlaag schuiven.
Live demonstratie
Demo-opname
Demo-opname (vertraagd)
Als je de demo goed bekijkt, zie je dat er een probleem is met de overgang: hoewel de alinea's met de beschrijving kinderen zijn van het <dialog> -element in de DOM, wordt de tekst niet afgesneden door het <dialog> -vak tijdens de overgang.
<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>
Het toepassen van overflow: clip op het <dialog> heeft ook geen effect.
Het probleem zit hem in de manier waarop weergaveovergangen hun pseudo-boom opbouwen en weergeven:
- In de pseudo-boom zijn alle snapshots standaard broers en zussen van elkaar.
- De pseudo-boomstructuur wordt weergegeven in een
::view-transitionpseudo-element dat bovenop het gehele document wordt weergegeven.
Voor deze specifieke demo ziet de DOM-structuur er als volgt uit:
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
└─ …
Omdat de ::view-transition-group(.text) pseudo's opeenvolgende broers en zussen zijn van de ::view-transition-group(card) pseudo, worden ze bovenop de kaart getekend.
Om ::view-transition-group(card) te laten clippen op ::view-transition-group(.text) , moeten de ::view-transition-group(.text) pseudo-elementen kinderen zijn van ::view-transition-group(card) . Gebruik hiervoor view-transition-group , waarmee je een "oudergroep" kunt toewijzen aan een gegenereerd ::view-transition-group() pseudo-element.
Om de bovenliggende groep te wijzigen, hebt u twee opties:
- Stel op het bovenliggende element de
view-transition-groupin opcontain, zodat deze alle onderliggende elementen met eenview-transition-namebevat. - Stel voor alle kinderen de
view-transition-groupin op deview-transition-namevan de ouder. Je kunt ooknearestgebruiken om de dichtstbijzijnde vooroudergroep te selecteren.
Voor deze demo, om geneste weergaveovergangsgroepen te gebruiken, wordt de code als volgt:
button.clicked,
dialog {
view-transition-group: contain;
}
Of
button.clicked,
dialog *,
view-transition-group: nearest;
}
Met deze code worden de ::view-transition-group(.text) pseudo's nu genest binnen de ::view-transition-group(card) pseudo. Dit gebeurt in een extra ::view-transition-group-children(…) pseudo, die alle geneste pseudo's bij elkaar houdt:
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
└─ …
Om er tot slot voor te zorgen dat de pseudo-paragrafen worden afgeknipt met ::view-transition-group(card) , pas je overflow: clip toe op de pseudo-paragraaf ::view-transition-group-children(card) :
::view-transition-group-children(card) {
overflow: clip;
}
Het resultaat is als volgt:
Live demonstratie
Demo-opname
Demo-opname (vertraagd)
Het pseudo-element ::view-transition-group-children is alleen aanwezig wanneer geneste groepen worden gebruikt. Het heeft de afmetingen van de border-box van het oorspronkelijke element en krijgt een transparante rand met dezelfde vorm en dikte als het element dat het pseudo-element heeft gegenereerd ( card in het vorige voorbeeld).
Knippen en meer
Geneste overgangsgroepen worden ook op andere plekken gebruikt dan bij knipeffecten. Een ander voorbeeld zijn 3D-effecten. In de volgende demo is er een optie om de kaart tijdens de overgang in 3D te roteren.
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;
}
}
Zonder geneste overgangsgroepen voor weergaven roteren de avatar en de naam niet mee met de kaart.
Live demonstratie
Demo-opname
Demo-opname (vertraagd)
Door de avatar- en naampseudo's in de kaart te nesten, kan het 3D-effect worden hersteld. Maar dat is niet het enige wat je moet doen. Naast het roteren van de ::view-transition-old(card) en ::view-transition-new(card) pseudo's, moet je ook de ::view-transition-group-children(card) pseudo roteren.
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;
}
}
Live demonstratie
Demo-opname
Demo-opname (vertraagd)
Meer demo's
In het volgende voorbeeld worden geneste weergaveovergangsgroepen gebruikt om ervoor te zorgen dat de kaarten worden afgesneden door de scrollbalk van het bovenliggende element. U kunt het gebruik van geneste weergaveovergangsgroepen in- of uitschakelen met behulp van de meegeleverde besturingselementen.
Live demonstratie
Demo-opname
Het interessante aan deze demo is dat alle ::view-transition-group(.card) pseudo's genesteld worden in – en afgesneden worden door – de voorouder ::view-transition-group(cards) pseudo. De #targeted-card pseudo is hiervan uitgezonderd, omdat de in- en uitgaande animatie ervan niet afgesneden mag worden door de ::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;
}
Samenvatten
Geneste weergaveovergangen stellen je in staat om een deel van de topologie van de DOM-boom te behouden bij het construeren van de pseudo-elementen. Dit maakt een verscheidenheid aan effecten mogelijk die voorheen niet mogelijk waren met weergaveovergangen, waarvan we er hier een aantal hebben beschreven.
Geneste elementen veranderen de manier waarop overgangen tussen weergaven worden geconstrueerd en zijn bedoeld om geavanceerde effecten te creëren. Zoals gezegd kunnen overgangen tussen weergaven op elementniveau ook een deel van de effecten bereiken met een eenvoudiger model. We raden u aan beide functies uit te proberen om te bepalen welke het beste bij uw behoeften past.