雖然對Web應用已經有3年的開發經曆,但是我還是CSS處於一知半解的狀態。主要是因為對xhtml恐懼,除了剛工作那陣子逼不得已,在後來的項目中我都選擇編寫資料、通訊或架構的代碼,最接近UI的僅限到編寫WebControl,UI的開發我會交給信任的並且擅長Web-End的partner去做。從2010開始我定位轉向互連網開發的工作,看現在每一個網站都在注重UI體驗,相關的RIA技術也是火爆異常,部落格園的首頁經常會有Ajax/JQuery/Silverlight的內容,沒辦法,我只有補課了,於是最近近乎瘋狂的學習相關技術。
如果你和我一樣,對CSS一知半解,那麼本文相信對你會非常有用。看看下面的列表,其中的css rule你是否都明白是什麼意思:
* {font-size:12px;}div {font-size:12px;}div > p {font-size:12px;}div + p {font-size:12px;}div:first-child {font-size:12px;}.light {font-size:12px;}div.light {font-size:12px;}#light {font-size:12px;}div#light {font-size:12px;}div[id] {font-size:12px;}div[id="foo"]{font-size:12px;}div[id~="foo"]{font-size:12px;}div[id^="foo"]{font-size:12px;}div[id$="foo"]{font-size:12px;}div[id*="foo"]{font-size:12px;}div[id|="foo"]{font-size:12px;}a:link {font-size:12px;}a:visited {font-size:12px;}div:hover {font-size:12px;}div:focus {font-size:12px;}textarea:active {font-size:12px;}p:first-letter {font-size:12px;}p:first-line {font-size:12px;}p:before {font-size:12px;}p:after {font-size:12px;}h1,h2 {font-size:12px;}.class1, .class2 {font-size:12px;}div.light a:link {font-size:12px;}
如果上面所列的css selectors中有你不熟悉的,沒關係,在讀完本文後你會有一個清楚的瞭解。本文將包括以下內容:
- 各式各樣的CSS Selector
- CSS Box Model
- 定位(positioning)
- CSS的版本和瀏覽器安全色
- 其他
聲明:本文所討論的CSS版本為CSS2.1
CSS Selectors
每一個CSS rule都是由selector {declaration}兩部分組成的,如p {font-size:12px},為了更精確選擇需要應用CSS樣式的元素,CSS為我們提供了各式各樣的selector。為什麼稱為selector(選取器),我在google上查了“why named css selector” ,沒有找到答案,但我猜想這應該是和瀏覽器的實現行為有關,瀏覽器在從伺服器獲得html字元流後,要根據CSS“畫”出html中包含的DOM element,這個“畫”的過程應該是按照DOM element在html字元流中出現的順序進行的,selector用於匹配滿足條件的DOM element,當然這隻是猜測,如果有哪位朋友知道麻煩請告訴我。CSS2.1中常用的有以下幾種類型的selector:
- type selector(DOM元素類型選取器)
- decendant selector (子項目節點選取器)
- class selector (class 選取器)
- id selector (id選取器)
- attribute selector (屬性選取器)
- pseudo-class and pseudo-element selector (偽class和虛擬元素選取器)
完整選取器的定義請參考W3C文檔:
W3C關於CSS2選取器的說明:http://www.w3.org/TR/CSS2/selector.html
最有趣的是, CSS的selector可以組合起來定義,我們看看下面的css rule:
div.post div.entry h1, div.post div.entry h2, div.post div.entry h3, div.post div.entry a:hover{margin-bottom:12px;margin-top:24px;}
上述css rule用了grouping selector的定義,匹配如下元素:
1) 匹配所有<div class=”post”>元素中的<div class=”entry”>中的<h1>、<h2>、<h3>元素。
2) a:hover是偽class選取器,匹配所有<div class=”post”>元素中的<div class=”entry”>中的<a>,定義了當滑鼠移至<a>元素時的樣式。
在實際的應用中,有時候會遇到css rule衝突的問題。像部落格園的頁麵包含了部落格園的css、模板的css、每個使用者自訂的css,難免會造成css selector或css rule的重複定義,看看下面的例子:
body div p { font-size: 14px; }div p { font-size: 12px; }
上面的例子中同樣是選擇p元素,那麼到底font-size最後是12px還是14px呢?CSS通過計算特徵權重來決定最後採用哪個css rule
CSS2中關於特徵計算的說明:http://www.w3.org/TR/CSS2/cascade.html#specificity
如果來自於部落格園頁面的CSS與使用者自己設定的偏好CSS衝突了,那又怎麼辦呢?
IE使用者可以完全忽略掉網站頁面提供的CSS,而採用自己偏好的CSS定義,具體設定路徑:控制台->Internet選項->常規選項卡->協助工具功能
CSS的全稱是Cascade Stylesheet,Cascade的意思是級聯、層疊,對於來自瀏覽器、使用者和頁面的CSS,瀏覽器將按照這些CSS的優先順序順序,採用高優先順序的CSS rule,若同優先順序則計算特徵。CSS優先順序從高到低排序如下:
- user important declaration
- author important declaration
- author normal declaration
- user important declaration
- user agent declaration (瀏覽器的css設定)
相信一般的使用者是不會去設定自己偏好的CSS設定的,瀏覽器我們也是管不著的。和CSS編寫有關的是2)和3)。我的部落格用的是老趙的模板,在模板的css裡,div.post h1的設定是gray,sidebar也是gray,但是我個人喜歡綠色和金色,但是不可能修改模板的css,幸好部落格園提供了自訂css設定,於是我在自訂css設定中重新定義了h1和sidebar的css rule,覆蓋掉了模板css的設定。對於類似這樣的css rule,CSS2提供了!important關鍵字,如:
div.post h1 {color: lime !important;}
所以,標記為important的css rule覆蓋掉了模板css中normal的css rule。Anyway,還是要感謝老趙提供的模板,我非常喜歡,老趙很王道。
CSS Box Model
Box Model是CSS的核心,雖然不同瀏覽器實現技術不同,但是它們都要按照相應的Box Model把html中的dom element給畫出來。我們先來看看一段簡單的html和它的Box Model:
<p style="height:140px;width:400px">Hi, u r reading a post written by k.k<img alt="aa" height="120" src="a7946.jpg" width="120" />.</p>
外層的方框表示的是<p>產生的Box Model,內層的方框表示<img>產生的Box Model,對瀏覽器來說顯示頁面就是畫框,把這些嵌套的Box Model畫出來(最外層的Box Model是html元素或body元素)。關於Box Model,最重要的是弄清楚padding、border和margin三個概念,W3C的文檔說得很清楚:
W3C關於Box Model的說明:http://www.w3.org/TR/CSS2/box.html
這裡討論兩個有關Box Model的兩個概念:Block-level element和Inline-level element
Block-level elements generate an element box that fills its parent element's content area and can not have other elements at its sides(left and right). It generates "break" before and after the element box.
Inline-level elements generate an element box within a line of text and do not break up the flow of that line.
Block-level element和Inline-level element的區別在於——是否會在前後元素之間產生換行。最典型的Block-Level element就是<p>和<div>,他們的出現讓前後元素之間產生換行;最典型的Inline-Level element是<a>,他的出現不會讓前後產生換行。通過display:block或display:inline,我們可以直接指定DOM element的Box Model的產生方式:
<div>this is <div style="display:block">block-level</div>element</div><p></p><div>this is <div style="display:inline">inline-level </div>element</div>
產生頁面效果如下:
display還有一個取值——display:none,可以用來不顯示某個element,視覺效果與visibility:hidden相同。但對於兩者在瀏覽器實現上是有區別的:瀏覽器不會對標記display:none的element的html進行處理,它的高、寬等值失效;visibility:hidden只是視覺上看不見,而瀏覽器仍保留element所佔據的空間,它的高、寬等值仍然有效。簡單的說,後者是哈利傳輸速率披了隱藏鬥篷。
現在流行的div彈出對話方塊,因為計算positioning offset,需要用到div的高和寬等資訊,所以css設定要用visibility:hidden。
定位 Positioning
CSS的定位分為三種:浮動定位、相對定位和絕對位置。
浮動定位(float)
用過Word等文字排版工具的使用者應該很容易理解浮動定位,類似Word中的圖文混排,不過CSS的浮動定位(float)非常簡單,只有left和right。
我的部落格頁面的右上方的About設定就用了float:
<img id="myicon" src="http://images.cnblogs.com/cnblogs_com/chwkai/227090/r_a7946.jpg" alt="k.k icon"/><p class="kkintro">
對一個問題或領域,從不瞭解到瞭解,從瞭解到熟悉,從熟悉到精通,這記錄了K.K思考和解決問題的成長過程。</p><p class="kkintro">On an issue or area, never learned to understand, from the learned to be familiar with, from the familiar
to the master, this blog records the K.K's growth by thinking and solving problems.</p><p></p>
頁面效果如下:
上面看到是文字和圖片混排的效果,如果你不希望混排,可以用設定clear屬性,可能取值為left/right/both/none。我們看看上面的html中<p>設定了clear:both後的效果:
相對定位(position:relative)
相對定位指的是html element的box model包含在父節點的box model內,以父節點的左上方(top-left-corner)為座標0點的定位。看下面的html代碼你就理解了:
<div style="width:200px;height:200px;margin: 30px;border: thin solid black;background-color: #FFFF99;display: block;"><div style="width:100px;height:100px;background-color: #CC3300;border: thin solid black;position: relative;top: 50%;left: 50%;"></div></div>
內層嵌套的div採用了相對定位,距離父div的左上方(x,y)的距離為(+100px, +100px),頁面效果如下:
絕對位置(position:fixed & position:absolute)
position:absolute指的是相對於已定位的父element的定位,position:fixed是相對於瀏覽器視窗的定位。當element不存在已定位的父elemenet時,position:absolute將相對瀏覽器視窗定位,等價於position:fixed。
已定位的父element:the containing block is set to the nearest ancestor (of any kind) that has a position value other than static
我們看看一個絕對位置的例子,google suggestion下拉框:
css設定:
.gac_m {-moz-background-clip:border;-moz-background-inline-policy:continuous;-moz-background-origin:padding;background:#FFFFFF none repeat scroll 0 0;border:1px solid #000000;cursor:default;font-size:14px;margin:0;position:absolute;z-index:99;}
.gac_m中的position:absolute的containing block是瀏覽器視窗,等價於position:fixed,都是相對於瀏覽器視窗的定位。現在個網站標配的div對話方塊基本上是用position:fixed來進行定位的。
CSS的版本和瀏覽器安全色 Version & User Agent Compatibility
CSS2.1和CSS3.0的瀏覽器安全色情況一覽:http://www.quirksmode.org/css/contents.html
CSS2.1瀏覽器安全色情況(詳細):http://www.webdevout.net/browser-support-css
其他 Tricks實現div透明遮罩(overlay)
div透明遮罩也基本成了div對話方塊的標配了,有全瀏覽器視窗的遮罩,如部落格園的求職簡曆填寫;也有邊框的遮罩,如豆瓣的“想讀”。我個人比較喜歡豆瓣的風格,雖然彈出一個對話方塊,然後這個瀏覽器視窗變灰或白這樣看起來很酷,但始終給人一種突兀的感覺,當然全屏的遮罩還有一個作用就是模仿模態視窗的效果,這倒是很實用的。
要實現透明遮罩要用到opacity設定,下面給出了在不同瀏覽器實現透明效果的css
div#overlay {/*opacity setting for ie*/filter:alpha(opacity=50);/*opacity setting for early version of firefox*/-moz-opacity:0.5;/*opacity setting for early version of safari*/-khtml-opacity: 0.5;/*opacity setting in css3*/opacity: 0.5;}
CSS Transparency settings for All browsers: http://css-tricks.com/css-transparency-settings-for-all-broswers/
在實現透明遮罩的時候,由於多個div之間存在層疊關係,我們可以通過設定z-index來實現element的層疊次序,z-index值大的在上面。
一個完整的實現overlay遮罩的例子:http://files.cnblogs.com/chwkai/popup.html.xml (去掉.xml尾碼可瀏覽)
解讀HTML的<link>元素
我相信做過Web頁面都知道<link>可以用來連結外部的css和javascript檔案,但不僅局限於此link可用來連結任何的外部資源。
W3C關於HTML的<link>元素的說明:http://www.w3school.com.cn/tags/tag_link.asp
以css為例,一個完整的<link>形如:
<link rel="stylesheet" type="text/css" href="style.css"/>
你可也可以連結一個RSS,當使用Rss feed reader訂閱此頁面時,reader會自動分析頁面中是否包含<link title=”RSS”>的<link>節點,如果有則會以此為該頁面的RSS feed,如douban http://www.douban.com/subject/1000534/ 頁面:
<link rel="alternate" href="/feed/subject/1000534/reviews" type="application/rss+xml" title="RSS" />
這裡要說明一下<link rel=”stylesheet” …>和<link rel=”alternate stylesheet” …>兩種<link>節點,同樣都是連結了外部的css,但瀏覽器會預設採用<link ref=”stylesheet” …>指向的css,<link rel=”alternate stylesheet” …>將作為備選的css。我們可以通過JS編程的方式實現alternate stylesheet的切換,從而實現諸如字型變換,背景變化等,好像這些功能也是流行網站的標配。
Stylesheet switcher (pure js): http://www.dynamicdrive.com/dynamicindex9/stylesheetswitcher.htm
Switch to alterate stylesheet using jQuery: http://webdevcodex.com/how-to-switch-to-an-alternate-stylesheet-using-jquery/
工具 Tools
工欲善其事必先利其器,進行Web頁面開發的時候,有一個好的編輯器是非常重要的,最著名的當然是Adobe Dreamweaver了,但是我更喜歡另外的一個工具——微軟的Expression Web Designer 3,更簡潔的介面,更好的Asp.Net支援,html和css智能提示也不錯,superpreview的功能更方便於查看頁面的多瀏覽器安全色情況。
Expression Web Desginer 3 download (simplified-chinese):
" href="http://download.microsoft.com/download/3/5/8/358EF194-E47F-46BC-815F-D610732E977C/Web_Trial_zh-Hans.exe">http://download.microsoft.com/download/3/5/8/358EF194-E47F-46BC-815F-D610732E977C/Web_Trial_zh-Hans.exe
第二個推薦的工具時firefox+firebug,firebug提供了inspect element的功能,可以選擇頁面上的任一dom element查看html和css,非常方便。
firebug: http://getfirebug.com/
參考資料 References
CSS – The Definitive Guide, 3rd Edition http://www.douban.com/subject/2152110/
CSS Cookbook, 3rd Edition http://www.douban.com/subject/4016866/
W3School CSS Online Tutorial http://www.w3school.com.cn/css/index.asp
建議每一個Web開發人員都有機會通讀《CSS: The definitive guide》,對CSS有一個完整的掌握。