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

仿Apple官网下拉菜单过渡异常:仅展开正常,收起失效

仿Apple官网下拉菜单收起时过渡失效的问题修复

问题现象

仿制Apple官网主页时,下拉菜单展开时过渡效果正常,但收起时过渡失效,视觉上显得仓促。

核心问题分析

  1. CSS过渡延迟逻辑混乱:展开时设置了正向延迟,但收起时未配置反向延迟顺序,导致多个属性同时触发收起,丢失动画层级
  2. max-height过渡局限性:收起时直接将max-height设为0,配合overflow: hidden会立刻截断内容,过渡效果被打断
  3. JS直接操作样式冲突:收起时同时修改多个样式属性,未给过渡动画留足执行时间
  4. 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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 03:54:53