css知多少(4)——解讀瀏覽器預設樣式

傑克.陳發表於2015-02-11

  上一節《css知多少(3)——樣式來源與層疊規則》介紹了樣式的五種來源,我們們再通過一張圖回顧一下。

  

  對於上面的三層,我們們大概都比較熟悉了。下面的兩層中,使用者自定義樣式一般也就是改一改字號大小和字型樣式,也沒甚好說的。而最有的說的就是瀏覽器的預設樣式。

  不同瀏覽器的預設樣式多少有些區別,特別是老版本的瀏覽器之間,現在高階瀏覽器越來越向統一的標準靠攏,對前端程式猿來說是一件好事情。雖然有些許差異,但是絕大部分還是相同的,我先把程式碼貼上出來 ,具體的解讀我們們慢慢道來(只說重點,比較容易的或者不常用的就不說了)。

  1 html, address, 
  2 blockquote, 
  3 body, dd, div, 
  4 dl, dt, fieldset, form, 
  5 frame, frameset, 
  6 h1, h2, h3, h4, 
  7 h5, h6, noframes, 
  8 ol, p, ul,center, 
  9 dir, hr, menu, pre{ display: block} 
 10 /* 以上按照block顯示,沒有規定的則按照預設的inline顯示 */
 11 
 12 li { display: list-item} 
 13 /* 程式猿常用的display值是:inline/block/inline-block,很少用到 list-item
 14 list-item到底是什麼樣的顯示效果,可以通過例子驗證。。。。
 15 第一,你可以不用ul-li,而用其他標籤實現list-item的效果
 16 第二,要意識到,瀏覽器對待html只是把它當作一個dom樹,至於顯示成什麼效果,是通過瀏覽器預設的css實現的,即樣式全部通過css設計,和html無關 */
 17 
 18 head { display: none} 
 19 table { display: table } 
 20 /* display:table 和 block 最大的區別在於:包裹性。 提到包裹性,就不得不提一下float和absolute*/
 21 
 22 tr { display: table-row} 
 23 thead { display: table-header-group} 
 24 tbody { display: table-row-group} 
 25 tfoot { display: table-footer-group} 
 26 col { display: table-column} 
 27 colgroup { display: table-column-group} 
 28 td, th { display: table-cell; } 
 29 /* 與table相關的其他display值,研究的意義不大,但是table-cell值得一說。
 30 table-cell是多列布局的最新解決方案,比使用float更加有效(不相容IE6、7)
 31 實際上table-cell是要依賴其他table相關的display,但是瀏覽器會為我們做這些工作,不必手動填寫 */
 32 
 33 caption{ display: table-caption} 
 34 th { font-weight: bolder; text-align: center} 
 35 /* 標題預設設定了粗體和文字居中 */
 36 
 37 caption{ text-align: center} 
 38 body { margin: 8px; line-height: 1.12} 
 39 /* 不同瀏覽器的margin不一樣,所以要設定【 *{margin:0} 】 
 40 line-height:1.12 針對英文沒問題,但是中文看起來很彆扭
 41 另外,1.12是一個相對值(即1.12em),與文字有關的距離設定最好用相對值*/
 42 
 43 h1{ font-size: 2em; margin: .67em 0} 
 44 h2{ font-size:1.5em; margin: .75em 0} 
 45 h3{ font-size: 1.17em; margin: .83em 0} 
 46 h4, p, 
 47 blockquote, ul, 
 48 fieldset, form, 
 49 ol, dl, dir, 
 50 menu { margin:1.12em 0} 
 51 /* em是相對單位,1em就是一單位,瀏覽器預設的一單位是16px,
 52 可以通過 body{font-size:20px} 來修改一單位的值
 53 p的字型大小是1em,h1是2em,h2是1.5em,等等
 54 另外,與文字相關的距離值,最好用相對單位,例如 line-height:1.4; margin:.5em等等,這樣做的好處就是當自定義了1em的絕對px時,line-height也會跟著變 */
 55 
 56 /* 注意,如果我們自己寫css【 * {margin:0} 】,可以把p、h1、h2等標籤的margin覆蓋掉
 57 我們都知道,*選擇器的權重是最低的,但是它卻能覆蓋掉標籤選擇器,說明瀏覽器已經在這裡面做了手腳
 58 瀏覽器沒有讓預設樣式和使用者自定義樣式“公平競爭”,而是優先使用者自定義樣式 */
 59 
 60 h5{ font-size: .83em; margin: 1.5em 0} 
 61 h6{ font-size: .75em; margin: 1.67em 0} 
 62 h1, h2, h3, h4, 
 63 h5, h6, b, 
 64 strong { font-weight: bolder} 
 65 /* 這裡可以看到哪些標籤文字是加粗的 */
 66 
 67 blockquote { margin-left: 40px; margin-right: 40px} 
 68 i, cite, em, 
 69 var, address { font-style: italic} 
 70 /* 這裡可以看到哪些標籤是斜體 */
 71 
 72 pre, tt, code, 
 73 kbd, samp { font-family: monospace} 
 74 pre{ white-space: pre} 
 75 button, textarea, 
 76 input, object, 
 77 select { display:inline-block; } 
 78 /* 不知道inline-block是什麼樣子的?或者不知道inline-block有什麼特性?
 79 在這裡看看哪些標籤是inline-block,就知道inline-block的用處了
 80 具體inline-block的用途,我們會在後面詳細介紹,此處只是點出來 */
 81 
 82 big { font-size: 1.17em} 
 83 small, sub, sup { font-size: .83em} 
 84 sub{ vertical-align:sub} 
 85 sup { vertical-align: super} 
 86 table { border-spacing: 2px; } 
 87 thead, tbody, 
 88 tfoot { vertical-align: middle} 
 89 td, th { vertical-align: inherit } 
 90 s, strike, del { text-decoration: line-through} 
 91 hr {border: 1px inset} 
 92 /* 為什麼<hr/>預設是那麼個難看的樣子,特別是IE下,這就是罪魁禍首 */
 93 
 94 ol, ul, dir, 
 95 menu, dd { margin-left: 40px} 
 96 ol {list-style-type: decimal} 
 97 /* ul 和 ol 在預設情況下都會有一篇左邊的間距,在這裡可以看到為何會有間距,以及間距的具體大小是多少。
 98  */
 99 
