CSS基本功從頭練之Selector
CSS一直是我的短板需曾,從來(lái)沒(méi)有系統(tǒng)學(xué)過(guò)寺惫,一直都是使用第三方的樣式庫(kù),或者在網(wǎng)上找點(diǎn)資料copy蕉毯。最近感覺(jué)應(yīng)該系統(tǒng)的梳理一下乓搬,否則很多概念還是不太清晰。還是屬于邊學(xué)邊寫(xiě)的資料代虾,難免各種漏洞进肯,希望大家多指正。
Selector(選擇器)
為什么會(huì)有選擇器這個(gè)概念棉磨?因?yàn)闃邮阶罱K是要應(yīng)用到HTML的元素上的江掩,那么哪一類(lèi)樣式應(yīng)該應(yīng)用到什么元素這個(gè)問(wèn)題就催生了選擇器的誕生〕巳浚總體來(lái)說(shuō)环形,Selector分標(biāo)簽選擇器、類(lèi)選擇器衙傀、ID選擇器和屬性選擇器
標(biāo)簽選擇器
顧名思義是以HTML標(biāo)簽作為篩選依據(jù)的抬吟,比如下面的代碼中,我們的可見(jiàn)標(biāo)簽一共有:<html>
统抬、<body>
火本、<div>
、<label>
蓄喇、<input>
和<output>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<div>
<label for="weight">體重</label>
<input id="weight" type="number">
</div>
<div>
<label for="height">身高</label>
<input id="height" type="number">
</div>
<div>
<label for="bmi">BMI</label>
<output id="bmi"></output>
</div>
</body>
</html>
如果我們?cè)赾ss中有下面的定義发侵,那么我們其實(shí)是對(duì)所有 <body>
標(biāo)簽(雖然事實(shí)上只有一個(gè))應(yīng)用樣式背景色 #DCEDC8
,而對(duì)所有 <input>
標(biāo)簽應(yīng)用樣式背景色 #8BC34A
body {
background-color: #DCEDC8;
}
input {
background-color: #8BC34A;
}

類(lèi)選擇器
類(lèi)選擇器的篩選標(biāo)準(zhǔn)是用類(lèi)來(lái)確定的妆偏,就是在html標(biāo)簽中,我們一般可以用 class="blablabla"
來(lái)完成樣式的類(lèi)指定≈殉冢現(xiàn)在我們改寫(xiě)HTML钱骂,把所有l(wèi)abel指定一個(gè) class="label"
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<div>
<label class="label" for="weight">體重</label>
<input id="weight" type="number">
</div>
<div>
<label class="label" for="height">身高</label>
<input id="height" type="number">
</div>
<div>
<label class="label" for="bmi">BMI</label>
<output id="bmi"></output>
</div>
</body>
</html>
然后在css中加上一個(gè)類(lèi)樣式定義,在css中我們?cè)陬?lèi)名的前面加上一個(gè) .
來(lái)表示這是個(gè)類(lèi)樣式定義挪鹏。
.label {
color: #fff;
}

ID選擇器
我們看到上面的HTML代碼中见秽,有一些元素是有 id
這個(gè)屬性的,那么這個(gè)選擇器當(dāng)然就是用來(lái)選擇 id="blablabla"
的元素的讨盒。如果我們?cè)赾ss中給BMI結(jié)果加入一個(gè)ID選擇器解取,放大結(jié)果的字體。
#bmi {
font-size: xx-large;
}

屬性選擇器
屬性選擇器就是對(duì)HTML標(biāo)簽中含有的屬性進(jìn)行篩選返顺,比如上例中我們?nèi)绻雽?duì)標(biāo)簽中 for
屬性禀苦、值為weight
的進(jìn)行特殊處理蔓肯,那么我們可以看到下圖的效果。
label[for="weight"] {
color: #FF4081;
}

其實(shí)我感覺(jué)前面的ID選擇器振乏、類(lèi)選擇器甚至標(biāo)簽選擇器都應(yīng)該是屬性選擇器的一種特殊形式蔗包,比如我們其實(shí)把 #bmi
那段代碼注釋掉,換成屬性選擇器:選擇 id="bmi"
的形式效果是一樣的慧邮。
/* #bmi {
font-size: xx-large;
} */
output[id="bmi"] {
font-size: xx-large;
}
屬性選擇器的花樣最多调限,下面我們來(lái)看看,如果不用 =
误澳,而使用 ~=
是什么效果耻矮。我們把bmi的label中的for改成 for="weight height"
。
<div>
<label class="label" for="weight height">BMI</label>
<output id="bmi"></output>
</div>
然后在css中用 ~=
替代 =
看看會(huì)發(fā)生什么忆谓?我們看到體重和BMI都應(yīng)用了 #FF4081
這個(gè)顏色裆装。也就說(shuō) ~=
表示選擇所有含有等號(hào)后面的值的元素。
label[for~="weight"] {
color: #FF4081;
}

