SpringSide開(kāi)發(fā)實(shí)戰(zhàn)(三):漫談CSS和頁(yè)面布局
Posted on 2006-12-26 15:13 京山游俠 閱讀(8525) 評(píng)論(23) 編輯 收藏 所屬分類(lèi): SpringSide開(kāi)發(fā)實(shí)戰(zhàn)還記得胡戈調(diào)侃《無(wú)極》中的王城布局為“圈圈套圈圈”娛樂(lè)城,也還記得我剛開(kāi)始做Web開(kāi)發(fā)時(shí)“表格套表格”的頁(yè)面布局。在大部分的程序員中,可能還在使用表格進(jìn)行布局,使用表格進(jìn)行布局的巨大缺點(diǎn)就是當(dāng)頁(yè)面進(jìn)行一點(diǎn)點(diǎn)修改的時(shí)候,都有可能完全打亂頁(yè)面的外觀,而且非常不利于和美工的配合。當(dāng)然了,很多美工人員也在使用表格進(jìn)行布局,他們?cè)趫D形軟件中設(shè)計(jì)好頁(yè)面,然后使用切片工具一切就完事,卻給我們需要在網(wǎng)頁(yè)網(wǎng)頁(yè)中動(dòng)態(tài)增加內(nèi)容的程序員帶來(lái)了麻煩。在CSS盛行的今天,我們?cè)缇驮撟尡砀裰蛔鏊谋痉止ぷ髁恕?br />
網(wǎng)上也有不少使用div + css進(jìn)行布局的教程,卻存在很多缺陷,一是對(duì)css的布局模型講解不清楚,讓人很難理解相對(duì)定位、浮動(dòng)等概念;二是雖然避免了“表格套表格”的缺點(diǎn),卻帶來(lái)了“div 套 div”的缺點(diǎn),過(guò)量使用div標(biāo)簽;三是class過(guò)多,造成class災(zāi)難。
要正確使用css,對(duì)css的基本只是就不能夠不了解。既然是漫談,我這里就只講四個(gè)方面,最后給出xkland項(xiàng)目作為實(shí)例。
一、CSS中的塊模型
在CSS的定義中,有的html標(biāo)簽被瀏覽器當(dāng)成一個(gè)塊來(lái)顯示,比如div、table、p、ul等等,我們稱之為塊元素;有的html標(biāo)簽被瀏覽器顯示在文本行之類(lèi),如a、span、font等等,我們稱之為行內(nèi)元素。行內(nèi)元素我這里就不講了,只講講塊元素的模型。
每一個(gè)塊元素都可以分為context、padding、boder和margin幾個(gè)部分,我們常說(shuō)的寬和高,指的只是context的寬和高,padding代表內(nèi)容和邊框之間的填充,margin代表邊框之外的空白,如下圖:
這幾個(gè)部分都是可以通過(guò)CSS進(jìn)行指定的,當(dāng)然,CSS還可以控制背景,因此,我們可以通過(guò)CSS來(lái)靈活控制我們頁(yè)面的外觀。
二、CSS中的文檔流模型
所有的塊元素在html文檔中是按照它們出現(xiàn)在文檔中的先后順序排列的(當(dāng)然,嵌套不在此列),每一個(gè)塊都會(huì)另起一行。如下圖:
他們對(duì)應(yīng)的html如下:



為了定義他們的寬度、高度還有邊框,我們定義如下的CSS:
























三、CSS中的相對(duì)定位和絕對(duì)定位模型
在文檔流中,每個(gè)塊元素都會(huì)被安排到流中的一個(gè)位置,我們可以通過(guò)CSS中的定位屬性來(lái)重新安排它的位置。定位分為相對(duì)定位和絕對(duì)定位,相對(duì)定位是相對(duì)于該塊元素在文檔流中的位置的,比如,我們可以使用相對(duì)定位把div2放到div1的右側(cè),CSS代碼如下:



























下面是效果:
可以看到一個(gè)有趣的現(xiàn)象,那就是雖然我們把div2移走了,但是div1和div3中間還是有一個(gè)空間,說(shuō)明相對(duì)定位的元素是會(huì)占據(jù)文檔流空間的,這里的div2就是典型的“站著茅坑不拉屎”。
使用絕對(duì)定位也是可以把div2擺到div1的右邊的,而且絕對(duì)定位是不會(huì)占據(jù)文檔流空間的,如下圖,div1和div3之間沒(méi)有空白:
div2的CSS代碼:











絕對(duì)定位是個(gè)好東西,可以把內(nèi)容顯示到頁(yè)面上的任何位置,但是對(duì)于我們程序員來(lái)說(shuō),卻不能使用太多的絕對(duì)定位,因?yàn)槭褂贸绦騽?dòng)態(tài)向div中添加內(nèi)容,div的大小是不可知的,無(wú)法將每一個(gè)div的位置都定死。
四、CSS中的浮動(dòng)和清除模型
在CSS中,最讓人不好理解的應(yīng)該算是float和clear意義了。float可以達(dá)到這樣一個(gè)效果,就是本來(lái)應(yīng)該一行一個(gè)的塊元素,如果定義了float屬性,則只要行的空間足夠,它會(huì)跑別的float元素的屁股后面,而不再會(huì)單獨(dú)占用一行,如下圖:
這里把div2和div3都定義了為浮動(dòng),代碼如下:


















