使用Vue Transitions实现侧边栏隐藏时中间div同步展开动画
问题根源
- 侧边栏动画使用
transform: translate()实现,该属性仅改变元素的视觉渲染位置,不会修改元素在flex布局中占据的实际空间。侧边栏视觉上滑出的过程中,始终占用原有宽度,中间区域无法获得可用空间完成展开。 - 侧边栏离开动画时长设置为0.5s,与进入动画、中间区域的0.3s过渡时长不统一,即使宽度联动生效也会出现动画节奏错位。
- 中间区域不存在挂载/卸载的进入/离开逻辑,不需要套Vue的
<transition>组件,套入后也不会触发对应的enter/leave状态;同时未绑定随侧边栏状态变化的可过渡属性,CSS transition无法自动触发过渡效果。
修复方案
不需要额外写watcher监听状态,利用CSS过渡配合flex布局的自动空间计算即可实现完全同步的动画效果,核心调整点:
- 侧边栏动画改为宽度从固定值线性收缩到0,让其在动画过程中实际占用的布局空间同步变化,flex会自动将腾出的空间分配给中间区域
- 侧边栏内容位移逻辑放到内层容器实现,避免外层宽度收缩时内容被挤压变形
- 所有动画时长统一为0.3s,保证节奏完全同步
- 容器添加
overflow: hidden,避免动画过程中内容溢出
完整修正代码
JS 部分(原有逻辑无需修改)
var app = new Vue({ el: '#app', data: { showSidebars: true, }, methods: { animate() { this.showSidebars = !this.showSidebars; } } });
CSS 部分
.container { display: flex; width: 600px; height: 200px; margin-bottom: 1em; overflow: hidden; } .sidebar { flex: 0 0 120px; background-color: #564D95; } .center { flex-grow: 1; background-color: #242C44; transition: all 0.3s linear; } .center:hover { flex-grow: 5; } /* Vue 过渡 统一动画时长 */ .expand-left-enter-active, .expand-left-leave-active, .expand-right-enter-active, .expand-right-leave-active { transition: all 0.3s ease; overflow: hidden; } /* 进入初始态、离开结束态:宽度归0、透明 */ .expand-left-enter, .expand-left-leave-to, .expand-right-enter, .expand-right-leave-to { flex: 0 0 0; opacity: 0; } /* 侧边栏内层内容做位移,避免外层宽度收缩挤压内容 */ .sidebar-inner { width: 120px; height: 100%; transition: transform 0.3s ease; } .expand-left-leave-to .sidebar-inner, .expand-left-enter .sidebar-inner { transform: translateX(-100%); } .expand-right-leave-to .sidebar-inner, .expand-right-enter .sidebar-inner { transform: translateX(100%); }
HTML 部分
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script> <div id="app"> <div class="container"> <!-- 左侧边栏 --> <transition name="expand-left"> <div v-show="showSidebars" class="sidebar"> <div class="sidebar-inner"></div> </div> </transition> <!-- 中间区域 --> <div class="center"></div> <!-- 右侧边栏 --> <transition name="expand-right"> <div v-show="showSidebars" class="sidebar"> <div class="sidebar-inner"></div> </div> </transition> </div> <button @click="animate">Animate</button> </div>
实现说明
- 动画过程中侧边栏宽度从120px线性降到0,flex布局自动计算剩余空间分配给中间区域,中间区域设置的
transition会自动监听宽度变化完成平滑展开,和侧边栏动画完全同步 - 所有动画由CSS原生驱动,不需要JS手动计算宽度,性能更好
- 保留了原有中间区域hover放大的交互,不影响原有逻辑
内容的提问来源于stack exchange,提问作者Matias
相关产品推荐
相关产品推荐

