You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用View Transitions API过渡时z-index失效问题求助

问题求助:View Transitions API 堆叠顺序问题

注意:以下示例使用View Transitions API,该API尚未被所有浏览器支持。在Firefox中,此代码不会执行过渡效果,因此无法复现我遇到的问题。

想要实现的功能

使用View Transitions API实现两个元素间的过渡效果:用户点击列表项时,以流畅过渡的方式在列表上方打开类模态框详情页。

遇到的问题

该API似乎无法很好地遵循堆叠顺序(z-index)。最严重的问题是.overlay.backdrop遮罩层会覆盖处于过渡状态的元素,只有过渡完成后,目标元素才会显示在遮罩层上方。此外,我也无法让选中的元素在过渡过程中显示在其他列表项之上。

提示:在Chrome开发者工具中将动画速度设置为10%,可以更清晰地观察问题。
动画速度设置

已尝试的方案

  • 尝试过调整DOM结构和元素的z-index值。
  • 尝试使用CSS伪元素::view-transition-group,但由于我是动态设置过渡名称,不确定是否适用。

我实在不知道该如何进一步调试此问题。

代码示例

JavaScript

const { ref } = Vue;

const app = Vue.createApp({
  setup() {
    const items = [
      {
        id: 1,
        title: 'Diablo 4',
        description: 'A shit game with a decent story',
      },
      {
        id: 2,
        title: 'Elden Ring',
        description: 'A good game with a shit story',
      },
      {
        id: 3,
        title: 'The Witcher 3',
        description: 'A good game with a good story',
      },
      {
        id: 4,
        title: 'Cyberpunk 2077',
        description: 'A shit game with a shit story',
      },
    ];

    const activeItem = ref(null);

    const setActiveItem = (item) => {
      if (!document.startViewTransition) {
        activeItem.value = activeItem.value === item ? null : item;
        return;
      }

      document.startViewTransition(() => {
        activeItem.value = activeItem.value === item ? null : item;
      });
    };

    return {
      items,
      activeItem,
      setActiveItem
    };
  }
});

app.mount('#app');

CSS

.box {
  background-color: lightblue;
  cursor: pointer;
  position: relative;
  z-index: 1;
}

.box.small {
  padding: 1rem;
}

.box.big {
  padding: 2rem;
  font-size: 1.5rem;
  margin: 2rem;
}

.grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 1rem;
  padding: 1rem;
}

.overlay {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  z-index: 11;
}

.overlay.backdrop {
  view-transition-name: overlay;
  background: rgba(0, 0, 0, 0.5);
  z-index: 10;
}

body {
  margin: 0;
  display: grid;
  place-items: center;
  min-width: 320px;
  min-height: 100vh;
}

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/3.5.4/vue.global.min.js"></script>

<div id="app">
  <!-- Detail view (overlay) -->
  <div>
    <div class="overlay backdrop" v-if="activeItem"></div>
    <div class="overlay" v-if="activeItem" @click="setActiveItem(null)">
      <div class="box big" :style="{ viewTransitionName: `box-${activeItem.id}` }">
        <span :style="{ viewTransitionName: `title-${activeItem.id}` }">
          {{ activeItem.title }}
        </span>
        <p>{{ activeItem.description }}</p>
      </div>
    </div>
    <!-- List view -->
    <div class="grid">
      <div v-for="item in items" :key="item.id" class="box small" @click="setActiveItem(item)"
        :style="{ 
          viewTransitionName: activeItem?.id === item.id ? '' : `box-${item.id}`,
          visibility: activeItem?.id === item.id ? 'hidden' : 'visible',
        }">
        <span :style="{ viewTransitionName: activeItem?.id === item.id ? '' : `title-${item.id}` }">
          {{ item.title }}
        </span>
      </div>
    </div>
  </div>
</div>

有没有人能提供解决思路?


内容的提问来源于stack exchange,提问作者Awesom-o

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 17:31:06