如何为按钮容器添加横向滚动并保留悬浮提示正常显示?
问题描述
我有一组带鼠标悬停提示的按钮,悬停时按钮上方会显示一个span提示框,正常显示效果没问题,但屏幕宽度变窄时显示异常:
- 正常状态:按钮排列整齐,悬停时提示框正确显示在对应按钮上方
- 窄屏状态:按钮被挤压变形,提示框位置错乱
相关代码
HTML代码
<div className='buttons'> <button className={editor.isActive('bold') ? 'is-active' : 'is-inactive'} > <strong>N</strong> <span className='popup'>Negrita (Ctrl+B)</span> </button> <button className={editor.isActive('italic') ? 'is-active' : 'is-inactive'} > <em>C</em> <span className='popup'>Cursiva (Ctrl+I)</span> </button> <button className={editor.isActive('strike') ? 'is-active' : 'is-inactive'} > <s>T</s> <span className='popup'>Tachado (Ctrl+Shift+X)</span> </button> ... (其余按钮逻辑类似) </div>
SCSS代码
.buttons button { position: relative; height: 29.19px; color: #000; border: 1px solid black; border-radius: 0.3rem; margin: 0.2rem !important; padding: 0.1rem 0.4rem !important; background: white; accent-color: black; font-weight: 500; } button .popup { visibility: hidden; width: 120px; background-color: black; color: #fff; text-align: center; border-radius: 6px; padding: 5px 0; position: absolute; z-index: 1; bottom: 100%; left: 50%; margin-bottom: 5px; margin-left: -60px; } button .popup::after { content: ""; position: absolute; top: 100%; left: 50%; margin-left: -5px; border-width: 5px; border-style: solid; border-color: black transparent transparent transparent; } button:hover .popup { visibility: visible; }
需求说明
我认为最佳解决方案是给按钮容器添加横向滚动,但由于提示框基于按钮绝对定位,不知道如何在添加滚动的同时,让提示框始终正常显示在悬停按钮上方。
更新1
我给按钮容器添加了横向滚动,代码如下:
.buttons { position: relative; overflow-x: scroll; white-space: nowrap; }
现在滚动功能正常,但提示框被容器遮挡,求解决办法。
解决方案
问题根源:绝对定位的提示框被滚动容器的overflow-x: scroll属性裁剪,因为提示框的定位基准是按钮(.buttons button),而按钮的父容器(.buttons)设置了滚动溢出隐藏,超出容器范围的元素会被裁剪。
方案1:JS+CSS联动适配(推荐)
通过修改提示框的定位基准,配合JS实时获取按钮位置,确保提示框始终跟随按钮且不被遮挡:
- 修改SCSS代码:
.buttons { position: relative; overflow-x: scroll; white-space: nowrap; } .buttons button { position: relative; height: 29.19px; color: #000; border: 1px solid black; border-radius: 0.3rem; margin: 0.2rem !important; padding: 0.1rem 0.4rem !important; background: white; accent-color: black; font-weight: 500; } button .popup { visibility: hidden; width: 120px; background-color: black; color: #fff; text-align: center; border-radius: 6px; padding: 5px 0; /* 将定位基准改为.buttons容器 */ position: absolute; z-index: 999; /* 提高层级避免被其他元素遮挡 */ bottom: calc(100% + 5px); left: 0; transform: translateX(-50%); } button:hover .popup { visibility: visible; /* 通过CSS变量动态获取按钮位置 */ left: calc(var(--button-left) + var(--button-width) / 2); }
- 添加JS代码实时更新按钮位置变量:
const buttons = document.querySelectorAll('.buttons button'); buttons.forEach(btn => { const updatePos = () => { const btnRect = btn.getBoundingClientRect(); const containerRect = btn.parentElement.getBoundingClientRect(); // 计算按钮相对于容器的左偏移(含滚动距离) const leftOffset = btnRect.left - containerRect.left + btn.parentElement.scrollLeft; btn.style.setProperty('--button-left', `${leftOffset}px`); btn.style.setProperty('--button-width', `${btnRect.width}px`); }; // 初始加载、窗口缩放、容器滚动时更新位置 updatePos(); window.addEventListener('resize', updatePos); btn.parentElement.addEventListener('scroll', updatePos); });
方案2:纯CSS简化方案(适合固定场景)
如果按钮容器固定在视口顶部,可改用fixed定位脱离滚动容器:
button .popup { /* ... 保留原有样式 */ position: fixed; /* 改为视口定位 */ bottom: calc(100% + 5px); left: 50%; transform: translateX(-50%); }
注意:此方案在容器滚动时,提示框位置不会跟随按钮移动,仅适合容器固定的场景。
内容的提问来源于stack exchange,提问作者Ignacio Passerini
相关产品推荐
相关产品推荐

