CSS中DIV定位


網上也有不少使用div + css進行佈局的教程,卻存在很多缺陷,一是對css的佈局模型講解不清楚,讓人很難理解相對定位、浮動等概念;二是雖然避免了“表格套表格”的缺點,卻帶來了“div 套 div”的缺點,過量使用div標籤;三是class過多,造成class災難。

要正確使用css,對css的基本只是就不能夠不瞭解。既然是漫談,我這裏就只講四個方面,最後給出xkland項目作爲實例。

一、CSS中的塊模型

在CSS的定義中,有的html標籤被瀏覽器當成一個塊來顯示,比如div、table、p、ul等等,我們稱之爲塊元素;有的html標籤被瀏覽器顯示在文本行之類,如a、span、font等等,我們稱之爲行內元素。行內元素我這裏就不講了,只講講塊元素的模型。

每一個塊元素都可以分爲context、padding、boder和margin幾個部分,我們常說的寬和高,通常指的是context的寬和高(也有可能是context+padding,具體跟瀏覽器有關),padding代表內容和邊框之間的填充,margin代表邊框之外的空白,如下圖:
/

這幾個部分都是可以通過CSS進行指定的,當然,CSS還可以控制背景,因此,我們可以通過CSS來靈活控制我們頁面的外觀。

二、CSS中的文檔流模型

所有的塊元素在html文檔中是按照它們出現在文檔中的先後順序排列的(當然,嵌套不在此列),每一個塊都會另起一行。如下圖:
/

他們對應的html如下:
/<div id="div1">div1</div>
/<div id="div2">div2</div>
/<div id="div3">div3</div>

爲了定義他們的寬度、高度還有邊框,我們定義如下的CSS:
/#div1 {
/    border: 1px solid #000099;
/    height: 60px;
/    width: 200px;
/    margin:2px;
/}

/#div2 {
/    border: 1px solid #000099;
/    height: 60px;
/    width: 200px;
/    margin:2px;
/}

/#div3 {
/    border: 1px solid #000099;
/    height: 60px;
/    width: 200px;
/    margin:2px;
/}

三、CSS中的相對定位和絕對定位模型

在文檔流中,每個塊元素都會被安排到流中的一個位置,我們可以通過CSS中的定位屬性來重新安排它的位置。定位分爲相對定位和絕對定位,相對定位是相對於該塊元素在文檔流中的位置的,比如,我們可以使用相對定位把div2放到div1的右側,CSS代碼如下:
/#div1 {
/    border: 1px solid #000099;
/    height: 60px;
/    width: 200px;
/    margin:2px;
/}

/#div2 {
/    border: 1px solid #000099;
/    height: 60px;
/    width: 200px;
/    margin:2px;
/    position: relative;
/    top: -64px;
/    left: 204px;
/}

/#div3 {
/    border: 1px solid #000099;
/    height: 60px;
/    width: 200px;
/    margin:2px;
/}

下面是效果:
/

可以看到一個有趣的現象,那就是雖然我們把div2移走了,但是div1和div3中間還是有一個空間,說明相對定位的元素是會佔據文檔流空間的,這裏的div2就是典型的“站着茅坑不拉屎”。

使用絕對定位也是可以把div2擺到div1的右邊的,而且絕對定位是不會佔據文檔流空間的,如下圖,div1和div3之間沒有空白:
/

div2的CSS代碼:
/#div2 {
/    border: 1px solid #000099;
/    height: 60px;
/    width: 200px;
/    margin:2px;
/    position: absolute;
/    top: 15px;
/    left: 214px;
/}


絕對定位是個好東西,可以把內容顯示到頁面上的任何位置,但是對於我們程序員來說,卻不能使用太多的絕對定位,因爲使用程序動態向div中添加內容,div的大小是不可知的,無法將每一個div的位置都定死。

四、CSS中的浮動和清除模型

在CSS中,最讓人不好理解的應該算是float和clear意義了。float可以達到這樣一個效果,就是本來應該一行一個的塊元素,如果定義了float屬性,則只要行的空間足夠,它會跑別的float元素的屁股後面,而不再會單獨佔用一行,如下圖:
/

這裏把div2和div3都定義了爲浮動,代碼如下:

/#div2 {
/    border: 1px solid #000099;
/    height: 60px;
/    width: 200px;
/    margin:2px;
/    float:left;
/}

/#div3 {
/    border: 1px solid #000099;
/    height: 60px;
/    width: 200px;
/    margin:2px;
/    float:left;
/}

