絕對定位對元素寬度的影響

WBOY
發布: 2016-10-20 10:09:27
原創
1785 人瀏覽過
一、問題來源
 
     自己編寫輪播圖切換的時候前一幅圖滑動時後邊出現空白直到前一幅圖全部滑出後第二幅圖才出現。剛開始出現問題到網上搜發現有的說定時器動畫可能會造成這種情況,於是我在代碼調試裡註釋掉了定時器,讓圖片只走一步就停下來,發現後邊還是有空白,所以確定不是定時器的問題。於是我查看了一下盒模型,發現包裹img的容器寬度div#main並不是我理想中六張圖片寬度的總和,原來是我沒有明確設定這個容器div#main的寬度。但是問題來了,沒有明確地設定容器寬度,大家可能就會感性的認為容器的寬度不應該是被其內容填充而適應的麼?根據前面所述的現象,答案自然是否定的,也可以說不是所有情況都是如此,因為實際上定位對容器的寬度也是有影響的。以下討論絕對定位元素的大小與放置狀況的關聯。
 
二、包含塊
 
     首先我們回顧一下包含區塊(定位情境)的基本概念:
 
1.初始包含區塊(根元素的包含區塊)由使用者代理程式決定。
2.浮動元素包含區塊定義為最近的塊級祖先元素。
3.相對定位或靜態定位元素包含區塊由最近的區塊級框、表單元格、或行內區塊框祖先元素(任何類型)內容邊界構成。
4.絕對定位元素包含區塊設定為最近的定位不是static的祖先元素(任何類型)的邊框界定(對區塊級父元素)或內容邊界界定(對行內父元素)。
 
三、寬度與偏移
 
     一般的,元素的大小和位置取決於其包含塊。定位是元素各外邊距邊界相對於其包含區塊對應邊(內邊界與邊框相鄰邊)進行偏移,影響的是元素的所有一切(外邊距、邊框、內邊距、內容)都會移動。故對於一個定位元素有以下等式(後邊的計算皆基於此式):
 
left+margin-left+border-left-width+padding-left+width+padding-right+border-right-width+margin-right+right=包含區塊的width    (式1-1)
 
     據此,在未定義元素的寬度width和高度height時,其值大小都會受到定位影響。對於定位元素來說,是否需要設定其寬度高度應根據情況決定。考慮以下幾種情況其寬度高度各是多少的決定規則:
 
1.如果將偏移屬性top,left,bottom,right都進行了確定,而未設定外邊距,內邊距和邊框的時候,是否明確設定寬度高度,其值都是由偏移屬性確定的;反之若設定了外邊距或內邊距(auto也算),邊框時,高度寬度就是其明確設定值,未明確設寬高的仍由偏移屬性決定。
 
2.對於非替換元素水平軸行為:
 
1)如果left,width,right都為auto,且沒有設定內外邊距,邊框,則經過計算元素左邊位於其靜態位置(從左到右讀),width“恰當收放”,根據上述等式right為餘下的水平距離;
2)當等式中所有值為固定值時,若元素「過度受限」則right會根據上式重置;
3)當上述等式中只有一個屬性值為auto時,元素「過度受限」時就會重置此屬性值以滿足等式;
4)垂直軸規則類似,但要注意只有top可以取靜態位置,bottom做不到。
 
3.對於替換元素(注意這裡沒有「恰當收放」的概念,因為替換元素有固有寬高):
 
1)先看其width(height)是否明確聲明,明確聲明則為該值,否則由元素內容實際大小(寬高)決定;
2)再看left,top若為auto則替換為靜態位置;
3)再看如果left和bottom值如果還為auto,則令margin的auto都置0,若未被置0就設定為左右相等,上下相等;
4)在此之後如果只剩下一個auto值,則同非替換元素類似,根據等式重置該auto值。
5)當元素「過度受限」時,與非替換元素處理一樣,使用者代理程式會忽略right(從左到右讀)和bottom。
 
     以上就是對一個絕對定位元素實際顯示的寬度高度的影響因素情況分析,當你發現界面顯示的效果與你預想的不一致時,可以考慮從上述角度分析一下看是否需要重新確定元素的寬度高度值,或以上其它屬性的值。
 
四、一種常見的情形分析
 
     現在來結合我在專案中遇到的寬度高度問題實際範例分析。這裡討論的假定情形為:設定好寬高的最外層div#rel為相對定位,其子div#abs僅設定left為固定值而未設定寬度(沒有內外邊距邊框前提下),div#abs內部包含不同類型的元素。
 
     1.先討論最內層包裹的是塊級元素的情況,代碼見下:
 
