How can I make CSS view-transitions respecting stacking of fixed elements

58 Views Asked by At

I'm trying to use the experimental view-transitions to animate the opening of a modal.

The problem is that there is a position: fixed menu on the page and any view-transitions get a jarring pop-in effect.

The ::view-transition-old image has a stacking context where I can't get it to interact with anything on the page, either it is below everything or above everything.

Is there any way of making the view-transition stack between elements in the DOM?

A minimal example where the popping occurs in both show and hide of the transition:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    
    <style>
      html {
      /*   z-index: 0; */
      }

      body {
        max-width: 600px;
        padding: 24px;
      /*   z-index: 1; */
      }

      .floating {
        background-color: red;
        width: 500px;
        height: 100px;
        position: fixed;
        top: 0;
      /*   z-index: 10; */
      }

      .content {
        background-color: white;
      /*   z-index: 2; */
      }

      .modal {
        display: none;
        position: fixed;
        width: 300px;
        border-width: 3px;
        border-style: solid;
        border-color: green;
        background-color: white;
        padding: 16px;
        top: 32px;
      /*   z-index: 20; */
      }

      .modal-visible .modal {
        display: block;
      }

      ::view-transition {
      /*   z-index: 3; */
      /*   position: fixed; */
      }

      ::view-transition-group(content) {
      /*   z-index: 4; */
      }

      ::view-transition-image-pair(content) {
      /*   z-index: 5; */
      }

      ::view-transition-old(content) {
        border: 3px solid blue;
      /*   z-index: 6; */
        animation-duration: 5s;
      }

      ::view-transition-new(content) {
        border: 3px solid green;
      /*   z-index: 7; */
        animation-duration: 5s;
      }
    </style>
  </head>
  <body>
    <div class="floating">
      Header
      <button>
        Transition
      </button>
    </div>
    <div class="content">
      Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
      
      Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
      
      Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
    </div>
    <div class="modal">
      Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
      
      Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
      
      Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
    </div>
    
    <script>
      
      const body = document.querySelector("body");
      const btn = document.querySelector("button");
      const content = document.querySelector(".content");
      const modal = document.querySelector(".modal");

      if (btn) {
        btn.onclick = function () {
          console.log('onclick', body)
          if(body.classList.contains('modal-visible')) {
            console.log('hide modal')
            modal.style.viewTransitionName = '';
            const transition = document.startViewTransition(() => {
              content.style.viewTransitionName = 'content';
              modal.style.viewTransitionName = '';
              body.classList.remove("modal-visible");
            });
            transition.finished.finally(() =>
              content.style.viewTransitionName = ''
            );
          } else {
            console.log('show modal')
            content.style.viewTransitionName = 'content';
            const transition = document.startViewTransition(() => {
              content.style.viewTransitionName = '';
              modal.style.viewTransitionName = 'content';
              body.classList.add("modal-visible");
            });
            transition.finished.finally(() =>
              modal.style.viewTransitionName = ''
            );
          }
        };
      }

    </script>
  </body>
</html>

0

There are 0 best solutions below