赞
踩
简易版复现这个问题的代码如下:
<div id='wrapper' style="height: 80px;background-color: bisque;width: 400px;overflow-x: auto;display: flex;flex-wrap: nowrap;">
<div class="menu">111
<div style="width: 100%;position: absolute;bottom: 40px;height: 100px;background-color: aquamarine;">子元素</div>
</div>
<div class="menu">222</div>
<div class="menu">333 </div>
</div>
样式:
.menu{
width: 50%;
height: 100%;
background-color: rgb(149, 182, 241);
flex-shrink: 0;
flex-grow: 0;
margin-right: 10px;
position: relative;
}
显示的结果如下:
目的是实现一个可以横向滑动的菜单栏,其中每个青色部分为一个菜单,点击该菜单可以在其上弹出它的子菜单,但是按照这种实现方式子菜单溢出的部分被隐藏了
导致该问题的原因是最外层div#wrapper设置了overflow且子菜单设置了postion:absolute,从而导致溢出部分隐藏(至于是什么原理尚不知晓,有明白的可以帮忙解答一下。谢谢~)
大家可能对absolute产生误区,切记,absolute元素在没有任何left/top/right/bottom属性设置,且其祖先元素全部都是非定位元素时,该元素的位置是当前位置而不是浏览器上方(张鑫旭《CSS世界》)!
因此,解决这个问题的方案就是将父菜单的position:relative样式去掉,并且设置子菜单宽度为具体的数值,在移动子菜单时也不能使用left/top/right/bottom属性(因为此时的定位祖先元素不知道在哪,甚至直接是body),可以使用transform进行平移。
<div id='wrapper' style="height: 80px;background-color: bisque;width: 400px;overflow-x: auto;display: flex;flex-wrap: nowrap;margin-top: 100px;"> <div class="menu">111 <div style="width: 200px;position: absolute;height: 100px;background-color: aquamarine;">子元素</div> </div> <div class="menu">222</div> <div class="menu">333 </div> </div> .menu { width: 50%; height: 100%; background-color: rgb(149, 182, 241); flex-shrink: 0; flex-grow: 0; margin-right: 10px; /* position: relative; */ }
将弹出的子菜单提到div#wrapper外面来,像很多UI框架(如antd)一样,将弹出层作为body的直接子元素,然后根据点击的父菜单的位置计算子菜单的位置
(.menu样式不变)
<body style="padding: 300px 0;height: 100%;"> <div id="wrapper" style="height: 80px;background-color: bisque;width: 400px;overflow-x: auto;display: flex;flex-wrap: nowrap;"> <div class="menu" id="menu1"> 111 </div> ....其他菜单 </div> <div id="submenu" style="width: 150px;position: absolute;height: 100px;background-color: aquamarine;">子元素</div> </body> <script> /*子菜单显示和隐藏的细节忽略,也不考虑滚动时子菜单的位置问题,只关注子菜单弹出时的位置*/ //使用事件委托添加按钮点击事件 document.getElementById('wrapper').onclick=e=>{ let source=e.srcElement||e.target if(source.className==='menu'){ let pos=document.getElementById(source.id).getBoundingClientRect() //减少回流,使用cssText替代style设置子菜单位置 document.getElementById('submenu').style.cssText+=`left:${pos.left}px;bottom:${pos.bottom+30}px` } } </script>
2. 关于overflow-x和overflow-y混合使用的问题
如果一个其中一个属性的值被赋为visible,另一个被赋值为 scroll 或 auto,那么visible会被重置为’auto’。
当一个元素的 ‘overflow-x’ 或 ‘overflow-y’ 指定值为 ‘hidden’,另一个特性的指定值为 ‘visible’ 时, 该元素最终渲染使用的 ‘overflow-y’ 或 ‘overflow-x’ 值不同。IE6 IE7 IE8 使用 ‘hidden’,其它浏览器使用 ‘auto’。
其他情况overflow使用两者的计算值
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。