Skip to content

Appending tree-structural pseudo-classes to ::view-transition shouldn't compile to a scoped selector #15312

@ccjmne

Description

@ccjmne

Issue

This code:

<style>
    ::view-transition-old:only-child {
        animation: leave-the-screen;
    }
</style>

... compiles to:

.svelte-1qc54kw::view-transition-old:only-child {
    animation-duration: leave-the-screen;
}

I believe that adding scoping this ::view-transition-old to a unique class (here .svelte-1qc54kw) is incorrect, since these pseudo-elements are always placed at the root of the document.

Prior Art

The counterpart without the :only-child tree-structural pseudo-class does indeed consider the selector to be "global-like", i.e.:

<style>
    ::view-transition-old {
        animation: translate-to-new-location;
    }
    ::view-transition-old:only-child {
        animation: leave-the-screen;
    }
</style>

... compiles to:

::view-transition-old {
    animation: translate-to-new-location;
}
.svelte-1qc54kw::view-transition-old:only-child {
    animation: leave-the-screen;
}

Motivation

The documentation for the view-transition API at developer.chrome.com employs this syntax (adding :only-child) to distinguish between the cases where:

  1. an element is both -new and -old, when it'll only play the "update" animation;
  2. either the -new or -old is the :only-child of that -pair, when it'll play a fade-in/out animation.

Reference: https://developer.chrome.com/docs/web-platform/view-transitions/same-document#view-transition-class
Specifically, see the demonstration available there: https://view-transitions.chrome.dev/cards/spa/

Work-Around

Use a :global(...) selector:

-  ::view-transition-old(the-thing):only-child {
+  :global(::view-transition-old(the-thing):only-child) {
       animation: leave-the-screen;
   }

Reproduction

I created a small app on Svelte's Playground to illustrate that issue.

https://svelte.dev/playground/dc174a9d91fd44179a48281446f1bbc0?version=5.20.1

In there, you can see that the JS "editor" (in green) doesn't use the slide-in or slide-out animations when being added/removed to the DOM when the corresponding checkbox is toggled; it'll only transition is a "cross-fade". The other two will work as expected.

The only difference is in this excerpt:

:global(::view-transition-old(editor-css):only-child) {
    animation: .3s ease-out slide-out;
}
:global(::view-transition-new(editor-css):only-child) {
    animation: .3s ease-out slide-in;
}

::view-transition-old(editor-js):only-child {
    animation: .3s ease-out slide-out;
}
::view-transition-new(editor-js):only-child {
    animation: .3s ease-out slide-in;
}

Severity

annoyance

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions