關於絕對定位和overflow的可見與不可見
之前給首頁做週年主題面板時遇到一個問題,寫了個demo,然後又遇到了問題
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <style> * { margin: 0; padding: 0; } .main { width: 1200px; height: 900px; margin: auto; position: relative; } .main-banner { width: 1200px; height: 100%; background: pink; } .banner-plugins { position: absolute; top: 0; } .banner-bg-left { left: -311px; } .banner-bg-right { right: -293px; } </style> </head> <body> <div class="main"> <img src="./banner-bg-left.png" class="banner-plugins banner-bg-left"> <img src="./banner-bg-right.png" class="banner-plugins banner-bg-right"> <div class="main-banner"></div> </div> </body> </html> 複製程式碼
效果就是這個樣子的

但是這樣有個問題,當viewport寬度小於內容寬度,就會出現橫向滾動條↓

這就很影響使用者體驗了,也不是我們想要的效果,我們想要的效果應該是,當寬度不足時,應該裁剪兩側圖片的寬度來填充內容寬度。這個地方就涉及到一個知識點,為什麼會出現滾動條?
W3C標準中指明: 通常一個盒子的內容是被限制在盒子邊界之內的。但有時也會產生溢位,即部分或全部內容跑到盒子邊界之外。溢位將在滿足下列條件之一時出現:
- 一個不換行的行元素寬度超出了容器盒子寬度。
- 一個寬度固定的塊元素放在了比它窄的容器盒子內。
- 一個元素的高度超出了容器盒子的高度。
- 一個子孫元素,由負邊距值引起的部分內容在盒子外部。
- text-indent屬性引起的行內元素在盒子的左右邊界外。
- 一個絕對定位的子孫元素,部分內容在盒子外。但超出的部分不是總會被剪裁。子孫元素的內容就不會被子孫元素和其包含塊之間的祖先元素的overflow的設定所剪裁。
我們遇到的就是第6條了,感覺很拗口,大概意思總結一下就是,假如我來自火星,秀恩愛不犯法,來地球后有規則秀恩愛犯法,但是誒,管不著我。就是這個意思。(涉及知識點包含塊)
問題產生的原因找到了,那麼就能找到解決方案了,目的是為了當內容部分超出可視區域的時候, 隱藏它!
很自然地就想到在body上加一個overflow-x: hidden。自然,確實是達到效果了,但是,中間的主體部分假如是1200px,希望的是如果可視區域小於1200px就會出現橫向滾動條,但是在body上加了這個之後就不能實現這個效果了。那能怎麼辦呢?最好的辦法是換成背景圖片就好了。
以上,就是這次換膚踩的坑,聽說duety也踩了,分享一下。
唔,我在寫demo的時候遇到一個問題,還是剛開始的程式碼,當可視區域寬度小於內容寬度的時候,出現橫向滾動條,這時候就會發現一個問題,當我縮小可視區域寬度到出現滾動條的時候,會發現,左邊的圖片會被切割,但是右邊的圖片由於溢位了,拉動滾動條就能看到全部的圖片,為什麼左邊會被切割呢?
我調整可視區域的寬度到剛好1200的時候,發現 body的內容+溢位 正好等於 粉色部分+右邊圖片 的寬度

我想了很久,我個人猜測:因為絕對定位脫離了文件流。
唔,怎麼理解呢。文件流就是在元素排版佈局的時候,元素會自動從左往右,從上到下進行排列,這時候沒有css也是依照這個順序排列的。但是呢,脫離文件流就不一樣了,脫離了文件流之後,它的位置就跟文件寫的順序不一定一致了,並且原本在正常文件流中所佔的空間也沒有了。
結合上面的圖來進行理解,我是這樣想的:
元素排版佈局的時候,因為可視區域的寬度正好等於文件流中的粉色部分的寬度,並且絕對定位左邊的那一部分的空間是沒有了的,所以粉色部分排列出來是緊挨著瀏覽器邊緣的,再看絕對定位的脫離文件流的部分,左邊這一塊被css推到了左邊,但是可視區域正好只能允許看到粉色部分,粉色部分已經緊貼邊緣了,滾動條也是緊貼著左邊的,即便出現了滾動條,也不能再往左劃對不對,於是左邊的就被不可見了,但是它的dom結構依然是存在的,等於說,雖然我們看不見左側部分,但是它依然與我們同在;
瀏覽器繼續渲染,到絕對定位右邊這一塊的時候,因為寬度不允許我們依然看不到它,但是呢,因為溢位,出現了滾動條,所以滑動滾動條將它滑至可視區域就可見。

如果可視區域稍大一點,粉色部分的寬度+一點,再看看是什麼效果

還是按照上面的說法,從左往右渲染的時候,粉色部分排在綽綽有餘的可視區域內,當渲染絕對定位的元素的時候,可視區域除開正常文件流寬度1291-1200=91,還剩91px的寬度,這點寬度留給脫離文件流的元素進行平分可視區域,所以左邊這部分在css的作用下佔據了粉色部分左邊的位置,可見的寬度是46px(為啥不是45.5,那就是另外的事了),同理,右邊也是隻能看到那一點,由於溢位,所以出現滾動條,滑動就可見。
我個人的猜想是這樣的。可以討論一下,以上。
=======================================
給這個問題找原因的時候,發現了一個屬性 direction: ltr;
,很少用,但是可以瞭解一下,還有很類似的近親 writing-mode: vertical-rl;
,這個是針對文字的對齊方式,應該比上面的要更容易想到怎麼用一點,也可以瞭解一下