那什麼情況下需要clear呢?這是因爲float的元素和絕對定位的元素一樣,也是不佔用文檔空間的,因此,如果我們把div2和div3都嵌套在div1中,並且把div2和div3都定義爲浮動,那麼由於它們不佔用文檔空間,設置爲浮動後div2和div3都不屬於div1的內容了,所以作爲父元素的div1沒有內容填充,不知道自動擴展大小,以至於顯示出來div2和div3會跑到div1的外面,如下圖:
/

下面是它們的html代碼:
/<div id="div1">div1
/<div id="div2">div2</div>
/<div id="div3">div3</div>
/</div>

下面是它們的css代碼:
/#div1 {
/    border: 1px solid #000099;
/    height: 60px;
/    width: 450px;
/    margin:2px;
/}

/#div2 {
/    border: 1px solid #000099;
/    height: 60px;
/    width: 200px;
/    margin:2px;
/    float:left;
/}

/#div3 {
/    border: 1px solid #000099;
/    height: 60px;
/    width: 200px;
/    margin:2px;
/    float:left;
/}

因爲float的元素不佔用文檔流空間,有時候被的元素還會重疊到float元素上,這裏我就不舉例了。

爲了解決上面的問題,就需要在float之後的元素上面使用clear,在此例中,我們在div3後面加入一個空段落,並設置其爲clear,如下:
/<div id="div1">div1
/<div id="div2">div2</div>
/<div id="div3">div3</div>
/<p class="clear"></p>
/</div>

clear 屬性定義了元素的哪邊上不允許出現浮動元素。在 CSS1 和 CSS2 中,這是通過自動爲清除元素(即設置了 clear 屬性的元素)增加上外邊距實現的。在 CSS2.1 中,會在元素上外邊距之上增加清除空間,而外邊距本身並不改變。不論哪一種改變,最終結果都一樣,如果聲明爲左邊或右邊清除,會使元素的上外邊框邊界剛好在該邊上浮動元素的下外邊距邊界之下

下面是新增加的空段落的CSS代碼:

/.clear{
/    clear:left;
/}

這時div1有了p這塊內容(儘管p裏面是空的),並且clear:爲left, 使得p的上外邊框邊界剛好在其上浮動元素的下外邊距邊界之下。
效果圖:
/

還是以我的xkland項目爲例,來設計一個完整的頁面吧。下面是我的welcome.jsp頁面的佈局圖:
/

在這個頁面中,我完全擺脫了“表格套表格”的模式,而且除了最上面一行在一個div裏面顯示logo、advertisment和appendix的div外,其它的地方沒有div嵌套。儘量減少div嵌套的有力武器是理解div的意義,div代表division,是部分的意思,也就是說只有在確實沒有標籤能夠作爲一個部分的根元素的時候才需要div。在上面的例子中,菜單條就沒有使用div。菜單條是使用列表實現的,因爲列表的都包含在ul標籤中,因此沒有必要使用div。下面是上圖的html代碼:

/<body>
/<div id="header">
/  <div id="logo">此處顯示 id "logo" 的內容</div>
/  <div id="appendix">此處顯示 id "appendix" 的內容</div>
/  <div id="advertisment">此處顯示 id "advertisment" 的內容</div>
/</div>
/<ul id="menu">
/  <li>菜單項一</li>
/  <li>菜單項二</li>
/  <li>菜單項三</li>
/  <li class="lastMenuItem">最後一個菜單項</li>
/</ul>
/<div id="loginView">此處顯示 id "loginView" 的內容</div>
/<div id="catalog">此處顯示 id "catalog" 的內容</div>
/<div id="search">此處顯示 id "search" 的內容</div>
/<div id="newTopics">此處顯示 id "newTopics" 的內容</div>
/<div id="newReply">此處顯示 id "newReply" 的內容</div>
/<div id="hotTopics">此處顯示 id "hotTopics" 的內容</div>
/<div id="statistics">此處顯示 id "statistics" 的內容</div>
/<div id="hotGroups">此處顯示 id "hotGroups" 的內容</div>
/<div id="hotUsers">此處顯示 id "hotUsers" 的內容</div>
/<div id="footer">此處顯示 id "footer" 的內容</div>
/</body>

是不是很簡潔?

而關於頁面美化和佈局的內容,全部轉移到了CSS中。先來說說菜單項,菜單項是使用列表實現的,而列表常規的顯示樣式是下面這樣的:
/