但是注意一點(diǎn)陪毡,~=
后面的一定是一個(gè)完整的屬性值米母,而不是含有這個(gè)字符串就行,比如上面HTML中如果我們寫(xiě)成 for="weight1 height"
那么這個(gè)選擇器就無(wú)法生效了毡琉。
css1中還支持一種符號(hào) |=
铁瞒,它會(huì)選擇所有以等號(hào)后的值開(kāi)頭的元素,同樣的桅滋,這里的開(kāi)頭指的是完整屬性值而不是字符串意義上的開(kāi)頭慧耍。那么問(wèn)題來(lái)了,有沒(méi)有辦法選擇字符串呢丐谋?css3中增加了 ^=
芍碧、$=
和 *=
這幾個(gè)符號(hào),是專(zhuān)門(mén)處理字符串這種需求的号俐。題外話(huà)感覺(jué)這幾個(gè)操作符很像正則表達(dá)式中的泌豆。
還是上面的例子,我們的html如下吏饿,注意bmi的label的for中是 weight1
踪危,而體重label的for中是 weight
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<script src="https://unpkg.com/@reactivex/rxjs@5.0.0-beta.7/dist/global/Rx.umd.js"></script>
<title>JS Bin</title>
</head>
<body>
<div>
<label class="label" for="weight">體重</label>
<input id="weight" type="number">
</div>
<div>
<label class="label" for="height">身高</label>
<input id="height" type="number">
</div>
<div>
<label class="label" for="weight1 height">BMI</label>
<output id="bmi"></output>
</div>
</body>
</html>
css中我們使用 ^=
來(lái)試驗(yàn)一下,你會(huì)發(fā)現(xiàn)選擇器又生效了猪落。
label[for^="weight"] {
color: #FF4081;
}

同樣的如果我們換成下面的css贞远,你會(huì)發(fā)現(xiàn)所有的label都變色了,因?yàn)槎际?eight
這個(gè)字符串結(jié)尾的
label[for$="eight"] {
color: #FF4081;
}

這時(shí)你會(huì)問(wèn)笨忌,不對(duì)啊蓝仲,bmi的label是 weight1
啊,但是請(qǐng)看仔細(xì) for="weight1 height"
,這個(gè)字符串的最后是 height
袱结。
*=
是選擇字符串中包含某個(gè)值的元素亮隙,遇到它的話(huà)我比較好奇的是它能不能選擇空格,因?yàn)?for="weight1 height"
中含有一個(gè)空格擎勘。于是我做了個(gè)實(shí)驗(yàn)咱揍,用如下的css證明了是可以選擇空格的。
label[for*=" "] {
color: #FF4081;
}

上下文選擇器
如果僅有上面這些也還不錯(cuò)棚饵,css的強(qiáng)大或者說(shuō)復(fù)雜在于還特么能組合煤裙。這個(gè)上下文選擇器可以看作組合的一種,它利用多種符號(hào)連接標(biāo)簽選擇器來(lái)實(shí)現(xiàn)根據(jù)上下文選擇元素的目的噪漾。
還是用實(shí)例說(shuō)話(huà)硼砰,首先最簡(jiǎn)單的組合符號(hào) ,
,為了看的更清楚一些欣硼,我們重新定義HTML:在最外面包了一層 div
题翰,并且給每一層 div
都指定了一個(gè)樣式類(lèi)。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<script src="https://unpkg.com/@reactivex/rxjs@5.0.0-beta.7/dist/global/Rx.umd.js"></script>
<title>JS Bin</title>
</head>
<body>
<div class="content">
<div class="weight">
<label class="label" for="weight">體重</label>
<input id="weight" type="number">
</div>
<div class="height">
<label class="label" for="height">身高</label>
<input id="height" type="number">
</div>
<div class="bmi">
<label class="label" for="weight1 height">BMI</label>
<output id="bmi"></output>
</div>
</div>
</body>
</html>
在 css
中為幾個(gè) div
定義背景色诈胜,以便看的更清楚些豹障。然后利用 ,
定義了 div,label
的padding是 20px
...
.weight {
background-color: gray;
}
.height {
background-color: silver;
}
.bmi {
background-color: darkgray;
}
.content{
background-color: brown;
}
div,label {
padding: 20px;
}
,
這種就比較簡(jiǎn)單,就是多個(gè)標(biāo)簽都使用這個(gè)樣式焦匈,我們來(lái)看看效果:



