如何用Tailwind实现日历详情Div的平滑宽度过渡动画?
使用Tailwind实现日历详情侧边栏平滑过渡效果
我用HTML、Tailwind CSS和JavaScript构建了一个日历,默认状态下id="show-details"的元素处于隐藏状态,点击特定日期时通过JavaScript显示,但当前该元素是直接弹出的,想要实现类似ChatGPT侧边栏的宽度增长平滑过渡效果。
现有代码结构
HTML结构(简化版)
<main> <div class='calendar'> .... </div> <div class='hidden calendar-day-details'> .... </div> </main>
实际Tailwind样式代码
<main class="max-w-auto shadow-2xl shadow-[#16093E] flex items-stretch"> <div class="bg-[#230F61] rounded-md px-10 py-6 shadow-2xl" id="calendar-wrapper"> .... </div> <div id="show-details" class="bg-[#1D0958] rounded-r-md px-10 py-6 shadow-2xl text-white transition-all hidden transform-gpu w-0" > .... </div> </main>
现有JavaScript代码
const calendarWrapper = document.getElementById('calendar-wrapper'); const clickableDates = document.querySelectorAll('.clickable:not(.empty)'); clickableDates.forEach(dateElement => { dateElement.addEventListener('click', () => { // other logic calendarWrapper.classList.add('rounded-r-none') dateDisplay.classList.remove('w-0', 'hidden', 'scale-0'); dateDisplay.classList.add('w-72', 'block', 'scale-100'); }); }); document.addEventListener('click', event => { if (!event.target.classList.contains('clickable') && !dateDisplay.contains(event.target)) { clickableDates.forEach(element => { element.classList.remove('bg-[#DF15ED]'); }); dateDisplay.classList.add('w-0', 'hidden'); dateDisplay.classList.remove('w-72', 'block'); calendarWrapper.classList.remove('rounded-r-none') } });
实现平滑过渡的解决方案
1. 调整侧边栏初始样式,移除hidden类
hidden类会直接将元素从DOM流中移除,无法触发过渡动画。改用opacity-0+w-0控制隐藏,同时添加过渡时长和溢出控制:
<div id="show-details" class="bg-[#1D0958] rounded-r-md px-10 py-6 shadow-2xl text-white transition-all duration-300 transform-gpu w-0 opacity-0 overflow-hidden" >
duration-300:控制过渡动画的时长(可根据需求调整为duration-200/duration-500)opacity-0:初始状态完全透明overflow-hidden:防止宽度变化时内容溢出到日历区域
2. 修改日历容器的过渡样式
给calendar-wrapper添加过渡类,让圆角切换也更平滑:
<div class="bg-[#230F61] rounded-md px-10 py-6 shadow-2xl transition-all duration-300" id="calendar-wrapper">
3. 更新JavaScript类切换逻辑
不再使用hidden/block,改用opacity和宽度类的切换:
const calendarWrapper = document.getElementById('calendar-wrapper'); const dateDisplay = document.getElementById('show-details'); const clickableDates = document.querySelectorAll('.clickable:not(.empty)'); clickableDates.forEach(dateElement => { dateElement.addEventListener('click', () => { // other logic calendarWrapper.classList.add('rounded-r-none'); // 显示侧边栏 dateDisplay.classList.remove('w-0', 'opacity-0'); dateDisplay.classList.add('w-72', 'opacity-100'); }); }); document.addEventListener('click', event => { if (!event.target.classList.contains('clickable') && !dateDisplay.contains(event.target)) { clickableDates.forEach(element => { element.classList.remove('bg-[#DF15ED]'); }); // 隐藏侧边栏 dateDisplay.classList.add('w-0', 'opacity-0'); dateDisplay.classList.remove('w-72', 'opacity-100'); calendarWrapper.classList.remove('rounded-r-none'); } });
关键注意点
- 避免用
hidden类控制过渡元素的显示/隐藏,它会中断元素的渲染状态,导致过渡失效 overflow-hidden必须添加,否则宽度缩小时内部内容会溢出到日历区域- 可通过调整
duration-*类的值,自定义过渡动画的快慢速度
内容的提问来源于stack exchange,提问作者MiRAY
相关产品推荐
相关产品推荐

