View Transitions API: animating underneath element

162 Views Asked by At

I am using the View Transitions API to make an element grow in size and be in the center of the screen.

During the animation the element is covered by the element next to it. This happens only when the element next to it has a view-transitions-name: <some-name> applied to it. I believe this happens because a new stacking order is created when a unique name is given to the element.

Is there a way that I can have the currently animating element on top over everything else?

Here is a script that demonstrates this issue. Note at the time of writing this only works in chromium browser.

<!doctype html>
<html lang="en">

<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <meta http-equiv="X-UA-Compatible" content="ie=edge" />
  <title>Overlapping elements</title>
</head>

<body>
  <style>
    * {
      box-sizing: border-box;
    }
    
    body {
      display: grid;
      grid-template-columns: 10vw 10vw;
      gap: 1em;
    }
    
    div {
      view-transition-name: div;
      grid-column: 1;
      width: 10vw;
      height: 10vh;
      background-color: hotpink;
    }
    
    article {
      /* This view-transitions-name causes the pink box to go underneath the
           green box */
      view-transition-name: article;
      grid-column: 2;
      width: 10vw;
      height: 10vh;
      background-color: forestgreen;
    }
    
    .grow {
      view-transition-name: div;
      position: fixed;
      left: 25vw;
      top: 25vh;
      width: 50vw;
      height: 50vh;
      background-color: hotpink;
    }
  </style>
  <div></div>
  <article></article>
  <button>click me</button>
  <script>
    document.querySelector("button").addEventListener("click", () => {
      document.startViewTransition(() => {
        const element = document.createElement("section");
        element.classList.add("grow");
        document.body.appendChild(element);
        document.querySelector("div").remove();
      });
    });
  </script>
</body>

</html>

1

There are 1 best solutions below

0
On

By adding the transitions name at runtime this issue can be tackled. So every time, at runtime, you have to determine what element is ready to be animated and at the corresponding transition name.

document.querySelector("button").addEventListener("click", () => {
  // By adding the viewTransitionName like this 
  document.querySelector("div").viewTransitionName = "div";

  document.startViewTransition(() => {
    const element = document.createElement("section");
    element.classList.add("grow");
    document.body.appendChild(element);
    document.querySelector("div").remove();
  });
});
body {
  display: grid;
  grid-template-columns: 10vw 10vw;
  gap: 1em;
}

div {
  grid-column: 1;
  width: 10vw;
  height: 10vh;
  background-color: hotpink;
}

article {
  grid-column: 2;
  width: 10vw;
  height: 10vh;
  background-color: forestgreen;
}

.grow {
  view-transition-name: div;
  position: fixed;
  left: 25vw;
  top: 25vh;
  width: 50vw;
  height: 50vh;
  background-color: hotpink;
}
<div></div>
<article></article>
<button>click me</button>