box-sizing
box-sizing是CSS3的box屬性之一。一說到CSS的盒模型(Box model)我想很多人都會比較煩,特別是對於新手,然而這個Box model又是我們CSS運用中比較重要的一個屬性。那麽CSS3的Box-sizing跟盒模型有什麽關系呢?第一句話就說了,Box-sizing是CSS3的Box屬性之一,那他當然也遵循CSS的Box model原理,為了能更好的學習和理解這個Box-sizing屬性,我們有必要先了解一下CSS中Box model的原理。
CSS中Box model是分為兩種,第一種是W3C的標準模型,另一種是IE的傳統模型,他們相同之處都是對元素計算尺寸的模型,具體說就是對元素的width,height,padding,border以及元素實際尺寸的計算關系;他們不同之處呢?兩者的計算方法不一至:
1、W3C的標準Box Model:
/*外盒尺寸計算(元素空間尺寸)*/ Element空間高度 = content height + padding + border + margin Element 空間寬度 = content width + padding + border + margin /*內盒尺寸計算(元素大小)*/ Element Height = content height + padding + border (Height為內容高度) Element Width = content width + padding + border (Width為內容寬度)
2、IE)傳統下Box Model(IE6以下,不含IE6版本或“QuirksMode下IE5.5+”):
/*外盒尺寸計算(元素空間尺寸)*/ Element空間高度 = content Height + margin (Height包含了元素內容寬度,邊框寬度,內距寬度) Element空間寬度 = content Width + margin (Width包含了元素內容寬度、邊框寬度、內距寬度) /*內盒尺寸計算(元素大小)*/ Element Height = content Height(Height包含了元素內容寬度,邊框寬度,內距寬度) Element Width = content Width(Width包含了元素內容寬度、邊框寬度、內距寬度)
其實原則上來說Box Model是分得很細的,我們這裏主要分了兩個比較明顯的地方,就是外盒模型和內合模型,如上面計算公式所示(後面我將會詳細介紹一下CSS中的Box Model)。這樣說大家可能還不太好理解,下面我們一起來看一個實際的例子,比如說現在有一個叫boxtest的Div,其具有下面一個屬性
.boxtest { border: 20px solid; padding: 30px; margin: 30px; background: #ffc; width: 300px; }
我們先來看一下W3C標準瀏覽器(Firefox,Safari,Chrome,Opera,IE6+)和傳統瀏覽器(IE6以下版本瀏覽器)的Layout截圖
上圖中明顯可以看出IE6以下版本瀏覽器的寬度包含了元素的padding,border值,換句話來說在IE6以下版本其內容真正的寬度是(width-padding-boder)。用內外盒來說的話,W3C標準瀏覽器的內盒寬度等於IE6以下版本瀏覽器的外盒寬度。這樣下來我們就需要在IE6下的版本寫Hack統一其內外盒的寬度,關於如何處理這樣的兼容問題,我在這裏不多說,感興趣的朋友可以點擊這裏。那麽瀏覽器發展到今天,世面上用IE6以下的瀏覽器應該所占比例相當的少,但不排除沒有人不在用。所以目前瀏覽器大部分元素都是基於W3C標準的Box Model上,但對於form中的有部分元素還是基於傳統的Box Model上,比如說input中的submit,reset,button和select等元素,這樣如果我們給其設置border和padding他也只會往內延伸。關於如何處理form中的這些元素,今日將會借此機會和大定一起探討一下,那麽現在我們還是先回到今天的正題上。
上面簡單讓大家對CSS的Box Model有了一個初步的概念(如果想了解更多的Box Model相關知識,可以點擊W3C Box Model,另外在這裏有中文版)。下面開始我們今天的主題——CSS3的Box-sizing。
語法:
box-sizing : content-box || border-box || inherit
取值說明
1、content-box:此值為其默認值,其讓元素維持W3C的標準Box Model,也就是說元素的寬度/高度(width/height)等於元素邊框寬度(border)加上元素內邊距(padding)加上元素內容寬度/高度(content width/height)即:Element Width/Height = border+padding+content width/height。
2、border-box:此值讓元素維持IE傳統的Box Model(IE6以下版本),也就是說元素的寬度/高度等於元素內容的寬度/高度。(從上面Box Model介紹可知,我們這裏的content width/height包含了元素的border,padding,內容的width/height【此處的內容寬度/高度=width/height-border-padding】)。
為了更能形像看出box-sizing中content-box和border-box兩者的區別,我們先簡單來看一人示例圖,如下所示:
兼容瀏覽器
box-sizing現代瀏覽器都支持,但IE家族只有IE8版本以上才支持,雖然現代瀏覽器支持box-sizing,但有些瀏覽器還是需要加上自己的前綴,Mozilla需要加上-moz-,Webkit內核需要加上-webkit-,Presto內核-o-,IE8-ms-,所以box-sizing兼容瀏覽器時需要加上各自的前綴:
Element { -moz-box-sizing: content-box; -webkit-box-sizing: content-box; -o-box-sizing: content-box; -ms-box-sizing: content-box; box-sizing: content-box; } Element { -moz-box-sizing: border-box; -webkit-box-sizing: border-box; -o-box-sizing: border-box; -ms-box-sizing: border-box; box-sizing: border-box; }
上面主要介紹了box-sizing的理論知識,我們還是理論和實踐結合吧,下面就一起先來看一個簡單點的例子:
HTML Code:
<<span class="title" style="margin-left: 60px; color: rgb(38, 139, 210);">div class="imgBox" id="contentBox"><<span class="title" style="margin-left: 60px; color: rgb(38, 139, 210);">img src="/images/header.jpeg" /></<span class="title" style="margin-left: 60px; color: rgb(38, 139, 210);">div> <<span class="title" style="margin-left: 60px; color: rgb(38, 139, 210);">div class="imgBox" id="borderBox"><<span class="title" style="margin-left: 60px; color: rgb(38, 139, 210);">img src="/images/header.jpeg" /></<span class="title" style="margin-left: 60px; color: rgb(38, 139, 210);">div>
CSS Code:
.imgBox img{ width: 140px; height: 140px; padding: 20px; border: 20px solid orange; margin: 10px; } #contentBox img{ -moz-box-sizing: content-box; -webkit-box-sizing: content-box; -o-box-sizing: content-box; -ms-box-sizing: content-box; box-sizing: content-box; } #borderBox img{ -moz-box-sizing: border-box; -webkit-box-sizing: border-box; -o-box-sizing: border-box; -ms-box-sizing: border-box; box-sizing: border-box; }
效果:
上面效果圖讓大家很明顯的區分開了content-box和border-box的區別了,為了更好的理解,我截了一份他們在Firebug下的一layout分析圖:
Layout分析圖再次證明了box-sizing:content-box是維持了W3C的標準Box Model,而box-sizing:border-box是維持了IE傳統(IE怪異模式)下的Box Model。其兩者區別我在這就不多說了,因為前面說的很清楚了,如果還有不清楚的同學,只要仔細看一下上面那張Layout分析圖,我想你會恍惚大悟的。那麽box-sizing主要運用在哪些方面呢?我總結了一下,第一點就是我們布局上,第二點就是表單元素上。為什麽呢?我想大家在平時布局中都有碰到當兩個塊元素的寬度剛好是其父元素總寬度時我們布局不會有任何問題,但當你在其中一個塊加上padding或border時(哪怕是1px)整個布局就會完全打亂,因為其總寬度超過了父元素的寬度。第二點表單元素,前面我提到過,form有很多元素還是使用的IE傳統Box Model,針對這兩點,box-sizing將在其身上發揮強大的作用,下面我們分別來看看box-sizing在這兩方面的運用:
一、box-sizing拯救我們的布局
為了能更好的說明問題,我們先來模仿一個兩欄布局,先來看其HTML Code:
<<span class="title" style="margin-left: 60px; color: rgb(38, 139, 210);">div class="layoutDemo"> <<span class="title" style="margin-left: 60px; color: rgb(38, 139, 210);">div id="header" class="innerPadding border">Header Content</<span class="title" style="margin-left: 60px; color: rgb(38, 139, 210);">div> <<span class="title" style="margin-left: 60px; color: rgb(38, 139, 210);">div id="content" class="clearfix"> <<span class="title" style="margin-left: 60px; color: rgb(38, 139, 210);">div id="left" class="aside innerPadding border">Left Sidebar</<span class="title" style="margin-left: 60px; color: rgb(38, 139, 210);">div>; <<span class="title" style="margin-left: 60px; color: rgb(38, 139, 210);">div id="main-content" class="article innerPadding border">Main Content</<span class="title" style="margin-left: 60px; color: rgb(38, 139, 210);">div> </<span class="title" style="margin-left: 60px; color: rgb(38, 139, 210);">div> <<span class="title" style="margin-left: 60px; color: rgb(38, 139, 210);">div id="footer" class="innerPadding border"> Footer Content</<span class="title" style="margin-left: 60px; color: rgb(38, 139, 210);">div> </<span class="title" style="margin-left: 60px; color: rgb(38, 139, 210);">div>
簡單的分析一下,這裏把LayoutDemo的div當作我們頁中的body,而div#header是頁面頭部,div#left是頁面左邊欄,div#main-content是頁面主內容,div#footer是頁面的頁腳,下面我們來模仿一個960的布局(比例縮小一半),我們加上平時布局的樣式上去:
.layoutDemo { width: 960px; background: #000; } #header { width: 100%; background: orange; } #left { width: 220px; float: left; margin-right: 20px background: green; } #main-content { width: 720px; float: left; background: gray; } #footer { width: 100%; background: red; }
效果:
到目前布局來說一點問題都沒有,那是因為我們子元素寬度加起來剛好與元素的是相等,那麽我們現在來變動一下,如果根據設計需要,每個塊中內容都離邊緣有10px的距離,那麽我們先來看看基header,left,main-content,footer這幾個塊加一個padding:10px,看看有什麽變化:
.innerPadding { padding: 10px; }
效果:
上圖清晰告訴我們,加了一個padding,惡夢就開始來了,header,footer撐破容器伸出去了,main-content也被掉到left的下面了。跟剛才當初的效果可是完全不一樣的呀,有人可能會問,如果我不使用padding我只使用border什麽怎麽樣呢?大家猜猜會怎麽樣?不用猜了,馬上換個代碼給大家看看,我們只要把剛才的padding註掉換成border,如下所示:
.border { border: 10px solid yellow; }
效果:
上圖是去掉了padding只加了10px的邊框,同樣把布局給打亂了。接著把padding和border同時加進去,反正都撐破了布局,就破罐子破摔。加上的效果如下:
不上我說,大家都知道上圖是因為加上了padding和border把布局給打亂了,下面主要看如何用box-sizing來修復這個撐破的布局,前面介紹了,上圖中box-sizing是取了其默認值content-box,其Box Model完全符合W3C的標準,為了修復這樣的布局,我們需要把Box Model改用IE傳統下的解析,這樣一加,我們給他加上下面box-sizing屬性:
.box-sizing { -moz-box-sizing: border-box; -webkit-box-sizing: border-box; -o-box-sizing: border-box; -ms-box-sizing: border-box; box-sizing: border-box; }
效果:
通過box-sizing:border-box改變了Box Model後,布局神奇般的好了,記得以前為了處理這樣的問題,我們需要改變box的寬度或者在box裏面在嵌套一個div,在裏面的div中增加padding和border來達到這樣的效果。從今天開始,我們不需要那樣做了,我們只要通過box-sizing:border-box來改變Box Model回到IE的傳統模式下,就可以實現了,只是有一點遺憾的是,我們IE6和IE7不支持,如果為了達到一致的效果,在加上你知道CSS Hack如何寫,這樣也並不難,你只要讓IE6和IE7的寬度改變一下,也能達到效果:
#left { *width:180px; } #right { *width: 680px; }
通過上面的hack,我們在IE6和IE7下也能正常顯示我們的布局需求。但是大家說討厭CSS Hack,不想寫,那麽大家在項目中運用時不得不要考慮一下,但對於我們學習CSS3的box-sizing來說是沒有大礙的。
二、Box-sizing統一form元素風格
前面簡單提到form有些input還是支持IE傳統下的Box Model標準,比如說【type="submit"】、【type="reset"】、button、select等,然在搜索box-sizing屬性使用時偶爾發現Roger Johansson早在2004年就發表了一篇關於表單元素樣式測試的文章《Styling form controls》。他告訴我們如果用樣式來控制表單元素在各瀏覽器下的顯示效果是很難,如果還要兼容各系統下的效果更是難上加難。除非使用UI去制作。那麽今天我們就要來看看用box-sizing如何來讓他們達到一致效果:今天我們只要來測試一下submit,reset,button,section,input[type="text"]幾個元素,下面我們先來看其默認狀態下的效果(模式是在):
Html Code:
<<span class="title" style="margin-left: 60px; color: rgb(38, 139, 210);">form action="#" method="post"> <<span class="title" style="margin-left: 60px; color: rgb(38, 139, 210);">div class="form-field"> <<span class="title" style="margin-left: 60px; color: rgb(38, 139, 210);">input type="submit" value="submit" class="submit" /> </<span class="title" style="margin-left: 60px; color: rgb(38, 139, 210);">div> <<span class="title" style="margin-left: 60px; color: rgb(38, 139, 210);">div class="form-field"> <<span class="title" style="margin-left: 60px; color: rgb(38, 139, 210);">input type="reset" value="reset" class="reset" /> </<span class="title" style="margin-left: 60px; color: rgb(38, 139, 210);">div> <<span class="title" style="margin-left: 60px; color: rgb(38, 139, 210);">div class="form-field"> <<span class="title" style="margin-left: 60px; color: rgb(38, 139, 210);">button class="button">button</<span class="title" style="margin-left: 60px; color: rgb(38, 139, 210);">button> </<span class="title" style="margin-left: 60px; color: rgb(38, 139, 210);">div> <<span class="title" style="margin-left: 60px; color: rgb(38, 139, 210);">div class="form-field"> <<span class="title" style="margin-left: 60px; color: rgb(38, 139, 210);">input type="text" value="text" class="text" /> </<span class="title" style="margin-left: 60px; color: rgb(38, 139, 210);">div> <<span class="title" style="margin-left: 60px; color: rgb(38, 139, 210);">div class="form-field"> <<span class="title" style="margin-left: 60px; color: rgb(38, 139, 210);">select name="select" id="select" class="select"> <<span class="title" style="margin-left: 60px; color: rgb(38, 139, 210);">option value="1">1980</<span class="title" style="margin-left: 60px; color: rgb(38, 139, 210);">option> </<span class="title" style="margin-left: 60px; color: rgb(38, 139, 210);">select> </<span class="title" style="margin-left: 60px; color: rgb(38, 139, 210);">div> <<span class="title" style="margin-left: 60px; color: rgb(38, 139, 210);">div class="form-field"><<span class="title" style="margin-left: 60px; color: rgb(38, 139, 210);">input type="checkbox" class="checkbox" />checkbox</<span class="title" style="margin-left: 60px; color: rgb(38, 139, 210);">div> <<span class="title" style="margin-left: 60px; color: rgb(38, 139, 210);">div class="form-field"><<span class="title" style="margin-left: 60px; color: rgb(38, 139, 210);">input type="radio" class="radio" />radio</<span class="title" style="margin-left: 60px; color: rgb(38, 139, 210);">div> <<span class="title" style="margin-left: 60px; color: rgb(38, 139, 210);">div class="form-field"><<span class="title" style="margin-left: 60px; color: rgb(38, 139, 210);">textarea name="textarea" id="" cols="30" rows="3" class="textarea"></<span class="title" style="margin-left: 60px; color: rgb(38, 139, 210);">textarea></<span class="title" style="margin-left: 60px; color: rgb(38, 139, 210);">div> </<span class="title" style="margin-left: 60px; color: rgb(38, 139, 210);">form>
CSS Code
<<span class="title" style="margin-left: 60px; color: rgb(38, 139, 210);">style type="text/css"> body { font-size: 12px; } form { width: 200px; margin: 20px auto; padding: 10px; border: 1px solid #ccc; } .form-field { margin-bottom: 5px; background: #cdcdcd; padding: 2px; } .submit, .reset, .button, .text, .select, .textarea { width: 80px; border-color: red; } .textarea { resize: none; } </<span class="title" style="margin-left: 60px; color: rgb(38, 139, 210);">style>
我們來看其效果,我在效果截圖中附上各個部分在firebug下的layout圖:
DOM元素的Layout圖明顯告訴我們:
1、【type="submit"】、【type="reset"】、button、【type="text"】、select、textarea默認情況下都帶有2px的border;
2、【type="submit"】、【type="reset"】、button默認情況下會有6px的左右padding;height在mac系統下會比在winxp win7系統下少1px,只有16px,(12px的字體時高度為17px);
3、【type="text"】默認情況下會有1px的上下padding;WinXP和Win7下高度為15px,Mac系統下為14px
4、【type="checkbox"】默認情況下會有margin:3px 3px 3px 4px,並且寬/高度默認為13px(IE6,IE7默認大約是15px,Mac系統下只有9px)
5、【type="radio"】默認情況下會有margin: 3px 3px 0 5px的外邊,並且寬/高度默認為13px(IE6,IE7默認大約是15px,Mac系統下只有9px)
6、textarea默認情況帶有1px的上下margin;
最後要說的一點是,上面那些常用的form元素只有【type="text"】和textarea兩者是遵循W3C的標準Box Model,而其他幾個都是還是遵循IE傳統下的Box Model。下面我們在把CSS修改一下,我們把margin、padding和border都統一一下。
.submit, .reset, .button, .text, .select, .textarea, .checkbox, .radio { margin: 0; padding: 0; border-width: 1px; }
同樣我們來看看其各元素在firebug下的Layout分析圖:
Layout圖告訴我們,其margin,border,padding現在都統一了,寬度只有【type="checkbox"】和【type="radio"】在不同的系統和瀏覽器會解析不一樣,最明顯的上面也說過了,這兩個表單元素在IE6和IE7下的寬、高度都是15px,而在Mac系統下是9px,但在WinXP/Win7的Firefox下又是13px,這樣給我們在線上的顯示效果完全帶來了不一樣的風格,這也是大家頭痛的一個地方;另外還有一點需要說明的一點是,別然在上面的Layout中分析【type="submit"】、【type="reset"】、button的寬度一樣,但是在IE6-7之中會隨著內容顯示不同而寬度不同,關於這個問題大家可以參考前面我寫的另一篇文章《input 按鈕在IE下兼容問題》。然而最讓我們頭痛的是表單元素的高度問題,前面也提到過了,在Mac系統下各種表單元素的高度都會比Win系列下少1px,這樣給我們也帶來很大的煩惱。我在網站搜索,看到nwind寫了一篇《如何更好地控制input輸入框的高度》,作者拿了【type="text"】做了很仔細的分析,另外Roger Johansson的《Controlling width with CSS3 box-sizing》一文也做過詳細的分析。從這兩篇文章得知解決這樣的兼容問題我們可以使用CSS3的box-sizing的border-box屬性。下面我截取【type="text"】的解決高度不一到致的方法,運用到表單元素上來
.submit, .reset, .button, .text, .select, .textarea, .checkbox, .radio { margin: 0; padding: 0; border-width: 1px; height: 17px; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; -o-box-sizing: border-box; -ms-box-sizing: border-box; box-sizing: border-box; } .checkbox, .radio { width: 13px; height: 13px; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; -o-box-sizing: border-box; -ms-box-sizing: border-box; box-sizing: border-box; }
我們來看看加上了box-sizing:border-box的layout分析圖:
從Layout圖明顯的可以看出,現在元素的參數都統一了,但是IE6和IE7是不支持box-sizing的屬性,所以為了兼容我們還需要為他們寫一個hack:
.submit, .reset, .button, .text, .select, .textarea, .checkbox, .radio { margin: 0; padding: 0; border-width: 1px; height: 17px; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; -o-box-sizing: border-box; -ms-box-sizing: border-box; box-sizing: border-box; *height:15px; *width: 15px; }
box-sizing:border-box主要用於:布局以及表單元素,表單中不同類型type的默認寬度不一致,可以通過border-box解決。
兼容性:
box-sizing是css3的新屬性,會有兼容性問題。
css3的計算屬性calc()的意思和box-sizing=border-box一樣。簡單用box-sizing,復雜可以用calc()
上面詳細介紹了form元素如何使用box-sizing來解決瀏覽器兼容問題。需要提醒大家一點的是,如果你在樣式中沒有對border進行設置的話,那麽表單中除了checkbox和radio外默認都是2px的border,這樣一來你的寬度和高度在都要相應的減去4px。
box-sizing