由一个绝对定位引发overflow:auto滚动问题产生的关于包含块(containing block)的思考

问题是解决了,不过需要根据自身情况而修改

前言

今天在项目中有一个需求,就是一个可滚动的列表的每一列鼠标悬浮上去就会产生一个浮动框显示其详细内容。简化下情景的代码如下:

<div class="box">
  <div class="item">
  我是列表项
    <div class="susp">我是悬浮框</div>
  </div>
</div>

.box {
  height: 200px;
  border: 1px solid red;
  overflow: auto;
}
.item {
  position: relative;
  height: 150px;
  border-bottom: 1px solid blue;
}
.susp {
  position: absolute;
  left: 0;
  top: 150px;
  height: 100px;
  background-color: #eee;
}

预览点击预览

我本来以为的效果是这样子的:
图片描述

实际却是这样的:
图片描述

我的内心是崩溃的,为何绝对定位可以触发容器的滚动效果?以前用css太随意了,根本没考虑过这些问题。

问题分析

万幸我在Stack Overflow找到了真有人提问过这个问题...下面的回答其实解释的也不是很明朗,但是看到了核心的概念containing block,也就是包含块。好吧,让还没看懂解释一脸懵逼的我突然把包含块说清楚也是有点困难...直接搬运W3C中文规范的定义:

  1. 根元素所在的包含块是一个被称为初始包含块的矩形
  2. 对于其它元素,如果该元素的position是'relative'或者'static',包含块由其最近的块容器祖先盒的内容边界形成
  3. 如果元素具有'position: fixed',包含块由连续媒体的视口或者分页媒体的页区建立
  4. 如果元素具有'position: absolute',包含块由最近的'position'为'absolute','relative'或者'fixed'的祖先建立

对照这个定义,我们的目前的情景就是符合第四条,我的悬浮框是absolute,列表项relative就是其包含块,而列表项的包含块就是容器box。理解到这个地步应该差不多可以推测出问题所在,悬浮框的包含块属于容器以内,因此其高度可以触发容器的滚动。虽然我没有在官方规范中找到对应的解释,但是这个理解应该是没有问题的,还请有看官大佬指点更好的分析。

解决方法

问题原因找到了,问题也就迎刃而解,既然是因为悬浮框的包含块在容器内,那么我们就让悬浮框的包含块在其外不就可以了么,就将其包含块默认为初始包含块即可,除非悬浮框的高度超出页面会触发页面的滚动...但悬浮框的设计高度肯定是不可能要超出页面视口的。修改后的代码如下:

<div class="box">
  <div class="item">
  我是列表项
    
  </div>
  <div class="susp">我是悬浮框</div>
</div>

.box {
  height: 200px;
  border: 1px solid red;
  overflow: auto;
}
.item {
  /* position: relative; */
  height: 150px;
  border-bottom: 1px solid blue;
}
.susp {
  position: absolute;
  /* left: 0; */
  /* top: 150px; */
  height: 100px;
  background-color: #eee;
}

其实就是注释掉列表项的position: relative,让悬浮框的包含块指向初始包含块,但是此时注意不能再加定位了,因为你没法算出来的,因此再注释掉lefttop,同时要把悬浮框的div放在列表项div的相邻下面,这样悬浮框是一个BFC,也达到我们想要的位置效果。这个其实和BFC关系不大,但是以前我没总结过,给个参考1参考2有空好好总结一下。

总结

还是那句话,如果一个块的包含块在容器内(包含容器本身),那么其高度就会触发容器的滚动。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值