這個(gè)操作符我認(rèn)為只起到節(jié)省代碼的作用;-)
后代選擇器
(空格)
下面我們看看 (空格)這個(gè)操作符缓熟,還是為了更明顯累魔,我們?cè)贖TML中的最外層div之外加一行
<label for="something">我不在div中,所以沒(méi)有變大</label>
我們?cè)赾ss中加上下面的定義够滑,我們會(huì)看到垦写,div內(nèi)部的所有l(wèi)abel的文字都變大了,但外部的沒(méi)有彰触。所以 x y
表示選擇在x
元素內(nèi)部的所有y
div label {
font-size: x-large;
}

子選擇器 >
那么下面我們看看 >
梯投,同樣需要改造一下HTML,在 <div class="content">
下加入下面的代碼况毅。
<p>
<label for="something">我的父節(jié)點(diǎn)不是div晚伙,所以沒(méi)有變大</label>
</p>
將css改成
div>label {
font-size: x-large;
padding:20px;
}
下面看看效果,剛剛加入的那個(gè)label文字沒(méi)有變大的原因在于它的父節(jié)點(diǎn)是 <p>

“親兄弟”選擇器 +
接下來(lái)的這位就有意思了 +
俭茧,你如果把 div+label
直接套用到上面的HTML中,會(huì)發(fā)現(xiàn)沒(méi)什么作用漓帚,哪個(gè)字體也沒(méi)變大母债。原因是這個(gè)符號(hào)是選擇div 之后 的 緊挨著 div的label元素。
那么我們的實(shí)驗(yàn)之前,請(qǐng)把下面的代碼插入到最外層div之后
<label for="something">我不在div中但緊挨著div毡们,所以變大了</label>
<label for="something">我雖然在div后但沒(méi)有緊挨著div迅皇,所以沒(méi)有變大了</label>

"兄弟連"選擇器 ~
有看后面的就有看前面的,接下來(lái)就是 ~
閃亮登場(chǎng)了衙熔,div~label
是個(gè)什么效果捏登颓? 事實(shí)證明 x~y
是用于選擇前面有 x
的所有 y
div~label {
font-size: x-large;
padding:20px;
}

偽類(lèi)
為什么叫這個(gè)名字?我也不知道红氯,感覺(jué)有點(diǎn)怪框咙,聽(tīng)說(shuō)一個(gè)說(shuō)法是它們很像類(lèi),但我真沒(méi)看出哪兒像痢甘。偽類(lèi)一般都是以 :
開(kāi)頭喇嘱,也不光是偽類(lèi)的捞烟,偽元素也是 :
開(kāi)頭匆背。
鏈接偽類(lèi)
首先看鏈接偽類(lèi),這個(gè)其實(shí)沒(méi)什么好講域仇,就是因?yàn)殒溄佑袔讉€(gè)狀態(tài)放椰,普通的選擇器無(wú)法篩選出來(lái)導(dǎo)致硬生生的造出來(lái)這幾個(gè)東東作烟。需要注意的是,這些貨必須按著下面的順序給出才可以生效砾医。其實(shí)我實(shí)驗(yàn)了一下拿撩,link和visited調(diào)換位置沒(méi)影響,其他按順序是因?yàn)檫@幾個(gè)狀態(tài)有時(shí)有重疊藻烤,寫(xiě)錯(cuò)順序會(huì)導(dǎo)致樣式被覆蓋绷雏。比如鼠標(biāo)按下未抬起其實(shí)同時(shí)也滿(mǎn)足hover的條件,如果我們把hover放在最后怖亭,active放在前面涎显,那么這時(shí)就會(huì)以最后的樣式(hover)覆蓋前面的樣式(active)
- link: 沒(méi)有訪(fǎng)問(wèn)過(guò)也沒(méi)有鼠標(biāo)懸停或點(diǎn)擊的狀態(tài)兴猩。
- visited:用戶(hù)點(diǎn)擊過(guò)這個(gè)鏈接之后的狀態(tài)期吓。
- hover:鼠標(biāo)指針正懸停在連接上。
- active:鏈接正在被點(diǎn)擊(鼠標(biāo)在元素上按下倾芝,還沒(méi)有釋放)讨勤。
“選中狀態(tài)”偽類(lèi)
再來(lái)看 :focus
偽類(lèi),這個(gè)也是由于輸入框處于聚焦?fàn)顟B(tài)時(shí)無(wú)法通過(guò)其他選擇器選取而特別定制的晨另,我們看一下效果
input:focus {
background-color: #C5CAE9;
}