100 ol ul, ul ol, 
101 ul ul, ol ol { margin-top: 0;margin-bottom: 0} 
102 u, ins { text-decoration: underline} 
103 br:before {content: "A"} 
104 /* ????????????? */
105 :before, :after { white-space: pre-line } 
106 /* <br/>為何能實現換行?瀏覽器得到html的br標籤,只會解析成一個dom節點而已,
107 而“換行”這一功能是通過這裡實現的????? */
108 
109 center{text-align: center} 
110 abbr, acronym { font-variant: small-caps; letter-spacing: 0.1em} 
111 :link, :visited { text-decoration: underline} 
112 :focus {outline: thindottedinvert} 
113 
114 /* Begin bidirectionality settings (do not change) */
115 BDO[DIR="ltr"] { direction: ltr; unicode-bidi: bidi-override} 
116 BDO[DIR="rtl"] { direction: rtl; unicode-bidi: bidi-override} 
117 
118 *[DIR="ltr"] { direction: ltr; unicode-bidi: embed} 
119 *[DIR="rtl"] { direction:rtl; unicode-bidi: embed} 
120 /* 這些標籤或屬性都不常用 */
121 
122 @media print{ 
123 h1{ page-break-before:always} 
124 h1, h2, h3, 
125 h4, h5, h6{ page-break-after: avoid} 
126 ul, ol, dl { page-break-before: avoid}
127 /* 對於列印頁面時的設定,不常用 */
128 
129 /* 以下都是按照標籤選擇器來的,標籤選擇器比類、id選擇器的權重都低。
130 所以,使用者自定義的樣式,無論是用標籤、類還是id,都能覆蓋預設的標籤選擇器 */
瀏覽器預設樣式

1.理念上的轉變

  在解讀程式碼之前,我先把我看瀏覽器預設樣式最大的體會給大家說一下,這個是非常重要的。就是要先從理念上重新認識html和css。

  以前我都是認為瀏覽器自身本來就認識各種html標籤,並且會根據規則設定標籤的樣子,例如p是block顯示,ul有margin-left,h1粗體顯示……以前以為這些標籤預設的顯示方式和css無關,是瀏覽器自己乾的,css設定網頁樣式是載入之後又渲染的。

  現在知道這種想法是錯誤的。其實瀏覽器載入了html之後只為一件東西——dom樹,瀏覽器把html變為dom樹結構,就完成了對html的結構化。至於後來對檢視的渲染,p是block、br換行,那是整合了css之後的事情。而瀏覽器整合css又是另一個路線,和解析html是分開的。這裡的“css”就包含了瀏覽器預設樣式。

  可以結合下圖理解(第二節的圖):

      

  一句話,瀏覽器將載入的html變為dom樹,但是此時沒有任何顯示樣式。所以顯示的樣式,都是css定義的,瀏覽器只會通過css來渲染檢視樣式

  ——多好的設計:指責單一,開放封閉!

2.block元素

  

  為何預設情況下p、h1、ul、div都是block顯示,就是這裡定義的。所以,不要再說div天生就是block——這句話應該換成:瀏覽器預設樣式天生規定了div是block——所以才導致了div是block!是預設樣式規定的,不是瀏覽器的核心規定的。

  沒有設定block的元素,預設為inline顯示。

3. display: list-item

  

  我們在使用display時,常用的值一般是:inline/block/inline-block,用不到list-item。那這裡的list-item到底有什麼作用?我們不妨親自試一試:

      

  看到沒有,出現了ul-li中的效果了吧,如果再加一個margin-left是不是就跟ul-li一樣了?

  所以,ul-li為什麼會預設顯示成那種樣子?——list-item才是“罪魁禍首”。

4. diplay:table

  

       先給出一個快速思考題:<table>和<div>在容器尺寸上最大區別是什麼(只是容器尺寸,不考慮內容區別)?請在兩秒鐘內說出答案。

       答案是——div寬度和父容器相同,table寬度根據內容而定——即table具有“包裹性”

       舉一個例子:

   

       上圖中,第一個div預設是block,寬度撐滿整個頁面。第二個div設定了display:table,寬度根據內容而定。這就是“包裹性”。而提到“包裹性”,又不得不讓我想到float和absolute。具體怎樣這裡無法細說,後面的文章會詳細講到,有興趣的可以先查著。

       各位思考一下,你們做的專案中,哪些地方想要這種“包裹性”,而不是寫死寬度或者用js計算寬度?如果想不到,我給大家截個圖提醒一下。如下圖:

      

5. display: table-cell

  

  上面的截圖中,我們看到了眼花繚亂的好多display,而且都是和table相關的。從字面意思上我們能看出,這是瀏覽器為了渲染一個完整的表格,而需要的許多顯示方式(PS:看似一個簡單的表格,渲染規則就這麼多,這就提醒我們思考問題的嚴謹性和邏輯性)。

  這裡的大部分都是我們一直都不會用到的,用不到的瞭解即可,沒必要深究。但是這個table-cell我們卻能用得到,而且是用它來幹一件很重要的事情——多列布局

  多列布局在css中有多重要就不用我說了吧,傳統模式下大家都使用float來解決這一問題,但是float寫出來的東西程式碼複雜,寬度調整不靈活,瀏覽器相容性有問題。所以才有了新方案——table-cell,注意,IE6、7不行!

  簡單舉個例子:

      

  記得我剛學html時候,不會用div + css做多列布局,我就用table做多列布局。而今,你可以用table-cell,像用table一樣做多列布局,做出來的效果和table做出來的效果是一模一樣的。

6. body樣式

  

  在body中,定義了兩個樣式,如上圖。

  第一,在預設情況下,頁面中的文字不會直接頂到瀏覽器的邊框,這就是因為預設樣式為body設定了margin的緣故。這裡需要注意個問題,不同瀏覽器為body設定的margin值可能不一樣,因此大家都知道在css中用 *{margin:0} 來解決這一相容性問題。

  之前已經提到過,*選擇器的級別要低於body標籤選擇器,但是*{margin:0}依然有效的原因,就是瀏覽器偷偷的做了優先順序的手腳。如果在正常情況下,*選擇器在遇到標籤選擇器時,是不會起作用的,及時它是“後載入”的。例如:

      

  第二,瀏覽器預設樣式還為body設定了line-height,line-height這個值1.12是對英文比較友好,中文狀態下就顯得有點擁擠。Line-height是具有繼承性的,在body中設定了,body下面所有的文字都會繼承生效。

  另外注意,這裡的line-height: 1.12是一個相對值,即是文字高度的1.12倍。看到這裡,我們在寫line-height的時候,也一定要注意使用相對值,不要使用絕對值。如下:

      

  上圖是編寫line-height的三種形式,大家覺得哪種形式最好?區別是什麼?

  1. 情況1:永遠按照文字的1.4倍計算,不管文字的高度如何,可適應任何變化;
  2. 情況2:永遠按照1.4em計算,隨著em的值改變,不管文字高度如何(此時文字高度可能已經通過絕對的px值該表了大小,而不是隨em改變的);
  3. 情況3:就是25px,絕對的。

  相信看到這裡大家會發現,通過一個line-height我能能窺探到的道道有很多。如果大家看懂了這三種情況,從軟體設計和系統擴充套件的角度說,當然我們都會選擇第一種。

7. em和px

  大家在設定文字高度或者與文字有關的距離,如p的margin、line-heigt(上文剛講完,不再贅述),會用em還是用px?——反正我之前不熟悉css時候,都是用px。因為px是固定大小,一目瞭然。——當然,它也不利於擴充套件。

  因此,我們推薦大家用em。而且瀏覽器的預設樣式也建議我們這樣書寫:

  

  如上圖,它設定了h1字型大小2em、縱向margin是0.67em,h2字型大小1.5em、縱向大小0.75em……p的縱向margin是1.12em,字型大小1em(上圖中沒有,但在整個檔案中有)

  em是什麼?——em是一個瀏覽器識別的長度單位,但是它不是絕對的、固定的,而是相對的。大家都知道px是一個絕對的長度單位制,它永遠不會改變。瀏覽器預設情況下令1em === 16px。現在你知道為何p預設是16px了吧。而且你還知道了h1是p高度的兩倍,h2是p高度的1.5倍……(你知道的越來越多了。。。)

  當然,我們可以通過css修改1em的值。

  

  由於font-size和margin都是通過em來定義的,當em被修改時,不管字型大小修改,margin值也會跟著修改。這就是em好用之處!

  從現在開始,與字型大小有關的css,全部都用em!

8. 粗體和斜體

  

  上圖中,標註了在整個html中,哪些元素設定了粗體/斜體。重點還是一個思維轉換的問題:h1不是天生的粗體,而是設定了font-weight:bolder的樣式而已……

  這裡需要提一句題外話:<b>和<strong>有啥區別?<i>和<em>有啥區別?——不知道的話自己去查查吧,看到許多面試題考這個。

9. inline-block

  

  我相信最初學習使用inline-block的朋友都有一個困惑:inline-block到底是個啥?這時候如果你非常勤奮好學的話,你就去網上查資料,然後做各種實驗。——精神可嘉,行為不可取。

  學習還是有捷徑的。看看瀏覽器預設樣式告訴你的捷徑:button、input就是inline-block!這樣以點播你就會一下子明白,最起碼能給你一個很好的形象的概念。看看button和input的表現,你就知道inline-block是什麼樣子了

  能被父容器居中、能設定高度寬度和margin、不會像table或div那樣佔一正行……——這就是inline-block——記得這是瀏覽器預設樣式告訴你的。

10. <br>樣式的疑問??

  

  這裡我提出自己的一個疑問。如上圖,瀏覽器預設樣式中,對br是這樣設定的。

  1. 這裡的br:before{content:”A”},” A”並沒有顯示出來啊?
  2. <br>的換行到底是誰導致的,是css還是瀏覽器?

  希望知道答案的朋友,不吝賜教,給我和大家分享一下,謝謝了。

11. 總結

  大家看著是不是很過癮?反正我寫著是挺過癮的,雖然打字、寫程式碼、畫圖很累,不過很有成就感——再有你們的鼓勵就更好啦!

  

  首先,我覺得瀏覽器預設樣式非常重要,所有詳細解讀其中的重點,希望能給大家帶來一些啟發。沒有解讀到的就是一些比較容易理解的,或者不常用的(例如列印的樣式設定),可以直接去看看原始碼。

  其次,這裡面也包含了我的一個疑問,很慚愧沒有看明白。即便是一時半會兒解決不了,給別人分享一下,讓你知道了一個疑問,對你來說,應該也是一個收穫。

---------------------------------------------------------------

本系列的目錄頁面:http://www.cnblogs.com/wangfupeng1988/p/4325007.html

-------------------------------------------------------------------------------------------------------------

學習作者教程:《前端JS高階面試》《前端JS基礎面試題》《React.js模擬大眾點評webapp》《zepto設計與原始碼分析》《json2.js原始碼解讀

也歡迎關注我的開源專案——wangEditor,簡潔易用的web富文字編輯器

-------------------------------------------------------------------------------------------------------------

相關文章