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

求助:使用translate(x)+transition实现带X/Y轴动画的飞出/滑动主菜单

求助:使用translate(x)+transition实现带X/Y轴动画的飞出/滑动主菜单

嗨,我完全懂你想把老旧的菜单动画升级成更现代的translate(x)+transition方案的需求,而且还希望菜单展开/收缩时同时有X轴滑动和Y轴高度变化的双重动画,这确实能让交互体验顺滑不少!我来给你梳理下实现思路,再附上完整的可运行代码示例,你可以直接参考调整。

核心实现思路

  • 用transform: translateX()替代margin控制水平位置:margin的过渡性能不如transform,而且transform不会触发重排,动画更流畅
  • 用max-height模拟高度过渡:CSS没法直接过渡height: auto,所以可以给菜单设置一个足够大的max-height值(比如菜单展开后的实际高度+余量),默认设为0,展开时切换到这个大值,配合transition实现高度动画
  • 统一用CSS类/状态控制样式:把菜单展开/收缩的样式都写在CSS里,JS只负责切换aria-expanded状态,符合“样式归CSS,交互归JS”的原则
  • 保留无障碍属性:aria-expanded和aria-controls这些属性别丢,保证菜单的可访问性

完整代码示例

<div id="wrap">
  <div id="navi-span">
    <nav id="main-nav" class="site-navigation" tabindex="-1">
      <button id="toggle" aria-expanded="false" aria-controls="menu">
      </button>
      <ul id="menu">
        <li><a aria-current="page" class='menu nav-highlight' href='#'>Aktuelles</a></li>
        <li><a class='menu' href='#'>Arbeiten</a></li>
        <li><a class='menu' href='#'>CV</a></li>
        <li><a class='menu' href='#'>Ausstellungen</a></li>
        <li><a class='menu' href='#'>Texte</a></li>
        <li><p></p></li>
        <li><a class="menu" href='#'>Max Mustermann</a></li>
        <li><a class="menu" href="/logout.php?csrf_token=c1f0d62e91ef9653d66f2fde34163834">abmelden</a></li>
      </ul>
    </nav>
  </div>
</div>

<style>
#wrap {
  max-width: 70rem;
  height: 100%;
  min-height: 100vh;
  margin: 0 auto;
  display: flex;
  justify-content: flex-end;
  background: rgba(205,192,176,0.4);
}

[aria-expanded] {
  width:45px;
  height: 45px;
  background: transparent;
  border: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 9 9'%3E%3Cpath d='M1,2 h7 M1,5 h7 M1,8 h7' fill='none' stroke='black' stroke-width='2' stroke-linecap='round'/%3E%3C/svg%3E");
  cursor: pointer;
  margin: 0.7rem;
}

[aria-expanded="true"] {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 9 9'%3E%3Cpath d='M2,2 l6,6 M8,2 l-6,6' fill='none' stroke='%23c82f04' stroke-width='2' stroke-linecap='round'/%3E%3C/svg%3E");
}

#navi-span {
  width: 25rem;
  display: flex;
  justify-content: flex-end;
  height: fit-content;
  overflow: hidden;
}

#main-nav {
  display: flex;
  justify-content: flex-end;
  flex-basis: auto;
  height: auto;
  position: relative;
}

#main-nav > * {
  font-size: 1.55rem;
  font-weight: bold; /* 修复原代码里的错误:font-style不能设置bold,应该用font-weight */
}

#menu {
  margin-top: 1em;
  margin-left: 1em;
  padding: 0.4em 0.9em;
  border: dashed 5px red;
  list-style: none;
  background: rgba(190,190,190,0.2);
  /* 初始状态:隐藏高度+向左平移 */
  max-height: 0;
  transform: translateX(-12em);
  transition: 
    transform 0.85s ease,
    max-height 0.85s ease,
    background-color 0.3s ease;
  overflow: hidden;
  width: 12em;
}

/* 展开状态:恢复高度+平移回原位+切换背景 */
#main-nav [aria-expanded="true"] ~ #menu {
  max-height: 600px; /* 设一个比菜单实际高度大的值即可,可根据实际情况调整 */
  transform: translateX(0);
  background: orange;
}
</style>

<script>
document.addEventListener('DOMContentLoaded', function () {
  const toggle = document.querySelector('#toggle');
  
  toggle.addEventListener('click', function() {
    // 切换aria-expanded状态,CSS会自动响应样式变化
    const currentState = toggle.getAttribute('aria-expanded') === 'true';
    toggle.setAttribute('aria-expanded', !currentState);
  });
});
</script>

关键细节说明

  • 水平滑动动画:通过transform: translateX(-12em)让菜单初始时向左移出视野,展开时translateX(0)滑回原位,这个过渡比margin操作更流畅,性能更好
  • 高度展开动画:用max-height的数值切换模拟高度变化,因为CSS无法直接过渡height: auto,只要设置的max-height值大于菜单实际展开高度,就能实现自然的高度过渡效果
  • 动画同步性:把transform、max-height、background-color的过渡都写在同一个transition属性里,保证所有动画同时触发,视觉上更协调
  • 简化逻辑:JS只负责切换无障碍状态属性,所有样式变化都由CSS控制,代码更简洁易维护

你可以把这段代码直接复制到本地测试,调整颜色、过渡时长、菜单尺寸这些参数来适配你的需求,要是还有细节需要调整随时说!

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.08 14:53:09