<span style="color: #0000ff"><</span><span style="color: #800000">div </span><span style="color: #ff0000">id</span><span style="color: #0000ff">="rel1"</span><span style="color: #0000ff">></span>
    <span style="color: #0000ff"><</span><span style="color: #800000">div </span><span style="color: #ff0000">id</span><span style="color: #0000ff">="abs1"</span><span style="color: #0000ff">></span>
        <span style="color: #0000ff"><</span><span style="color: #800000">div </span><span style="color: #ff0000">id</span><span style="color: #0000ff">="box1"</span><span style="color: #0000ff">></</span><span style="color: #800000">div</span><span style="color: #0000ff">></span>
        <span style="color: #0000ff"><</span><span style="color: #800000">div </span><span style="color: #ff0000">id</span><span style="color: #0000ff">="box2"</span><span style="color: #0000ff">></</span><span style="color: #800000">div</span><span style="color: #0000ff">></span>
    <span style="color: #0000ff"></</span><span style="color: #800000">div</span><span style="color: #0000ff">></span>
<span style="color: #0000ff"></</span><span style="color: #800000">div</span><span style="color: #0000ff">></span> 
登入後複製
<span style="color: #800000">*</span>{<span style="color: #ff0000">margin</span>:<span style="color: #0000ff">0</span>;<span style="color: #ff0000">padding</span>:<span style="color: #0000ff"> 0</span>}<span style="color: #800000">
#rel1</span>{<span style="color: #ff0000">position</span>:<span style="color: #0000ff"> relative</span>;<span style="color: #ff0000">width</span>:<span style="color: #0000ff"> 120px</span>;<span style="color: #ff0000">height</span>:<span style="color: #0000ff"> 50px</span>;<span style="color: #ff0000">background-color</span>:<span style="color: #0000ff"> yellow</span>;}<span style="color: #800000">
#abs1</span>{<span style="color: #ff0000">position</span>:<span style="color: #0000ff"> absolute</span>;<span style="color: #ff0000">top</span>:<span style="color: #0000ff"> 0</span>;<span style="color: #ff0000">left</span>:<span style="color: #0000ff"> -15px</span>}<span style="color: #800000">
#box1</span>{<span style="color: #ff0000">width</span>:<span style="color: #0000ff"> 50px</span>;<span style="color: #ff0000">height</span>:<span style="color: #0000ff"> 50px</span>;<span style="color: #ff0000">background-color</span>:<span style="color: #0000ff"> red</span>}<span style="color: #800000">
#box2</span>{<span style="color: #ff0000">width</span>:<span style="color: #0000ff"> 50px</span>;<span style="color: #ff0000">height</span>:<span style="color: #0000ff"> 50px</span>;<span style="color: #ff0000">background-color</span>:<span style="color: #0000ff"> blue</span>}
登入後複製
     
     由代碼可知,我們將絕對定位元素的margin,padding都置0,且無邊框,則上述式1-1化為:
 
                                         绝对定位元素div#abs的 left+width+right = 包含块div#rel的 width
 
     由于绝对定位元素的left是定值,而未设width和right,所以后两个都是初始值auto,根据非替换轴的水平行为1)可知,先将width恰当收放,也就是以绝对定位元素的子元素内容刚好放好为准,再自动计算right的值,使三个属性之和刚好等于绝对定位的包含块div#rel的宽度120px。因此,此时绝对定位的元素div#abs的宽度width的值由其内容决定,在如下图两种情形下(通过代码改变子div#box1的宽度进行测试),绝对定位元素的width始终等于子div中宽度最大的那个值。且不受left值的影响,因为无论left值为多少,其right的值都会自动调整,从而不影响width的值。
 
                        
 
     2.再来看最内层包裹的是替换行内元素的情况,代码及示意图如下:
 
<span style="color: #0000ff"><</span><span style="color: #800000">div </span><span style="color: #ff0000">id</span><span style="color: #0000ff">="rel2"</span><span style="color: #0000ff">></span>
    <span style="color: #0000ff"><</span><span style="color: #800000">div </span><span style="color: #ff0000">id</span><span style="color: #0000ff">="abs2"</span><span style="color: #0000ff">></span>
        <span style="color: #0000ff"><</span><span style="color: #800000">img </span><span style="color: #ff0000">src</span><span style="color: #0000ff">="images/pic1.jpeg"</span><span style="color: #ff0000"> alt</span><span style="color: #0000ff">=""</span><span style="color: #ff0000"> id</span><span style="color: #0000ff">="img1"</span><span style="color: #0000ff">></span>
        <span style="color: #0000ff"><</span><span style="color: #800000">img </span><span style="color: #ff0000">src</span><span style="color: #0000ff">="images/pic2.jpeg"</span><span style="color: #ff0000"> alt</span><span style="color: #0000ff">=""</span><span style="color: #ff0000"> id</span><span style="color: #0000ff">="img2"</span><span style="color: #0000ff">></span>
    <span style="color: #0000ff"></</span><span style="color: #800000">div</span><span style="color: #0000ff">></span>
