CSS選擇器世界
CSS選擇器的分類與優先級
css選擇器分為四類:選擇器、選擇符(后代關系的空格、>、+、~、||)、偽類、偽元素(::before、::after、::first-letter等)。
css的優先級:
css的優先級有很多划分方法,所有的方法其實都大同小異。這里將CSS優先級划分為6個等級:
- 0級:通配選擇器(*)、選擇符(+、>、~、空格、||)、邏輯組合偽類(:not()、:is()等)
- 1級:標簽選擇器
- 2級:類選擇器、屬性選擇器、偽類
- 3級:ID選擇器
- 4級:style內聯屬性
- 5級:!important
CSS優先級的計算規則:0級選擇器優先級數值+0,1級選擇器+1,2級選擇器+10,三級選擇器+100
#foo a:not([ref=nofollow]){} 優先級數值:100+1+0+10 = 111
tips1:增加CSS優先級的小技巧
重復自身選擇器,如以下選擇器即提高了優先級,又不會增加耦合:
.foo.foo
或者如下寫法:
.foo[class] 、 #foo[id]
tips2: 實現類似:first-child的效果
有如下場景,我們希望列表除了第一個第一個以外其他的都有margin-top,一般我們會這樣寫:
1:.cs:not(:first-child){margin-top:1em;}
2:.cs{margin-top:1em};
.cs:first-child{margin-top:0}
下面我們利用兄弟選擇器:
.cs+.cs{margin-top: 1em}
tips3:實現前面兄弟選擇符的效果
如下場景:輸入框聚焦時,前面文字高亮顯示
1:flex布局;
2:float浮動;
3:absolute絕對定位;
4:direction屬性實現,代碼如下:
<div class="cs-direction">
<input class="cs-input"><label class="cs-label">用戶名:</label>
</div>
.cs-direction{
direction: rtl
}
.cs-direction .cs-input,.cs-direction .cs-label{
direction: ltr;
}
.cs-label{
display:inline-block;
}
:focus + .cs-label{
color: darkblue;
text-shadow: 0 0 1px;
}
注意:使用direction屬性時,針對的必須為內聯元素,因此,對於塊級元素需進行轉化為內聯
屬性選擇器
-
[attr]
-
[attr = ''val']
-
[attr ~= 'val']
-
[attr ^= 'val']
-
[attr $= 'val']
-
[attr *= 'val']
用戶行為偽類
1:手型經過偽類:hover(支持所有HTML元素)
一個簡單的應用場景:當鼠標經過a標簽時,'顯示' 文字顯示,因為:hover是即時的,所以通過transition對visibility進行過渡(trantion對display不起作用)起到時延作用。
<a href class="icon-delete" data-title="顯示">刪除</a>
.icon-delete{
display: inline-block;
height: 20px;
position: relative;
}
.icon-delete::before{
content: attr(data-title);
position: absolute;
bottom: 30px;
left: 0;
}
.icon-delete::before,
.icon-delete::after {
transition: visibility 0s 0.2s;
visibility: hidden;
}
.icon-delete:hover::before,
.icon-delete:hover::after {
visibility: visible;
}
純hover顯示浮層的體驗問題:純hover顯示浮層確實很方便,但是如果鼠標壞了,或者是觸屏設備通過Tab來切換,如果是一個下拉列表,那么久完全癱瘓了,我們可以通過增加:focus來優化css,上述代碼可以優化為:
<a href class="icon-delete" data-title="刪除">刪除</a>
.icon-delete{
display: inline-block;
height: 20px;
position: relative;
}
.icon-delete::before{
content: attr(data-title);
position: absolute;
bottom: 30px;
left: 0;
}
.icon-delete::before,
.icon-delete::after {
transition: visibility 0s 0.2s;
visibility: hidden;
}
.icon-delete:hover::before,
.icon-delete:hover::after {
visibility: visible;
}
.icon-delete:focus::before,
.icon-delete:focus::after {
visibility: visible;
transition: none;
}
但是,上述並沒有解決所有的問題,如果浮層的內部有鏈接或者按鈕的話,使用:focus浮層內的連接或者按鈕是無法被點擊的,因為Tab在切換焦點元素的時候,浮層會失焦而迅速隱藏。這時需要另外一個偽類:focus-within來解決,詳細我們在下面討論。
2:激活偽類:active
:active可以用於設置元素激活狀態的樣式,可通過點擊鼠標主鍵,也可以通過手指或者觸控筆點擊觸摸屏觸發激活狀態。具體表現為 點擊按下觸發,點擊抬起取消。:active支持所有HTML元素
:active的不足之處:
- IE瀏覽器下,:active無法冒泡。即當一個元素與父級都設置:active樣式時,點擊子元素,父元素的:active不會被觸發
- IE瀏覽器,html、body用:active設置背景后,背景色無法還原;
- 移動端safari瀏覽器下,:active偽類默認無效
按鈕的通用:active樣式技巧(主要應用移動端)
在桌面端可以通過:hover來反饋狀態變化,移動端只能通過:active來反饋,移動端有很多需求點擊反饋鏈接跟按鈕,有如下通用技巧:
- 使用box-shadow(兼容IE9,該方法對非對稱閉合標簽無效)
[href]:active,button:active{
box-shadow: 0 0 0 999px rgba(0,0,0,.05);
}
- 使用linear-gradient線性漸變(兼容IE10以上)
[href]:active,button:active,[type=reset]:active,[type=button]:active,[type=submit]:active{
background-image: linear-gradient(rgba(0,0,0,.05),rgba(0,0,0,.05));
}
3:焦點偽類:focus(支持IE8+)
:focus只能匹配特定的元素,包括:
- 非disabled狀態的表單元素;
- 包含href的<a>元素
- <area>、<summary>
那么如何讓普通的元素也可以用:focus偽類呢?
設置HTML tabindex屬性,如下寫法:
<div tabindex='-1'>內容</div>
<div tabindex='0'>內容</div>
<div tabindex='1'>內容</div>
如果期望<div>元素被Tab索引,且被點擊的時候觸發:focus偽類樣式,設置tabindex='0';如果期望不希望被索引,只在點擊的時候觸發:focus,則設置為-1。
如下,實現點擊一個圖標顯示大圖的交互:
<span class="cs-small" tabindex='0'></span><span class="cs-big"></span>
.cs-small{
display: inline-block;
width: 10px;
height: 10px;
background: green;
};
.cs-big{
display: inline-block;
width: 50px;
height: 50px;
background: green;
margin-left: 10px;
display: none;
};
:focus + .cs-big{
display: inline-block;
}
實際上,使用tabindex也並不是那么完美,在ios safari瀏覽器下,元素處於focus狀態后,除非有其他可聚焦的元素轉移焦點,否則會一直保持聚焦狀態。解決方法只需要再套個父盒子,設置tabindex=‘-1’,同時該復盒子需要取消outline樣式(outline:0 none;)
4:整體焦點偽類:focus-within(移動端以及非IE瀏覽器)
:focus-within功能通:focus類似,但是:focus是對當前元素而言,:focus-within在當前元素或者當前元素的子元素處於聚焦狀態都會匹配。
例::focus-within 實現無障礙訪問的下拉列表,解決上面:focus在浮層里也有鏈接無法Tab切換的問題:
<div class="cs-bar">
<div class="cs-details">
<a href='javascript:void(0)' class="cs-summary">我的消息</a >
<div class="cs-datalist">
<a href class="cs-datalist-a">我的回答<sup class="cs-datalist-sup">12</sup>
</a >
<a href class="cs-datalist-a">我的私信</a >
</div>
</div>
</div>
cs-bar {
background-color: #e3e4e5;
color: #888;
padding-left: 40px;
margin-bottom: 200px;
}
.cs-details {
display: inline-block;
text-align: left;
}
.cs-summary {
display: inline-block;
padding: 5px 28px;
text-indent: -15px;
user-select: none;
position: relative;
z-index: 1;
}
.cs-datalist {
display: none;
position: absolute;
min-width: 100px;
border: 1px solid #ddd;
background-color: #fff;
margin-top: -1px;
}
.cs-datalist-a {
display: block;
padding: 5px 10px;
transition: background-color 0.2s, color 0.2s;
color: inherit;
}
.cs-datalist-a:hover {
background-color: #f5f5f5;
}
.cs-datalist-a:active {
background-color: #f0f0f0;
color: #555;
}
.cs-datalist-sup {
position: absolute;
color: #cd0000;
font-size: 12px;
margin-top: -0.25em;
margin-left: 2px;
}
.cs-details:focus-within .cs-summary,
.cs-summary:hover {
background-color: #fff;
}
.cs-details:focus-within .cs-datalist {
display: block;
}
URL定位偽類
:link偽類(基本被a標簽取代,不做討論)
:visited偽類(怪癖最多的CSS偽類)
- 1:支持:visited的CSS屬性有限
目前僅支持以下CSS: color、background-color、border-color、border-bottom-color、border-top-color、border-left-color、border-right-color、column-rule-color、outline-color。類似::before跟::after也不支持。
例:實現訪問過的連接文字后面加上一個visited的字樣
<a href=''>文字<small></small></a>
small{
color: white;
}
small:after{
content: 'visited';
}
a:visited small{
color: lightskyblue;
}
- 2:沒有半透明,該偽類控制顏色時,加透明度無效
- 3:只能重置,不能憑空設置
如下:
a{
color: blue;
}
a:visited{
color: red;
background-color: gray;
}
以上代碼設置只會使color生效。
- 4:無法獲取:visited設置和呈現的色值
該偽類設置的色值,用js的getComputedStyle()無法獲取。
:any-link偽類(IE9+)
兩大特性:
1.匹配所有設置了href的連接元素,包括<a>、<link>、<area>
2.匹配所有匹配:link偽類或者:visited偽類的元素(:link只匹配沒有訪問過的連接)
目標偽類:target
URL錨點可以跟頁面中元素的id匹配進行錨定,例:
<div>
<p id='cs-first'>第一行,id:cs-first</p>
<p id='cs-second'>第二行,id:cs-second</p>
<p id='cs-last'>第三行,id:cs-last</p>
</div>
p:target{
font-size: bold;
color: skyblue;
}
通過鏈接的hash值就可以匹配到對應的元素
樹結構偽類
:root偽類
在html中:root等同於html元素;
:empty偽類
- :empty用來匹配空標簽元素
- :empty偽類可以匹配前后閉合的替換元素(button、textarea等);
- :empty偽類匹配非閉合的元素(input、img等)
若元素有注釋或者空格、換行等都是不能匹配到的
::before、::after都可以插入內容,但是不會影響:empty的匹配
:empty的實際應用
- 隱藏空元素。
比如像一個動態列表有內容的時候可能會加margin、padding等布局,但是沒有內容的時候就會空出一大塊,這時候就可以用:empty偽類在匹配到空的時候隱藏掉。 - 字段缺失只能提示
如在一個動態詳情列表中,如果對應的字段沒有內容,則在后面顯示 '暫無'的字樣,代碼如下:
<dl>
<dt>姓名:</dt><dd>張三</dd><br/>
<dt>年齡:</dt><dd></dd><br/>
<dt>身高:</dt><dd>178cm</dd>
<dl>
dt,dd{
display: inline-block;
}
dd:empty:before{
content: '暫無';
}
子索引偽類
:first-child、:last-child
:only-child
:nth-child()偽類和:nth-last-child()偽類
適用於動態匹配場景,可以匹配制定索引序號的元素。參數可以是關鍵字(odd/even),也可以是函數符號。
函數符號形式如下:
- An+B: A、B必須為整數,n前面可以有負數,n為從1開始的自然序列(0,1,2…..),第一個子元素匹配序號為1.
- 一些示例:
- tr:nth-child(odd),匹配1、3、5…..行;
- tr:nth-child(even),匹配2、4、6…..;
- li:nth-child(1),匹配第一個;
- li:nth-child(n+4):nth-child(-n+10): 匹配4-10個li
:first-of-type偽類和:last-of-type偽類
表示當前標簽類型元素第一個和最后一個
:only-of-type
:nth-of-type()偽類和:nth-last-of-type偽類
:nth-of-type與:nth-child的不同之處::nth-of-type匹配的是所有相同標簽的兄弟元素,而另一個無視標簽類型。
<div>
<h3>標題一</h3>
<p>段落一</p>
<p>段落二</p>
<h3>標題二</h3>
<p>段落三</p>
<p>段落四</p>
</div>
p:nth-child(2n+1){
color: red;
}
p:nth-child(4n){
color: darkblue;
}
p:nth-of-type(2n+1){
color: skyblue;
}
圖中,第2、5行為淺藍色,第三行為紅色。
邏輯組合偽類
否定偽類:not()
:not()主要的應用場景為重置CSS
例:input:not(:disabled):not(:read-only)()
表示匹配所有不處於禁用,也不是只讀狀態的input
例: 列表一行5個,每個都向右有空隙,每一行的最后一個沒有空隙;
li:not(:nth-of-type(5n+1)){
margin-right: 10px;
}
任意匹配偽類:is()
例:
.cs-a img,.cs-b img,.cs-c img,.cs-d img{
border: 1px solid skyblue;
}
可以簡化為如下:
:is(.cs-a,.cs-b,.cs-c,.cs-d) img{
border: 1px solid skyblue;
}
:where()、:has()
輸入偽類
輸入控件狀態:
可用狀態與禁用狀態偽類 :enabled和:disabled (IE9+)
- 對於表單元素來說,:enable跟:disabled是完全對立的。但是有一個例外<a>元素,在chrome瀏覽器下,帶href的a元素是可以匹配:enabled偽類的,但是卻無法匹配:disabled偽類,其他瀏覽器也有各種各樣的問題,不展開討論。
- 設置tabindex屬性的元素不能匹配:enabled偽類;
- 元素設置visibility:hidden跟display:none的能夠匹配:enabled偽類跟:disabled偽類。
讀寫特性偽類:read-only和:read-write
readonly與disabled的區別:
設置readonly的輸入框不能輸入內容,但是可以被表單提交;
設置disabled的輸入框不能輸入內容美也不能被表單提交。
占位符顯示偽類:placeholder-shown(除IE)
表示當輸入框的placeholder內容顯示的時候,匹配輸入框
由於其只在內容為空值狀態的時候才顯示,所以我們可以借助placeholder-shown偽類來判斷一個輸入框是否有值。
例: 輸入框沒有值得時候顯示空值提示
input:placeholder-shown + small:before{
content: '尚未輸入驗證碼';
color: red;
}
默認選項偽類default
輸入值狀態:
選中選項偽類:checked
- :checked與[checked]的比較:
- :checked只能匹配標准的表單控件元素,[checked]可以與任意元素匹配;
- [checked]是非實時的,因此不建議用此屬性選擇器;
- 偽類可以從祖先元素繼承;
不確定值偽類:indeterminate
輸入值驗證:
有效驗證偽類:valid和:invalid
范圍驗證偽類:in-range和:out-of-range
可選性偽類:required和:optional
參考資料: