由一個絕對定位引起overflow:auto滾動問題產生的關於包含塊(containing block)的思考

前言

今天在項目中有一個需求,就是一個可滾動的列表的每一列鼠標懸浮上去就會產生一個浮動框顯示其詳細內容。簡化下情景的代碼以下:css

<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;
}

預覽html

我原本覺得的效果是這樣子的:
圖片描述web

實際倒是這樣的:
圖片描述post

個人心裏是崩潰的,爲什麼絕對定位能夠觸發容器的滾動效果?之前用css太隨意了,根本沒考慮過這些問題。spa

問題分析

萬幸我在Stack Overflow找到了真有人提問過這個問題...下面的回答其實解釋的也不是很明朗,可是看到了核心的概念containing block,也就是包含塊。好吧,讓還沒看懂解釋一臉懵逼的我忽然把包含塊說清楚也是有點困難...直接搬運W3C中文規範的定義:.net

  1. 根元素所在的包含塊是一個被稱爲初始包含塊的矩形
  2. 對於其它元素,若是該元素的position是'relative'或者'static',包含塊由其最近的塊容器祖先盒的內容邊界造成
  3. 若是元素具備'position: fixed',包含塊由連續媒體的視口或者分頁媒體的頁區創建
  4. 若是元素具備'position: absolute',包含塊由最近的'position'爲'absolute','relative'或者'fixed'的祖先創建

對照這個定義,咱們的目前的情景就是符合第四條,個人懸浮框是absolute,列表項relative就是其包含塊,而列表項的包含塊就是容器box。理解到這個地步應該差很少能夠推測出問題所在,懸浮框的包含塊屬於容器之內,所以其高度能夠觸發容器的滾動。雖然我沒有在官方規範中找到對應的解釋,可是這個理解應該是沒有問題的,還請有看官大佬指點更好的分析。設計

解決方法

問題緣由找到了,問題也就迎刃而解,既然是由於懸浮框的包含塊在容器內,那麼咱們就讓懸浮框的包含塊在其外不就能夠了麼,就將其包含塊默認爲初始包含塊便可,除非懸浮框的高度超出頁面會觸發頁面的滾動...但懸浮框的設計高度確定是不可能要超出頁面視口的。修改後的代碼以下:code

<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有空好好總結一下。htm

總結

仍是那句話,若是一個塊的包含塊在容器內(包含容器自己),那麼其高度就會觸發容器的滾動。blog

參考

文中Stack Overflow問題

相關文章
相關標籤/搜索