<span style="color: #0000ff"></</span><span style="color: #800000">div</span><span style="color: #0000ff">></span>
登入後複製
<span style="color: #800000">*</span>{<span style="color: #ff0000">margin</span>:<span style="color: #0000ff">0</span>;<span style="color: #ff0000">padding</span>:<span style="color: #0000ff"> 0</span>}<span style="color: #800000">
#rel2</span>{<span style="color: #ff0000">position</span>:<span style="color: #0000ff"> relative</span>;<span style="color: #ff0000">width</span>:<span style="color: #0000ff"> 120px</span>;<span style="color: #ff0000">height</span>:<span style="color: #0000ff"> 50px</span>;<span style="color: #ff0000">background-color</span>:<span style="color: #0000ff"> yellow</span>;}<span style="color: #800000">
#abs2</span>{<span style="color: #ff0000">position</span>:<span style="color: #0000ff"> absolute</span>;<span style="color: #ff0000">top</span>:<span style="color: #0000ff"> 0</span>;}<span style="color: #800000">
img</span>{<span style="color: #ff0000">float</span>:<span style="color: #0000ff">left</span>}<span style="color: #800000">
#img1</span>{<span style="color: #ff0000">width</span>:<span style="color: #0000ff"> 50px</span>;<span style="color: #ff0000">height</span>:<span style="color: #0000ff"> 50px</span>}<span style="color: #800000">
#img2</span>{<span style="color: #ff0000">width</span>:<span style="color: #0000ff"> 50px</span>;<span style="color: #ff0000">height</span>:<span style="color: #0000ff"> 50px</span>}
登入後複製
 
     其中,绝对定位元素的left将被设为定值,而width根据“恰当收放”的原则,它的最大值应该是行内子元素宽度之和,最小值应该是子元素中宽度最大者的宽度值,而right的值情况有一点复杂,因为默认情况下,块级元素是垂直排列而行内元素都是一个挨着一个(中间的缝隙可以用:float:left清除)从左向右排列,且中间没有换行符。所以行内元素放在绝对定位的块级元素内作为元素内容宽度过宽时,会由于其行内元素的特点将内容撑开一直到其包含块内容区右边界(从左向右读),因此当行内子元素(即绝对元素的内容)受限出现折行时right的值为0,式1-1便简化为如下:
 
                                           绝对定位元素div#abs的 left+width = 包含块div#rel的 width
 
     当然这种情况应该是在left设定值在一定范围内的前提下(因为宽度没有设置,是auto的),那么如何确定这个范围呢?当绝对定位元素的宽度刚好等于其最小值和最大值时,利用上面的公式求出left的范围设置在(包含块width-最大绝对定位元素width)~(包含块width-最小绝对定位元素width)之间时,绝对定位元素的宽度是受left值影响的,可以通过上面的公式求出当left为某一特定值时的绝对定位元素的width。
     當left的值設定在上面所說的範圍之外時,絕對定位元素的width已經達到了極值,就不會再受left變化而影響了,此時right就不再是0,而會自動進行計算以符合下述公式:
 
                                                          時中使用中的  
                            
       3.總結來說,在前提假定的情形下:
 
1)如果絕對定位元素包裹區塊級元素,則其width值始終等於子元素中寬度最大者的值。
2)如果絕對定位元素包裹的行內元素,則其width值最大為子元素寬度之和,最小為子元素寬度最大者的值;並需先求出影響width值的left區間,在用其包含塊的寬度-left值來求其寬度。
 
五、總結

       兜兜轉轉說了這麼多,其實就是一個道理,如果你擔心絕對定位元素的寬度出現問題的話,最好顯式地給它設定一個width固定值,因為根據規則1,在沒有將四個偏移屬性全部設定的前提下,明確的width值是管用噠~然而在實際環境中,設定寬度高度對定位元素來說不一定必要,所以理解寬度高度的影響因素將會對遇到的一些關於效果顯示的問題更有幫助。這是我第一次寫科技博文,首先我要向替我審校的本人優雅的攻城獅男友致以最真摯的謝意,同時感謝O'Reilly叢書《CSS權威指南第三版》的作者及其相關工作人員,本文大量內容皆是參考該書並加以自己的理解所寫,初次發文如有問題,還請大家批評指正,非常感謝各位~

來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!