如何让fixed与absolute定位元素保持同一水平位置?
问题:让fixed元素与absolute元素保持同一水平位置
我尝试让一个position: fixed元素与position: absolute元素相对于其父容器处于同一位置:
现有代码
CSS
.content { position: relative; max-width: 20em; margin: 2em 5em; resize:both; height: 200vh; } .menu { border: 1px solid red; background-color: pink; top: -1.5em; right: 0; position: absolute; cursor: pointer; } /* change to fixed position when focused */ .menu:focus { cursor: not-allowed; position: fixed; top: 0.5em; } .menu::after { content: "absolute (click me)"; } .menu:focus::after { content: "fixed (click anywhere else)"; }
HTML
<div class="content"> some long text that might wrap or not <div class="menu" tabindex="0"> Position: </div> </div>
使用position: absolute时一切正常,但position: fixed会使元素移出父容器边界。请问在未设置固定宽度的情况下,是否可以计算fixed元素的位置以使其保持同一水平位置?
注:请勿将此问题标记为重复,另一话题中的答案使用transform: translate(),会导致fixed元素随页面滚动而非固定在原位!
解决方案
可以通过JavaScript动态计算父容器的实时位置,设置fixed状态下元素的right值,以此保持和absolute状态一致的水平位置,同时保证fixed元素固定在视口不随滚动移动。
新增JavaScript代码
const content = document.querySelector('.content'); const menu = document.querySelector('.menu'); // 更新fixed元素的位置 function updateFixedPosition() { if (menu.matches(':focus')) { const contentRect = content.getBoundingClientRect(); // 计算视口右侧到父容器右侧的距离,作为fixed元素的right值 menu.style.right = `${window.innerWidth - contentRect.right}px`; } } // 监听focus事件,切换fixed时更新位置 menu.addEventListener('focus', updateFixedPosition); // 监听blur事件,恢复原布局 menu.addEventListener('blur', () => { menu.style.right = ''; }); // 监听窗口resize,父容器大小变化时重新计算位置 window.addEventListener('resize', updateFixedPosition);
原理说明
- 当
.menu获得焦点切换为fixed定位时,通过getBoundingClientRect()获取父容器.content相对于视口的位置信息。 - 计算视口宽度与父容器右侧位置的差值,将这个值设置为fixed元素的
right属性,确保其水平位置和absolute状态时一致。 - 监听窗口resize事件,保证父容器大小改变(比如拖动resize)时,fixed元素的位置能实时更新。
- 失去焦点时清空动态设置的
right值,恢复absolute状态的布局。
内容的提问来源于stack exchange,提问作者vanowm
相关产品推荐
相关产品推荐