那什么情況下需要clear呢?這是因?yàn)閒loat的元素和絕對(duì)定位的元素一樣,也是不占用文檔空間的,因此,如果我們把div2和div3都嵌套在div1中,并且把div2和div3都定義為浮動(dòng),那么由于它們不占用文檔空間,所以作為父元素的div1不知道自動(dòng)擴(kuò)展大小,以至于顯示出來(lái)div2和div3會(huì)跑到div1的外面,如下圖:
下面是它們的html代碼:




下面是它們的css代碼:


























因?yàn)閒loat的元素不占用文檔流空間,有時(shí)候被的元素還會(huì)重疊到float元素上,這里我就不舉例了。
為了解決上面的問(wèn)題,就需要在float之后的元素上面使用clear,在此例中,我們?cè)赿iv3后面加入一個(gè)空段落,并設(shè)置其為clear,如下:





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





效果圖:
還是以我的xkland項(xiàng)目為例,來(lái)設(shè)計(jì)一個(gè)完整的頁(yè)面吧。下面是我的welcome.jsp頁(yè)面的布局圖:
在這個(gè)頁(yè)面中,我完全擺脫了“表格套表格”的模式,而且除了最上面一行在一個(gè)div里面顯示logo、advertisment和appendix的div外,其它的地方?jīng)]有div嵌套。盡量減少div嵌套的有力武器是理解div的意義,div代表division,是部分的意思,也就是說(shuō)只有在確實(shí)沒(méi)有標(biāo)簽?zāi)軌蜃鳛橐粋€(gè)部分的根元素的時(shí)候才需要div。在上面的例子中,菜單條就沒(méi)有使用div。菜單條是使用列表實(shí)現(xiàn)的,因?yàn)榱斜淼亩及趗l標(biāo)簽中,因此沒(méi)有必要使用div。下面是上圖的html代碼:























是不是很簡(jiǎn)潔?
而關(guān)于頁(yè)面美化和布局的內(nèi)容,全部轉(zhuǎn)移到了CSS中。先來(lái)說(shuō)說(shuō)菜單項(xiàng),菜單項(xiàng)是使用列表實(shí)現(xiàn)的,而列表常規(guī)的顯示樣式是下面這樣的:
怎么樣才能讓它們顯示到一行呢?那就是我前面講到的float屬性。我們給id為menu的ul定義如下樣式,來(lái)顯示邊框:










為了避免前面講到的float元素跑到邊框之外,我這里沒(méi)有使用clear,而是將menu的height屬性定義為12px,和頁(yè)面上的字體等高,而菜單只有一行,因此不會(huì)跑到邊框之外。menu中的每一個(gè)菜單項(xiàng)都是一個(gè)li,我們可以通過(guò)#menu li { }來(lái)定義它的樣式,這種方式叫做后代選擇器,充分使用這種選擇器,是避免使用過(guò)多的類(lèi)的有力武器,從前面的html代碼中可以看出,我只對(duì)最后一個(gè)菜單項(xiàng)定義了類(lèi),因?yàn)槲也幌胱詈笠粋€(gè)菜單后面還跟一個(gè)小豎線,菜單項(xiàng)之間的小豎線是通過(guò)定義li的右邊框樣式做到的,其css代碼如下:















對(duì)于下面那么多的框框,除了#netTopics我使用絕對(duì)定位把它擺到了右邊作為主要內(nèi)容區(qū)之外,其它的都是順著文檔流擺下來(lái)的,只定義了寬度,而不需要定義位置。
如果我們要美化頁(yè)面,比如添加網(wǎng)站特有的圖片,我們可以修改#logo、#advertisment、#appendix的css代碼,甚至當(dāng)以后別人美化我的網(wǎng)站時(shí),可以把這三個(gè)div的visible設(shè)置為false,而直接定義#header的樣式。在這里,我們只簡(jiǎn)單的把#logo的背景設(shè)置為logo圖片,并去掉邊框。下面是css代碼:








對(duì)于其他的div,我們還需要為它們添加內(nèi)容,#loginView這個(gè)稍微特殊一點(diǎn),需要添加標(biāo)題和表單,而其他的div就簡(jiǎn)單得多,只需要標(biāo)題和列表就夠了。這里我們以#loginView為例,下面是添加內(nèi)容之后的效果:
別看這里面布局也挺復(fù)雜的,我也完全沒(méi)有使用表格。下面是html代碼:



















可以看到,我使用的h3標(biāo)簽來(lái)作為標(biāo)題,這樣避免了為標(biāo)題另外嵌套一個(gè)div,對(duì)輸入文本框定義了類(lèi)textInput來(lái)定義它們的樣式,而其他的文本內(nèi)容,我都是使用了p標(biāo)簽和ul、li標(biāo)簽,從上面的效果圖就可以看出CSS的強(qiáng)大。下面是它們的css代碼:























































總之,使用CSS將程序和美工分離是絕對(duì)的真理,我們程序員只要能夠在框框內(nèi)輸出正確的數(shù)據(jù)就夠了,這樣能夠盡量減少程序的bug,美化頁(yè)面的事就讓界面設(shè)計(jì)師去做吧。當(dāng)然,我們程序員還是要能夠在html中設(shè)計(jì)正確的division劃分和嵌套,讓界面設(shè)計(jì)師在設(shè)計(jì)界面的時(shí)候能夠找到定義CSS的錨點(diǎn)。
最后提一下,如果你的公司附近有幾所大學(xué)的話,那么恭喜你,你只需要設(shè)置少量的獎(jiǎng)金舉辦一個(gè)什么CSS設(shè)計(jì)大賽,那么你的網(wǎng)站就有成十上百的界面可用,何樂(lè)而不為呢?