浮動與定位在網頁設計中應用得很廣泛,是兩種主要布局方式的實現方法。
我們知道,網頁上一般來說,塊標簽是自上而下的一塊塊堆疊,行內標簽則在一行內從左到右依次並排,如果所有網頁的都這樣機械的排列着,也太單調了,所以有沒有一個東西讓標簽內容脫離這種文檔流呢,首先就可以考慮float。
float,使某元素浮動起來,可以把元素移到,比如瀏覽器邊沿的左邊或右邊,看上去它們就像粘在邊沿上一樣,它下邊的文本則會充斥在它的一邊或者下面,如下例

<!DOCTYPE html> <html> <head> <title>float test</title> <style type="text/css"> /*reset*/ body,div,p,a,ul,li,h1,h2,h3,h4,h5,h6,pre,img{margin:0;padding:0;} .wrap{ width:300px; margin:0 auto; border:2px solid #30c13a; } .wrap .fl{ width:100px; float:left; background-color:#8cceff; } </style> </head> <body> <div class="wrap"> <p class="fl"> The Macintosh Classic is a personal </p> <p> It was the first Apple Macintosh sold under US$1,000. Production of the Classic was prompted by the success of the Macintosh Plus and the SE. </p> </div> </body> </html>
效果
float有三個值:left、right、none,向左、向右或者不使用浮動。上邊是向左浮動(藍色背景),跟在它后邊p標簽中的文本沒給任何樣式,本來兩個p標簽中的文本塊會一上一下分段堆疊,加了float left后,下邊p標簽中的文本,就環繞在它周圍,包括下邊和右邊。
一般我們在設置浮動時會給浮動塊一個寬度,這樣才能顯示浮動的意義,如果任由其充滿在其父元素中一整行就不需要浮動了,但是多的文本又會跑到浮動塊的下邊去,所以讓兩個塊分開來更合理,可以對右邊環繞的文本塊加一個margin(或者再加一個padding),這個左邊距至少要是浮動塊的盒模型寬度(注意不是左邊元素本身的width屬性值,還包括了它的padding、border和margin),通常比這個寬度略大,比如這里可以給右邊那個文本塊設置:margin-left:110px; ,將兩個塊隔離開。
因為浮動脫離了html文檔流,所以有時候瀏覽器在計算塊的寬高時,沒有將浮動的模塊算在內,比如下邊這樣

<!DOCTYPE html> <html> <head> <title>float test</title> <style type="text/css"> /*reset*/ body,div,p,a,ul,li,h1,h2,h3,h4,h5,h6,pre,img{margin:0;padding:0;} .wrap{ width:300px; margin:0 auto; border:2px solid #30c13a; } .wrap .fl{ width:100px; float:left; background-color:#8cceff; } </style> </head> <body> <div class="wrap"> <p class="main"> It was the first Apple Macintosh sold under US$1,000. Production of the Classic was prompted by the success of the Macintosh Plus and the SE. </p> <p class="fl"> The Macintosh Classic is a personal </p> </div> </body> </html>
效果
就是將上例中的浮動模塊和右邊的文本模塊調換了位置,去掉了右邊文本塊的margin,外圍的類為wrap的div明明將這個浮動塊包在里邊,但是網頁上的border邊框可以看出,高度的計算沒有把它放在里邊,浮動也跑到外邊去了,因此浮動還要注意的是:如果要讓B圍繞A,且A浮動,在html代碼的組織上,要把A模塊的代碼放在B模塊之前,對於左或右均是如此。
浮動的一個常用的情形,就是水平導航條了。水平導航條有兩種方式可以實現,例如下面一種,只要將li標簽的display屬性改為行內樣式,即可讓列表平鋪,這步起核心作用,但是在了解盒模型我們知道,行內標簽的加margin、padding對上下方向是無效的,這里只能讓列表選項左右拉長,上下卻不受控制,塊級標簽才行。
<ul> <li><a href="#">go</a></li> <li><a href="#">some</a></li> <li><a href="#">where</a></li> </ul> li {display:inline;}
采用浮動可以解決這個問題。首選讓列表中的a標簽成為塊級標簽,然后向左浮動列表項就水平展示了,通常要先去掉列表前綴樣式。
li{ list-style-type:none; } li a{ margin:5px; display:block; float:left; }
浮動可能產生的問題:
1.元素的border穿浮動塊而過
代碼和效果

<!DOCTYPE html> <html> <head> <title>float test</title> <style type="text/css"> /*reset*/ body,div,p,a,ul,li,h1,h2,h3,h4,h5,h6,pre,img{margin:0;padding:0;} .wrap{ width:400px; height:100px; margin:0 auto; border:2px solid #3c3c3c; } .wrap .banner{ font-size:120%; font-weight:normal; } .wrap .banner{ margin:5px; border: 2px dashed #30c13a; /*overflow:hidden;*/ } .wrap .fr{ float:right; width:100px; color:#fff; margin-left:10px; margin-right:10px; background-color:#c19132; } </style> </head> <body> <div class="wrap"> <div class="fr"> <ul> <li>Apple</li> <li>Google</li> <li>Microsoft</li> </ul> </div> <h1 class="banner"> Welcome To CSS World </h1> </div> </body> </html>
效果
添加overflow后
右上角,標題的邊框穿過了浮動的列表,為消除這種因背景色或邊框在浮動元素的下方出現的情形,需要使用overflow,我們知道overflow是文本溢出時采取的措施,比如hidden隱藏多出寬高范圍的文本。具體說是,在.wrap .banner{...}中添加overflow:hidden即可,IE6可能還要加一個zoom:1;(這是一個神奇的IE屬性,解決了好多IE顯示問題~)
2. 只浮動,但不需要環繞
一般的浮動和環繞,代碼

<!DOCTYPE html> <html> <head> <title>float test</title> <style type="text/css"> /*reset*/ body,div,p,a,ul,li,h1,h2,h3,h4,h5,h6,pre,img{margin:0;padding:0;} .wrap{ width:400px; height:136px; margin:0 auto; border:2px solid #3c3c3c; } .wrap .left-sidebar{ width:100px; background-color:#e0c898; text-align:center; float:left; } .wrap .left-sidebar ul{list-style-type:none;} .wrap .main{ margin-left:110px; } .wrap .copyright{ background-color: #000; color:#fff; padding:5px; text-align: center; } </style> </head> <body> <div class="wrap"> <div class="left-sidebar"> <ul> <li>A</li> <li>B</li> <li>C</li> <li>D</li> <li>E</li> <li>F</li> </ul> </div> <div class="main"> <p> The Macintosh Classic is a personal computer that was manufactured by Apple Computer from October 15, 1990 to September 14, 1992. </p> </div> <div class="copyright"> <p>Copyright 1996-2015. Some Inc.</p> </div> </div> </body> </html>
效果
clear清除包圍后
有的網站可能是這樣的,左邊一個類似於導航條的東西,浮在瀏覽器左邊,右邊是主要文本內容,假如這個導航條高度比較高,而右邊的文本又不多,所以本該放在頁底的版權聲明跑到文本內容下邊,導航條右邊了。如何解決?就要使用clear屬性,有三個值:left、right、both。比如clear:left,就是在告訴瀏覽器,我不會包圍左浮動的元素,如果是both,則是不包圍左或者右浮動的元素,一般版權聲明始終在頁底,所以我們可以在版權的代碼(.wrap .copyright{..})上加上clear:both,效果如右圖(在這里只需要clear left就行)。
定位,源於網頁設計者想控制網頁上的元素的位置,使它們能放在任何地方,假如你在博客園看某人的博客,比如我這個模板(ThinkInside),會發現頂部導航欄總是懸浮在頂部,即便向下滾動網頁,這就是定位的很好體現。使用Chrome查看它的代碼可以找到這樣的
使用了position屬性,值為fixed,即固定,規定了left、right和top屬性,離左邊、右邊和頂部的距離,就完成了定位(其實還與父元素的position屬性有關)。
網頁設計經常遇到像logo放在哪兒,文字如何放到圖片上等,這就是如何以及在何處顯示特定的元素的問題,解決它的屬性---position,一個精確的定位離不開設置它的left、top等屬性。
position有四個屬性值:absolute(絕對定位)、relative(相對定位)、fixed(固定定位)、static(靜態定位)。
首先,靜態定位是position的默認值,即跟隨html文檔流的排列形式,沒有進行定位,它忽略給出的left、right、top、bottom值,以及z-index(如果把網頁看做是水平的,它就是在豎直方向上的值,即所謂的“層”,層越高(z-index值越大)就越被擺放在網頁的外面,里面的層就被覆蓋掉了)。
絕對定位,通過設置它距離父元素的左、右、上或下的距離,它甚至可以脫離頁面文檔流。前面介紹float時,我們看到標題的邊框線穿過了浮動的元素底部,就是由於浮動元素不再是html文檔流,所以其他元素不知道它的存在,對於絕對定位也有可能面臨這種情況,所以絕對定位的元素可以覆蓋網頁上其他的元素,它被擺在外面。
如果使用了絕對定位,而它的父元素里邊沒有將position屬性設置成absolute或者relative的話,它一定是相對於瀏覽器的邊沿進行定位的,即你設置的left距離左邊界多遠,完全是相對於瀏覽器的邊界的,必須清楚這一點。舉例

<!DOCTYPE html> <html> <head> <title>float test</title> <style type="text/css"> /*reset*/ body,div,p,a,ul,li,h1,h2,h3,h4,h5,h6,pre,img{margin:0;padding:0;} .wrap{ width:760px; height:630px; margin:0 auto; border:2px solid #c19132; } .wrap .piece{ width:100px; height:60px; background-color:#0092ff; position:absolute; right:0; } </style> </head> <body> <div class="wrap"> <div class="piece"> </div> </div> </body> </html>
效果
從代碼中可以看到,即便類名為piece的div就放在類名為wrap的div中,不出意外它至少也要挨着那個邊框線,但是現在給了它position絕對定位,讓它距離右邊距(right)為0,它卻跟瀏覽器邊沿挨着了。
相對定位,如果A元素設置了相對定位屬性(position:relative),B是A里面的子元素,現在要對B進行定位,B將以誰為參照進行定位呢,答案是A。相對定位就是在告訴它里面的子元素:如果你們使用position進行位置控制的話,請以我當前的位置為標准。如果你設置了position:absolute和left:10px,top:5px,那是在距離我(A)的左邊界10像素,上邊界5像素來擺放你。所以相對定位作用的對象是它的子元素,而且它的子元素也要設置position為absolute,否則子元素的left,right等的屬性沒意義。
固定定位,就像定位屬性開始說的,有時候讓導航一直懸在那里是為了方便用戶,還有比如為了強化公司品牌,將logo一直固定在右上角,也可以這樣干。它與設置背景圖片background-attachment設為fixed時作用一樣,前者是將背景圖片固定,用戶滾動網頁時背景圖片跟着滾動。固定定位IE6不支持,用IEtest打開博客看頂部就可以看到奇葩效果。
重點:除了靜態定位和相對定位,不能將float屬性與其他的定位方式同時應用於同一元素。
所以現在,請把一張小圖放在一張大圖上,即所謂的飄浮,就很好辦了。首先,我們需要的不是相對於瀏覽器邊沿定位,而是放在某個元素中,因為要相對於大圖放置,所以是相對定位,直接用img標簽不能達到效果
<img src="大圖" /> <img src="小圖" />
因img是自開自閉標簽,相對定位屬性是對子元素起作用,難道把一個img放在另一個img里面?當然不行,方法就是在兩個img外面加個div包起來,使小圖相對於這個父元素div來定位。代碼

<!DOCTYPE html> <html> <head> <title>float test</title> <style type="text/css"> /*reset*/ body,div,p,a,ul,li,h1,h2,h3,h4,h5,h6,pre,img{margin:0;padding:0;} .pt{ /*父元素設置相對定位,使子元素相對於它偏移*/ position:relative; } .pt .smallimg{ /*子元素相對於父元素絕對定位*/ position:absolute; top: 30px; left:60px; } </style> </head> <body> <div class="pt"> <!-- 大圖 --> <img src="./image/blue.png" /> <!-- 小圖 --> <img class="smallimg" src="./image/doraemon.png" /> </div> </body> </html>
效果
其他的文字飄浮、什么定位差不多同一個道理,如果想對定位元素相互覆蓋的話,設置一個z-index屬性,越大的就會越在網頁表面,從而拒絕被覆蓋。
需要注意的是,與定位相關的left、right、top、bottom屬性都可以給負值,可以制造成它們像懸在某一個塊的邊界上那樣的效果,一半在里面,一半在外面。
OK,既然浮動與定位都可以使圖片、文本等元素位移,假如讓一個大的div位移呢?這就牽涉到網頁的布局設計了。很多個人網站,比如某些博客,是經典的三欄設計
頁面設計 代碼順序
banner里邊放logo,昵稱,簽名 or whatever,左邊放導航,右邊放說明,主要內容展示在中間(隨便說的),底下再標識版權(記得clear both)。有兩種可選的方案是:
一,left-sidebar:向左浮動,right-sidebar像右浮動,main設置好margin-left和margin-right;二,left-sidebar和main均向左浮動,right-sidebar向右浮動,當然main還是要設置margin的。使用float的布局,有的稱為“流式設計”。而通常會把wrap整個給一個固定寬度,如960px,居中,然后再對其中的div浮動。它的html代碼順序相對於布局基本同步(上右圖),注意float的塊要放在圍繞它的塊的前面。
等所有做好后,可能再就是針對不同的屏幕尺寸用@media做下適配,基本就可以用了(如果不考慮IE的話)(說得簡單其實偶還不會=_=#)。
還有一種稱為固定寬度設計,無論屏幕多大,先划分好所有的大小塊,給一個固定的寬度,這樣做起來比較簡單。頁面設計和代碼順序均和上面一樣。
還記得盒模型中說過嗎?css有的屬性可以給負值,如margin、left。給一個足夠的負值,它可以“越過”它前面的元素,跑到它前面去,這在網頁優化時很有用,可以將一部分體現網頁內容的更多的暴露給搜索引擎。清楚了position定位后,就可以實現。同樣是上面的頁面設計,它的代碼順序可能是這樣的
main主要內容在更前面,如果直接按文檔流走的話,達不到上面頁面設計的效果,所以我們可以給left-sidebar的left給一個負值,假設#main的盒模型寬度是480px,注意不是它的width屬性值,要算上left/right padding + left/right border + left/right margin及width的和,給#left-sidebar使用絕對定位,left值給這個寬度值的負數,這樣在頁面上看上去它在#main的左邊,而#main這個塊給一個margin-left值,因為要避免被定位偏移后的#left-sidebar覆蓋(#left-sidebar使用絕對定位后脫離了文檔流),這個值是整個#left-sidebar這個div的盒模型寬度,或者再大一點,使它們之間邊間清晰。這是對整個大div的定位。
通過定位完全可以達到跟浮動一樣的效果,就看你想不想進一步玩玩。