怎麼樣才能讓它們顯示到一行呢?那就是我前面講到的float屬性。我們給id爲menu的ul定義如下樣式,來顯示邊框:
/#menu {
/    border: 1px solid #0F54C3;
/    padding:5px;
/    margin:0px;
/    width:804px;
/    margin:1px 0px;
/    height: 12px;
/}

爲了避免前面講到的float元素跑到邊框之外,我這裏沒有使用clear,而是將menu的height屬性定義爲12px,和頁面上的字體等高,而菜單隻有一行,因此不會跑到邊框之外。menu中的每一個菜單項都是一個li,我們可以通過#menu li { }來定義它的樣式,這種方式叫做後代選擇器,充分使用這種選擇器,是避免使用過多的類的有力武器,從前面的html代碼中可以看出,我只對最後一個菜單項定義了類,因爲我不想最後一個菜單後面還跟一個小豎線,菜單項之間的小豎線是通過定義li的右邊框樣式做到的,其css代碼如下:
/#menu li {
/    float:left;
/    padding-left:10px;
/    padding-right:10px;
/    border-right-width: 1px;
/    border-right-style: solid;
/    border-right-color: #0F54C3;
/}

/#menu .lastMenuItem {
/    border-right-style:none;
/}


對於下面那麼多的框框,除了#netTopics我使用絕對定位把它擺到了右邊作爲主要內容區之外,其它的都是順着文檔流擺下來的,只定義了寬度,而不需要定義位置。

如果我們要美化頁面,比如添加網站特有的圖片,我們可以修改#logo、#advertisment、#appendix的css代碼,甚至當以後別人美化我的網站時,可以把這三個div的visible設置爲false,而直接定義#header的樣式。在這裏,我們只簡單的把#logo的背景設置爲logo圖片,並去掉邊框。下面是css代碼:

/#logo {
/    float:left;
/    height: 60px;
/    width: 200px;
/    background:url(../images/xkland_logo.gif) no-repeat left top;
/}


對於其他的div,我們還需要爲它們添加內容,#loginView這個稍微特殊一點,需要添加標題和表單,而其他的div就簡單得多,只需要標題和列表就夠了。這裏我們以#loginView爲例,下面是添加內容之後的效果:
/

別看這裏面佈局也挺複雜的,我也完全沒有使用表格。下面是html代碼:

/<div id="loginView">
/  <h3>用戶登錄</h3>
/<form name="form1" id="form1" method="post" action="">
/  <p>用戶名:
/      <input class="textInput" name="userName" type="text" id="userName" />
/  </p>
/  <p>密 碼: 
/    <input class="textInput" name="password" type="password" id="password" />
/  </p>
/  <ul>
/      <li>忘記密碼?</li>
/      <li>新用戶註冊</li>
/      <li><input type="checkbox" name="checkbox" value="checkbox" />記住我</li>
/  </ul>
/  <p class="clear">
/  <input type="submit" name="Submit" value="登 錄" />
/  </p>
/</form>
/</div>

可以看到,我使用的h3標籤來作爲標題,這樣避免了爲標題另外嵌套一個div,對輸入文本框定義了類textInput來定義它們的樣式,而其他的文本內容,我都是使用了p標籤和ul、li標籤,從上面的效果圖就可以看出CSS的強大。下面是它們的css代碼:
/#loginView {
/    border: 1px solid #0F54C3;
/    width: 280px;
/    margin:1px 0px;
/}

/h3 {
/    border-bottom-width: 2px;
/    border-bottom-style: solid;
/    border-bottom-color: #0F54C3;
/    padding-top: 5px;
/    padding-right: 5px;
/    padding-bottom: 5px;
/    padding-left: 15px;
/    margin: 0px;
/    font-size: 10.5pt;
/}

/#loginView p {
/    margin:3px;
/    text-align:center;
/}

/#loginView form {
/    margin:0px;
/}

/.textInput {
/    border: 1px solid #CCCCCC;
/    width: 15em;
/    height:12px;
/}

/#loginView ul {
/    margin:8px 10px 3px 10px;
/}

/#loginView ul li {
/    float: left;
/    width: 130px;
/    height:18px;
/}

/.clear {
/    clear: left;
/}

總之,使用CSS將程序和美工分離是絕對的真理,我們程序員只要能夠在框框內輸出正確的數據就夠了,這樣能夠儘量減少程序的bug,美化頁面的事就讓界面設計師去做吧。當然,我們程序員還是要能夠在html中設計正確的division劃分和嵌套,讓界面設計師在設計界面的時候能夠找到定義CSS的錨點

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章