vanilla-calendar.pro弹窗日历不随滚动容器同步滚动问题求助
问题:Vanilla Calendar Pro弹窗无法随滚动容器同步滚动
我正在使用Vanilla Calendar Pro日历组件,实现代码如下:
JavaScript 代码
document.addEventListener('DOMContentLoaded', () => { const calendar = new VanillaCalendar('#calendar', { // Settings input: true, actions: { changeToInput(e, self) { if (!self.HTMLInputElement) return; if (self.selectedDates[0]) { self.HTMLInputElement.innerHTML = self.selectedDates[0]; // 选择日期后隐藏日历 self.hide(); } else { self.HTMLInputElement.textContent = ''; } }, }, settings: { visibility: { positionToInput: 'center', }, }, }); calendar.init(); });
HTML 代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <link href="https://cdn.jsdelivr.net/npm/vanilla-calendar-pro/build/vanilla-calendar.min.css" rel="stylesheet"> <script src="https://cdn.jsdelivr.net/npm/vanilla-calendar-pro/build/vanilla-calendar.min.js" defer></script> <title>test page</title> </head> <body> <h1 style =" font-size: 40px;" >Test Project</h1> <div style="height: 50rem; background-color: rgb(182, 142, 215); overflow-y: scroll; display: flex; justify-content: center; flex-direction: column;"> <div style="margin-bottom: 90rem;" > some components 1</div> <input id="calendar" type="text" placeholder="Choose date" readonly /> <div style="margin-bottom: 90rem;" > some components 2</div> </div> </body> </html>
问题描述
点击输入框唤起日历弹窗后,滚动设置了overflow-y:scroll的内部div时,日历弹窗无法随容器同步滚动。尝试过将弹窗包裹在div中、调整position和z-index样式属性,均未解决问题。
解决方案
方案1:绑定弹窗到滚动容器内部
Vanilla Calendar Pro默认将弹窗挂载到body下,脱离了滚动容器的上下文。我们可以通过配置让弹窗挂载到滚动容器内,并监听滚动事件更新位置:
- 修改初始化配置,指定弹窗容器并添加滚动监听:
document.addEventListener('DOMContentLoaded', () => { const scrollContainer = document.querySelector('div[style*="overflow-y:scroll"]'); const calendar = new VanillaCalendar('#calendar', { input: true, // 将弹窗挂载到滚动容器内 container: scrollContainer, actions: { changeToInput(e, self) { if (!self.HTMLInputElement) return; if (self.selectedDates[0]) { self.HTMLInputElement.innerHTML = self.selectedDates[0]; self.hide(); } else { self.HTMLInputElement.textContent = ''; } }, // 初始化时添加滚动监听,实时更新弹窗位置 init(self) { scrollContainer.addEventListener('scroll', () => { if (self.isVisible) { self.updatePosition(); } }); } }, settings: { visibility: { positionToInput: 'center', // 弹窗使用绝对定位(相对于滚动容器) position: 'absolute' }, }, }); calendar.init(); });
- 给滚动容器添加相对定位:
绝对定位需要依赖相对定位的父容器,修改滚动容器的样式:
<div style="height: 50rem; background-color: rgb(182, 142, 215); overflow-y: scroll; display: flex; justify-content: center; flex-direction: column; position: relative;">
方案2:手动计算并同步弹窗位置
如果方案1不生效,可直接监听滚动事件,手动计算输入框的相对位置来更新弹窗:
document.addEventListener('DOMContentLoaded', () => { const scrollContainer = document.querySelector('div[style*="overflow-y:scroll"]'); const calendarInput = document.getElementById('calendar'); const calendar = new VanillaCalendar('#calendar', { input: true, actions: { changeToInput(e, self) { if (!self.HTMLInputElement) return; if (self.selectedDates[0]) { self.HTMLInputElement.innerHTML = self.selectedDates[0]; self.hide(); } else { self.HTMLInputElement.textContent = ''; } }, // 弹窗显示时添加滚动监听并初始化位置 show(self) { updateCalendarPosition(self); scrollContainer.addEventListener('scroll', () => updateCalendarPosition(self)); }, // 弹窗隐藏时移除监听 hide(self) { scrollContainer.removeEventListener('scroll', () => updateCalendarPosition(self)); } }, settings: { visibility: { positionToInput: 'center', }, }, }); calendar.init(); // 自定义更新弹窗位置的函数 function updateCalendarPosition(calendarInstance) { const inputRect = calendarInput.getBoundingClientRect(); const containerRect = scrollContainer.getBoundingClientRect(); // 计算输入框相对于滚动容器的坐标 const relativeTop = inputRect.top - containerRect.top + scrollContainer.scrollTop; const relativeLeft = inputRect.left - containerRect.left; // 同步弹窗位置(保持居中对齐输入框) calendarInstance.HTMLElement.style.top = `${relativeTop + inputRect.height + 10}px`; calendarInstance.HTMLElement.style.left = `${relativeLeft + (inputRect.width / 2) - (calendarInstance.HTMLElement.offsetWidth / 2)}px`; } });
同时通过CSS强制弹窗使用绝对定位:
.vanilla-calendar { position: absolute !important; }
内容的提问来源于stack exchange,提问作者Dreamer64
相关产品推荐
相关产品推荐

