使用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
相关产品推荐
相关产品推荐

