使用Alpine.js+Bulma开发菜单时,无法实现关闭反向动画
Alpine.js + Bulma 侧边导航关闭动画修复方案
论坛里很多人可能会吐槽我用Alpine.js时不用Tailwind CSS自找麻烦,但这次实践就是要证明Alpine.js能适配任意CSS框架,不局限于某一个。我选了Bulma框架,因为它比Bootstrap或Tailwind更易用。我做了个个性化导航菜单,点击按钮能完美从右侧滑入,但关闭菜单的反向动画实现不了,这只是美观需求。
原代码
HTML & Alpine
<body x-data="{ isOpen: false }" x-cloak> <div x-show="isOpen" > <div id="side_navbar" x-transition:enter="slide_In"> <img id="close_icon" x-transition:enter="slide_Out" class="is-pulled-right m-4" src="close_icon.svg" width="32px" @click=" isOpen = false "> <ul class="side_navbar-items mx-2 my-6 pt-1"> <li><a class="side_navbar-item mb-4">link</a></li> <li><a class="side_navbar-item mb-4">link</a></li> </ul> </div><!-- side_navbar --> </div><!-- x-show component isOpen --> <nav class="navbar" role="navigation" aria-label="main navigation"> <div class="navbar-brand"> <!-- navbar items, navbar burger... --> <a class="navbar-item" href="#"> <img src="Grouplogo.svg"> </a> <a role="button" class="site-menu " width="32px" aria-label="menu" aria-expanded="false" data-target="navbarBasicExample" @click=" isOpen = !isOpen"> <img src="burger_icon.svg"> </a> </div><!-- navbar-brand --> <div id="navbarBasicExample" class="navbar-menu"> <div class="navbar-menu"> <!-- navbar start, navbar end --> <div class="navbar-end"> <div class="navbar-item has-text-weight-medium "> <a class="navbar-item">link</a> <a class="navbar-item">link</a> </div><!-- navbar-end --> </div><!-- x-show component isOpen --> </nav>
Custom CSS
#side_navbar{ background-color: #57219C; color: #fffeff; z-index: 100; position: absolute; right: 0; top: 0; min-width: 20em; min-height: 100%; animation-name: slide_In; animation-duration: 0.1s; } @keyframes slide_In { from { margin-right: -200px; opacity: 0; } to { margin-right: 0; opacity: 1; } } @keyframes slide_Out { from { margin-right: 0; } to { margin-right: 200px; } }
问题原因
- 直接给
#side_navbar绑定CSS动画,与Alpine.js的x-transition机制冲突,导致关闭时无法触发反向动画。 - 关闭动画错误绑定在关闭按钮上,而非侧边栏容器本身。
- 使用
margin-right控制位移,性能不如transform,且动画逻辑不符合侧边栏滑出的需求。
修复后的代码
修改后的HTML & Alpine
<body x-data="{ isOpen: false }" x-cloak> <!-- 给x-show容器添加x-transition控制进入/离开动画 --> <div x-show="isOpen" x-transition:enter="slide-in" x-transition:leave="slide-out"> <div id="side_navbar"> <img id="close_icon" class="is-pulled-right m-4" src="close_icon.svg" width="32px" @click="isOpen = false"> <ul class="side_navbar-items mx-2 my-6 pt-1"> <li><a class="side_navbar-item mb-4">link</a></li> <li><a class="side_navbar-item mb-4">link</a></li> </ul> </div> </div> <nav class="navbar" role="navigation" aria-label="main navigation"> <div class="navbar-brand"> <a class="navbar-item" href="#"> <img src="Grouplogo.svg"> </a> <a role="button" class="site-menu" width="32px" aria-label="menu" aria-expanded="false" data-target="navbarBasicExample" @click="isOpen = !isOpen"> <img src="burger_icon.svg"> </a> </div> <div id="navbarBasicExample" class="navbar-menu"> <div class="navbar-end"> <div class="navbar-item has-text-weight-medium"> <a class="navbar-item">link</a> <a class="navbar-item">link</a> </div> </div> </div> </nav> </body>
修改后的Custom CSS
#side_navbar{ background-color: #57219C; color: #fffeff; z-index: 100; position: absolute; right: 0; top: 0; min-width: 20em; min-height: 100%; } /* 进入动画类 */ .slide-in { animation: slide_In 0.3s ease forwards; } /* 离开动画类 */ .slide-out { animation: slide_Out 0.3s ease forwards; } @keyframes slide_In { from { /* 使用transform实现位移,性能更优 */ transform: translateX(100%); opacity: 0; } to { transform: translateX(0); opacity: 1; } } @keyframes slide_Out { from { transform: translateX(0); opacity: 1; } to { transform: translateX(100%); opacity: 0; } }
修复说明
- 移除
#side_navbar上直接绑定的CSS动画,交给Alpine.js的x-transition控制元素的进入/离开状态。 - 将
x-transition:enter和x-transition:leave绑定到x-show的容器上,分别对应进入和离开的动画类。 - 用
transform: translateX()替代margin-right控制侧边栏位移,提升动画流畅度。 - 调整动画时长到0.3s,让过渡效果更自然。
内容的提问来源于stack exchange,提问作者Graeme Robinson
相关产品推荐
相关产品推荐

