翻书交互中z-index设置视觉生效延迟问题求助
书本翻页交互:z-index更新后视觉延迟问题
我在实现可点击翻页的书本交互效果:点击页面时先判断方向,若当前不是左侧则翻至左侧,同时修改z-index维持页面层级顺序。
遇到的问题:将页面从左侧翻回右侧时,控制台显示z-index已正确更新,但视觉上要几秒后才会看到层级变化。请问遗漏了什么?
代码实现
HTML
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <link rel="stylesheet" href="style.css"> <script src="js.js" defer> </script> </head> <body> <div class="book"> <div class="cover" data-index="7" data-position="right"> cover </div> <div class="page page-1" data-index="6" data-position="right"> page 1</div> <div class="page page-2" data-index="5" data-position="right"> page 2</div> <div class="page page-3" data-index="4" data-position="right"> page 3</div> <div class="page page-4" data-index="3" data-position="right"> page 4</div> <div class="last-page" data-index="2" data-position="right">page 5</div> <div class="back-cover" data-index="1" data-position="right"></div> </div> </body> </html>
CSS
* { padding: 0; margin: 0; box-sizing: border-box; } body { height: 100vh; display: flex; align-items: center; justify-content: center; background: yellow; perspective: 1000px; } .book { display: flex; align-items: center; cursor: pointer; } .book:hover .cover{ /* transform: rotateX(10deg) rotateY(-180deg); */ } .book:hover .page{ /* transform: rotateX(10deg) rotateY(-180deg); */ /* z-index: 2; */ } .flip-to-left { transform: rotateX(10deg) rotateY(-180deg); } .flip-to-right { transform: rotateX(10deg) rotateY(0deg); } .cover { z-index: 7; /* transform: rotateX(10deg) rotateY(-180deg); */ transition: all 3s; } .page-1 { z-index: 5; } .page-2 { z-index: 4; } .page-3 { z-index: 3; } .page-4 { z-index: 2; } .last-page { z-index: 1; } .back-cover { z-index: 0; } .back-cover, .cover{ height: 300px; width: 260px; background-color: blue; border-radius: 10px; position: absolute; box-shadow: 1px 1px 10px gray; /* transform: rotateX(10deg); */ transform-origin: center left; } .last-page, .page { height: 280px; width: 250px; background: white; position: absolute; border-radius: 10px; /* transform: rotateX(10deg); */ transform-origin: center left; transition: all 3s; /* z-index: -1; */ } /* .page:nth-child(2) { transition-duration: 3s; } .page:nth-child(3) { transition-duration: 2.6s; } .page:nth-child(4) { transition-duration: 2.2s; } .page:nth-child(5) { transition-duration: 1.8s; } .page:nth-child(6) { transition-duration: 1.4s; } .book:hover .page:nth-child(2) { transition-duration: 6s; } .book:hover .page:nth-child(2) { transition-duration: 6s; } .book:hover .page:nth-child(3) { transition-duration: 5.6s; } .book:hover .page:nth-child(4) { transition-duration: 5.2s; } .book:hover .page:nth-child(5) { transition-duration: 4.8s; } .book:hover .page:nth-child(6) { transition-duration: 4.4s; } */ .last-page > div { width: 150px; border-radius: 10px; margin: 20px auto; background-color: green; position: relative; /* z-index: -1; */ }
JavaScript
const book = document.querySelector('.book'); book.addEventListener('click', e => { if (e.target.attributes['data-position'].value !== 'left') { e.target.setAttribute('data-position', 'left'); e.target.classList.remove('flip-to-right'); e.target.classList.add('flip-to-left'); setTimeout(() => { console.log (e.target.attributes['data-position'].value); // e.target.style.zIndex = e.target.attributes['data-index'].value*(-1); e.target.style.zIndex = 1; }, 1000); } else { e.target.style.zIndex = e.target.attributes['data-index'].value; e.target.classList.remove('flip-to-left'); e.target.classList.add('flip-to-right'); e.target.setAttribute('data-position', 'right'); } })
问题原因与解决方案
核心原因
你给页面元素设置了transition: all 3s,这个属性会让所有CSS属性的变化都应用3秒的过渡动画,包括z-index。所以当你把页面从左侧翻回右侧时,虽然控制台显示z-index已经更新,但视觉上需要等3秒过渡完成后才会看到层级变化。
修复步骤
- 限制过渡属性范围:把CSS中的
transition: all 3s改为只过渡transform属性,避免z-index被过渡影响。 - 调整JS逻辑:翻回右侧时直接修改z-index(现在会立即生效),翻到左侧时延迟到动画结束再修改z-index,避免翻页过程中层级错乱。
修改后的代码片段
CSS修改部分
.cover { z-index: 7; transition: transform 3s; /* 从all改为transform */ } .last-page, .page { /* ...其他样式... */ transition: transform 3s; /* 从all改为transform */ }
JavaScript修改部分
const book = document.querySelector('.book'); book.addEventListener('click', e => { const target = e.target; if (target.dataset.position !== 'left') { target.dataset.position = 'left'; target.classList.remove('flip-to-right'); target.classList.add('flip-to-left'); // 延迟时间和transform过渡时长一致,确保动画完成后再调整层级 setTimeout(() => { target.style.zIndex = 1; }, 3000); } else { // z-index现在无过渡,修改后立即生效 target.style.zIndex = target.dataset.index; target.classList.remove('flip-to-left'); target.classList.add('flip-to-right'); target.dataset.position = 'right'; } })
额外优化
- 使用
dataset属性代替attributes['data-xxx'],代码更简洁易读。 - 翻到左侧的延迟时间设为3秒,和过渡动画时长匹配,确保翻页动画完成后再把页面层级降到最低,避免动画过程中被其他页面遮挡。
内容的提问来源于stack exchange,提问作者user17833823
相关产品推荐
相关产品推荐

