CSS提示框在overflow:scroll的div中被截断隐藏的解决求助
解决滚动容器中Tooltip被裁剪/位置错位问题
问题根源
你的Tooltip出现被裁剪、触发多余滚动的核心原因:
- Tooltip是设置了
position:relative的item-container的子元素,绝对定位的参考对象是该容器 - 父容器
item-options开启了overflow:scroll,绝对定位元素会被容器的溢出规则裁剪,超出部分还会触发X轴滚动、撑开容器底部
解决方案
1. 调整HTML结构
将Tooltip从滚动容器item-options内部移出,放到item-list层级,脱离滚动容器的限制:
<div id="item-list"> <div id="item-search">//此处为简易搜索栏</div> <div id="item-options"> <div class="item-container" data-tooltip-id="tooltip-1"> <img src="itemsImages/1001.png" class="item-images" /> </div> <!-- 其他物品容器,每个对应唯一的data-tooltip-id --> </div> <!-- 所有Tooltip统一放在滚动容器外 --> <span class="item-tooltip" id="tooltip-1"> <maintext> <stats> <attention>25</attention> Move Speed </stats> </maintext> </span> <!-- 其他Tooltip --> </div>
2. 修改CSS样式
- 移除
item-container的position:relative,避免成为Tooltip的定位参考 - 限制
item-options仅开启垂直滚动,隐藏水平滚动条 - 调整Tooltip的定位规则,确保层级足够高:
#item-list { position: relative; /* 让Tooltip的absolute定位参考此容器 */ } #item-options { display: flex; justify-content: flex-start; align-items: center; height: 80%; flex-wrap: wrap; overflow-y: scroll; /* 仅开启垂直滚动 */ overflow-x: hidden; /* 隐藏水平滚动条 */ font-size: 0; } #item-options .item-container { width: 10%; aspect-ratio: 1/1; /* 移除position:relative */ } .item-images { width: 100%; margin: 0; } .item-tooltip { position: absolute; visibility: hidden; width: 200px; background-color: #555; color: #fff; text-align: center; padding: 5px 0; border-radius: 6px; z-index: 999; /* 确保Tooltip在最上层 */ opacity: 0; transition: opacity 500ms ease; font-size: 12px; user-select: none; pointer-events: none; }
3. 添加JavaScript定位逻辑
通过监听鼠标hover和容器滚动事件,动态计算Tooltip的位置,确保跟随物品且不溢出容器:
// 用事件委托减少事件绑定数量,提升性能 const itemOptions = document.getElementById('item-options'); const itemList = document.getElementById('item-list'); // 鼠标进入物品容器时显示并定位Tooltip itemOptions.addEventListener('mouseenter', (e) => { const container = e.target.closest('.item-container'); if (!container) return; const tooltipId = container.dataset.tooltipId; const tooltip = document.getElementById(tooltipId); if (!tooltip) return; const containerRect = container.getBoundingClientRect(); const listRect = itemList.getBoundingClientRect(); // 计算Tooltip位置:物品下方居中 let left = containerRect.left - listRect.left + (containerRect.width / 2) - (tooltip.offsetWidth / 2); let top = containerRect.top - listRect.top + containerRect.height + 10; // 处理左右边界溢出,确保Tooltip始终在容器内 if (left < 10) left = 10; if (left + tooltip.offsetWidth > listRect.width - 10) left = listRect.width - tooltip.offsetWidth - 10; tooltip.style.left = `${left}px`; tooltip.style.top = `${top}px`; tooltip.style.visibility = 'visible'; tooltip.style.opacity = '1'; }); // 鼠标离开物品容器时隐藏Tooltip itemOptions.addEventListener('mouseleave', (e) => { const container = e.target.closest('.item-container'); if (!container) return; const tooltipId = container.dataset.tooltipId; const tooltip = document.getElementById(tooltipId); if (!tooltip) return; tooltip.style.visibility = 'hidden'; tooltip.style.opacity = '0'; }); // 滚动时更新Tooltip位置,避免错位 itemOptions.addEventListener('scroll', () => { const visibleTooltip = document.querySelector('.item-tooltip[style*="visibility: visible"]'); if (!visibleTooltip) return; const tooltipId = visibleTooltip.id; const container = document.querySelector(`.item-container[data-tooltip-id="${tooltipId}"]`); if (!container) return; const containerRect = container.getBoundingClientRect(); const listRect = itemList.getBoundingClientRect(); let left = containerRect.left - listRect.left + (containerRect.width / 2) - (visibleTooltip.offsetWidth / 2); let top = containerRect.top - listRect.top + containerRect.height + 10; if (left < 10) left = 10; if (left + visibleTooltip.offsetWidth > listRect.width - 10) left = listRect.width - visibleTooltip.offsetWidth - 10; visibleTooltip.style.left = `${left}px`; visibleTooltip.style.top = `${top}px`; });
优化说明
- 采用事件委托减少事件绑定数量,适配大量物品的场景
- 自动处理Tooltip的边界溢出问题,确保始终显示在容器可视范围内
- 滚动时实时更新位置,彻底解决Tooltip错位问题
- Tooltip脱离滚动容器后,不会触发多余滚动条或撑开容器底部
内容的提问来源于stack exchange,提问作者Gustavo Feijó
相关产品推荐
相关产品推荐

