網頁

2013年5月12日 星期日

CSS 基礎與選擇器使用

參考文章:如何撰寫有效率的CSS選擇器(CSS Selector)
                    那些 CSS 偽元素可以幫你做的 10 個效果

CSS用來制定HTML元素的顯示外觀
在Web上的功能大致可區分為 HTML - 資料集合、JavaScript - 操作控制、CSS - 外觀指定
跟JavaScript一樣,CSS能以內部撰寫或引入外部連結使用
內部撰寫會需要在<head>元素裡撰寫<style>標籤,然後把CSS的內容寫在裡面
如:
<style>
    p { font-size:16px; }
</style>

你可能會發現把<style>標籤放到<body>裡也可以執行,但實務上非常不建議如此
原因是如果先讓瀏覽器讀取CSS,你可以快速地看到CSS的效果套用在HTML上
另一個原因則是每當瀏覽器在<body>裡讀取到<style>標籤後就會重新繪製畫面,以確保符合CSS要求
重新繪製畫面對效能上會有很大的影響

外部連結則需要在<head>元素裡撰寫<link>標籤
href屬性指定了CSS檔的位置,rel屬性則標示了檔案和頁面的關係,如下示範:
<link rel=stylesheet href="css/base.css" />

CSS的語法結構是選取器 { 屬性:設定值;} ,註解形式則為 /* here */
以 p { font-size:16px; } 為例,這行指定了所有的p元素都必須套用16px的字體大小設定

選取器(Selector)指定了那些元素應該套用宣告的內容
而且選取器會區分大小寫,所以只有完全符合的元素才會被選取
較常用的選取器有以下數種:
Universal selector -
選取頁面裡所有的元素,寫法: * {}

Type selectors -
選取符合指定類別的元素,寫法: p {}

Attribute selectors -
選取有特定屬性值的元素,寫法如下:
div[class] {}             選取有class屬性的div元素
div[class=demo] {}  選取有class屬性,值等於demo的div元素
div[class~=demo] {} 選取有class屬性,值含有demo的div元素,例如:<div calss="demo another">
div[class^=demo] {} 選取有class屬性,值以demo開頭的div元素
div[class*=demo] {} 選取有class屬性,值的字串包含demo的div元素
div[class$=demo] {} 選取有class屬性,值以demo結尾的div元素
屬性選擇器好用的地方在於當搭配 not 選擇敘述後,可以做到非常彈性的選擇
例如:input:not([type="radio"]):not([type="checkbox"]) 選取非 radio 、 checkbox 的 input 元素

Class selectors -
選取所有class值符合的元素,寫法: .demoElement {}

ID selectors -
選擇ID符合的元素,寫法: #header {} 取得id屬性值等於header的元素

Child selectors -
找出特定元素的直系子元素,寫法: li > a {} 指定所有父元素是li元素的a元素

Descendant selectors -
找出一指定元素的後代元素,寫法: li a {} 指定所有li元素裡的a元素,而不僅限於父子關係的元素

Adjacent sibling selectors -
選擇與特定元素同階層且相鄰的指定元素,寫法: div + p {} 指定所有與div元素同一層且相鄰的p元素

General sibling combinator -
選擇與特定元素同階層的指定元素,寫法: div ~ p {} 指定所有與div元素同一層的所有p元素

Groups of selectors -
若要對多種元素指定樣式,則可以用逗號分隔,寫法: h1, h2, p {} 選取所有的h1、h2及p元素

Pseudo-classes -
偽類別能給部分選擇器增加特殊效果,如:
a:link {color:#FF0000;}      /* unvisited link */
a:visited {color:#00FF00;}  /* visited link */
a:hover {color:#FF00FF;}  /* mouse over link */
a:active {color:#0000FF;}  /* selected link */
以上是常見對應連結的操作行為,這個部分不多提

Pseudo-element -
偽元素也同樣是給部分選擇器增加特殊效果
::first-line:   給第一行定義樣式 (瀏覽器會隨著放大或縮小來換行)
::first-letter:給第一個字母定義樣式 (以英文來看是第一個字母;中文就是第一個中文字)
::before:    在元素之前插入樣式/內容
::after:       在元素之後插入樣式/內容
::selection:定義當使用者反白<p>時的樣式

和偽類別的差別在於抽象的概念是否有增加新元素,例如:
.lineSection::after {
    content:'';
    display:block;
    clear:both;
    padding-top: 0;
}

在過去為了給流動式排版(float)的元素換行,常用作法是在後面塞一個空Div並指定clear的CSS屬性
透過偽元素::after ,就好像在該元素後面新增一個元素,並套用換行用的CSS
注意雖然外觀上看的到偽元素、偽類別的效果、影響
但實際上的HTML程式碼並沒有增加任何新元素,所以和DOM的操作一點關係也沒有

又例如撰寫反白效果,就好像在原本的元素位置上再增加反白顯示用的元素
span.hightlight::selection {
    background: #333;
    color: #eee;
}

所以善用偽元素可以讓HTML程式碼的結構更加清晰明瞭
注意在CSS3之後,為了區分偽元素和偽類別,偽元素的宣告須加上兩個 ':'


選擇器的執行速度一般來說不會特別注意
但如果建置/維護的網站規模龐大,則選擇器的設計也需要多加注意
執行速度依序為:

1. ID (#id)
2. Class (.class)
3. Type (如div)
4. Adjacent sibling (如: h2+p)
5. Child (如: li>ul)
6. Descendant (如:ul a)
7. Universal (*)
8. Attribute (如: [type="text"])
9. Pseudo-element/classes (如: a:hover)

一般設計上也常橋接選擇器,如:#list li a
上面的意思是選擇在ID為 list 的元素中的每個 li 元素中的所有 a 元素
當然這是就人類的自然語言的理解結果
實際上瀏覽器的套用過程是由右至左
也就是先選取所有的 a 元素,接著過濾出親代元素有 li 的結果,最後再過濾出位於#list底下的結果
從上述過程就可以知道效率改進的要旨
例如在最後要套用的a元素上加上class屬性,改為 #list li .selected
撰寫時擺脫不必要的指定也是一個要點,例如再將上述改成 #list selected 就少了一層的過濾


實務上很常見到一個元素會符合多種CSS宣告
而當宣告內容有所衝突時會依以下規則處理:
相同選取器的話則會以最後指定的宣告為準
選取器不同時則會依照選取器的敘述精確程度最高的宣告為準
例如同樣指定了 * {} 、p {} 同樣屬性的宣告,則 p {} 的會優先套用

略帶一提的是 font-family 屬性帶有繼承的效果
例如: body{ font-family: Arial, sans-serif;} 可以讓頁面上大部分的元素都套用相同的font-family設定
如果想強迫其他元素套用父元素的屬性值,可以設定為inherit,例如: .demo{ padding:inherit;}

沒有留言:

張貼留言