同理潭千,還有類(lèi)似的對(duì)于復(fù)選框、單選框等選中狀態(tài)的選擇所設(shè)計(jì)的 :checked
借尿;為元素禁用和激活狀態(tài)所設(shè)計(jì)的 :enabled
和 :disabled
刨晴。這些就不舉例了屉来,比較簡(jiǎn)單,如果有坑狈癞,請(qǐng)指教茄靠。
“排頭兵”偽類(lèi)
:first-letter
、 :first-line
蝶桶、 :first-child
這幾個(gè)跟在某個(gè)元素后面的作用是選取該元素的第一個(gè)文字(英文的話(huà)是字母)慨绳、第一行和父元素的第一個(gè)子元素中的所有該元素。還是看圖說(shuō)話(huà)吧真竖。
我們把體重的selector加了一個(gè)首字母?jìng)晤?lèi)放大字體200%脐雪,效果如下圖,另兩個(gè)的效果類(lèi)似疼邀,只不過(guò)是第一行或者第一個(gè)子元素喂江,自己可以實(shí)驗(yàn)一下。
.weight:first-letter {
font-size:200%;
}

“前綴”和“后綴”偽類(lèi)
為什么叫它們“前綴”和“后綴”呢旁振?因?yàn)樗鼈兪亲饔糜谶x擇內(nèi)容之前或之后的获询,為什么要設(shè)計(jì)這個(gè)選擇器呢?我們的BMI計(jì)算器目前的兩個(gè)輸入值都是沒(méi)有單位的拐袜。如果我們希望增加一個(gè)單位的話(huà)吉嚣,當(dāng)然可以在HTML頁(yè)面增加,但是如果對(duì)于某一類(lèi)值它們的單位就是某些文字的話(huà)蹬铺,這么做就有點(diǎn)累尝哆。我們給css加上下面的樣式看看效果。
.weight::after {
content: "公斤";
}
.height::after {
content: "厘米";
}
另外一個(gè)比較常見(jiàn)的技巧是利用這個(gè)偽類(lèi)去改造默認(rèn)的控件樣式甜攀,比如復(fù)選框默認(rèn)是方塊型秋泄,如何改造成圓形呢?我們就可以先把復(fù)選框中的原有表現(xiàn)形式(方塊)隱藏起來(lái)规阀,然后利用“后綴”偽類(lèi)畫(huà)出一個(gè)圓來(lái)恒序。
//html
<input type="checkbox" class="check">
//css
.check {
background-color: #8BC34A;
width: 40px;
-webkit-appearance: none;
appearance: none;
}
.check::after {
content: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="-10 -18 100 135"><circle cx="50" cy="50" r="50" fill="none" stroke="#fff" stroke-width="3"/></svg>');
}

“正著數(shù)和倒著數(shù)”偽類(lèi)
css增加一堆很類(lèi)似數(shù)組或集合中常用的選擇器,這一類(lèi)的大部分都是成對(duì)的谁撼,可以記成正著數(shù)和倒著數(shù)歧胁。為了方便記憶,我就起名叫“正著數(shù)和倒著數(shù)”偽類(lèi)了厉碟。這一類(lèi)有好多喊巍,包括選擇首尾的: :first-of-type
,:last-of-type
箍鼓,:first-child
(這個(gè)不是css3引入的)崭参,:last-child
;第n個(gè)子元素的 :nth-child(n)
款咖,:nth-last-child(n)
阵翎;第n個(gè)某類(lèi)型子元素:nth-of-type(n)
逢并,:nth-last-of-type(n)
;當(dāng)然對(duì)于特殊情況郭卫,比如只有一個(gè)的會(huì)有專(zhuān)門(mén)的處理::only-child
,:only-of-type
應(yīng)用這種選擇器可以非常方便的打造一些效果背稼,比如交替顏色的表格贰军。
table {
width: 100%;
}
tr:nth-child(even){background-color: #f2f2f2}

這里有問(wèn)題了,這個(gè) even
是怎么回事蟹肘?這一類(lèi)Selector是可以接受表達(dá)式作為參數(shù)的词疼,而 even
和 odd
作為兩個(gè)特別常用的東東被認(rèn)定成關(guān)鍵字,其實(shí) nth-child(even)
可以改寫(xiě)成 nth-child(2n)
而 nth-child(odd)
可以改寫(xiě)成 nth-child(2n+1)
帘腹。是的贰盗,如果你愿意可以寫(xiě)出3的倍數(shù),5的倍數(shù)等等序列等等阳欲。