仿Apple官网下拉菜单过渡异常:仅展开正常,收起失效
仿Apple官网下拉菜单收起时过渡失效的问题修复
问题现象
仿制Apple官网主页时,下拉菜单展开时过渡效果正常,但收起时过渡失效,视觉上显得仓促。
核心问题分析
- CSS过渡延迟逻辑混乱:展开时设置了正向延迟,但收起时未配置反向延迟顺序,导致多个属性同时触发收起,丢失动画层级
max-height过渡局限性:收起时直接将max-height设为0,配合overflow: hidden会立刻截断内容,过渡效果被打断- JS直接操作样式冲突:收起时同时修改多个样式属性,未给过渡动画留足执行时间
- CSS语法错误:原代码中
transition属性存在.0.3s的无效写法
修复方案
1. 重构CSS:用类控制状态,统一过渡逻辑
避免直接通过JS修改样式,改用类切换状态,让过渡规则更清晰:
.drop-down { position: fixed; z-index: 1; width: 100%; height: 94%; opacity: 0; margin-top: 6%; left: 0; bottom: 0; right: 0; background-color: rgba(22, 22, 23, 0.325); -webkit-backdrop-filter: blur(2px); backdrop-filter: blur(2px); transition: opacity 0.3s ease-in-out, backdrop-filter 0.3s ease-in-out; overflow-y: hidden; } .drop-down.active { opacity: 1; -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px); transition-delay: 0s, 0.1s; } .drop-down-str { width: 100%; max-height: 0; background-color: rgba(22, 22, 23, 0.982); transition: max-height 0.3s ease-in-out; overflow-y: hidden; } .drop-down-str.active { max-height: 1000px; /* 用固定大值替代100%,解决百分比过渡失效问题 */ transition-delay: 0.1s; } .str-txt { width: 100%; display: flex; flex-direction: row; font-family: SF Pro Display, SF Pro Icons, Helvetica Neue, Helvetica, Arial, sans-serif; max-height: 0; opacity: 0; overflow-y: hidden; padding: 0; transition: opacity 0.3s ease-in-out, max-height 0.3s ease-in-out, padding 0.3s ease-in-out; } .str-txt.active { opacity: 1; max-height: 1000px; padding-left: calc((100vw - 1035px) / 2 + 17px); padding-top: 44px; padding-bottom: calc(6em - 19px); transition-delay: 0.2s, 0.15s, 0.15s; } #str{ padding: 0; border: 1px solid red; margin-right: 3em; opacity: 0; transition: margin-right 0.3s ease-in-out, opacity 0.3s ease-in-out; overflow-y: hidden; } #str.active { opacity: 1; transition-delay: 0.3s, 0.3s; } #str-li-1 { margin-bottom: 13px; transition: margin-bottom 0.3s ease-in-out; } #str-li-1.active { margin-bottom: 19px; transition-delay: 0.4s; } .gen-drop-2 { height: 0; width: 100%; transition: height 0.3s ease-in-out; } .gen-drop-2.active { height: 100vh; } .Nav { background: rgba(22, 22, 23, .8); transition: background 0.3s ease-in-out; } .Nav.active { background: rgba(22, 22, 23, 0.982); }
2. 简化JS逻辑:仅切换类名
const store = document.querySelector(".store"); const dropD = document.querySelector(".drop-down"); const dropDStr = document.querySelector(".drop-down-str"); const genDrop2 = document.querySelector(".gen-drop-2"); const nav = document.querySelector(".Nav"); const appl = document.querySelector(".appleLogo"); const strTxt = document.querySelector(".str-txt"); const strElements = document.querySelectorAll("#str"); const strLiElements = document.querySelectorAll("#str-li-1"); // 展开菜单:添加所有active类 function grow() { dropD.classList.add('active'); dropDStr.classList.add('active'); genDrop2.classList.add('active'); nav.classList.add('active'); strTxt.classList.add('active'); strElements.forEach(el => el.classList.add('active')); strLiElements.forEach(el => el.classList.add('active')); } // 收起菜单:按反向顺序移除类,触发平滑过渡 function shrink() { strLiElements.forEach(el => el.classList.remove('active')); strElements.forEach(el => el.classList.remove('active')); strTxt.classList.remove('active'); dropDStr.classList.remove('active'); genDrop2.classList.remove('active'); nav.classList.remove('active'); dropD.classList.remove('active'); } // 事件监听保持不变 store.addEventListener('mouseenter', grow); genDrop2.addEventListener('mouseenter', shrink); appl.addEventListener('mouseenter', shrink); window.addEventListener('mouseout', (event) => { const toElement = event.toElement || event.relatedTarget; if (!toElement || toElement.nodeName === 'HTML') { shrink(); } }); window.addEventListener('scroll', shrink);
3. 关键优化说明
- 用
max-height: 1000px替代100%:解决max-height对百分比值过渡支持不佳的问题 - 反向过渡顺序:收起时先隐藏文字,再收缩容器,最后隐藏背景,与展开顺序完全相反,保证动画连贯性
- 统一类控制:避免JS直接操作样式,减少样式冲突,便于维护
- 修复CSS语法错误:修正了原代码中
transition属性的无效延迟写法
内容的提问来源于stack exchange,提问作者Godwin Marvellous
相关产品推荐
相关产品推荐

