單選/覆選框是 Web 應用常用控制項,隨處可見,原生的單/覆選框控制項的外觀一般都不怎麼美觀,有些時候,原生的控制項模樣並不能滿足設計要求,這時需要更為精緻的控制項樣式,我們更希望其樣式可以允許自定義。 CSS3 新增了一個偽類選擇器 ,用於選擇被勾選的單/覆選框,利用該選擇器可以分別為未選中和選中狀態的 ...
單選/覆選框是 Web 應用常用控制項,隨處可見,原生的單/覆選框控制項的外觀一般都不怎麼美觀,有些時候,原生的控制項模樣並不能滿足設計要求,這時需要更為精緻的控制項樣式,我們更希望其樣式可以允許自定義。
CSS3 新增了一個偽類選擇器 :checked
,用於選擇被勾選的單/覆選框,利用該選擇器可以分別為未選中和選中狀態的單/覆選框應用不同的樣式,怎麼給它應用樣式呢?直接修改單/覆選框的樣式比較困難,不過可以使用一些其它方法來實現。
單選/覆選框作為一個表單控制項,可以使用一個 <label>
元素與之關聯,將 <label>
元素的 for
屬性指向覆選框的 id
屬性,這裡使用一個覆選框來舉例說明:
<input id="example-checkbox" type="checkbox">
<label for="example-checkbox">Check</label>
此時,每次點擊這個 <label>
元素會發現覆選框的選擇狀態也會變化,測試表明,點擊關聯某個單/覆選框的 <label>
時,產生的效果和點擊單/覆選框自身相同。然後,因為 <label>
元素緊鄰在單/覆選框之後,通過組合使用相鄰元素選擇器(Adjacent sibling selector),我們可以把相應的樣式應用到 <label>
元素上去,相比較而言,給 <label>
元素應用樣式要比給原生的單/覆選框應用樣式簡單多了。
相鄰元素選擇器,在兩個選擇器中間添加一個加號,像這樣 selector1 + selector2,表示選擇 selector1 元素之後緊鄰的 selector2 元素:
input[type="checkbox"] + label {
/* 未選中狀態 */
}
input[type="checkbox"]:checked + label {
/* 選中狀態 */
}
為了不對 <label>
元素自身的樣式造成影響,這裡使用生成內容偽元素(::before/::after)來應用單/覆選框的自定義樣式,首先使用 ::before 偽元素來生成覆選框的外框樣式:
input[type="checkbox"] + label::before {
background-color: #fff;
border: 1px solid #50a7f8;
border-radius: 3px;
content: "\00a0";
height: 13px;
left: 0;
position: absolute;
width: 13px;
}
然後使用 ::after 偽元素來生成覆選框中間的勾的樣式,用一個矩形只應用左邊框和下邊框,然後逆時針旋轉 45 度即可做成一個簡單的勾形:
input[type="checkbox"] + label::after {
background: transparent;
border: 0 solid #50a7f8;
border-width: 0 0 3px 3px;
content: "\00a0";
height: 3px;
left: 3px;
position: absolute;
top: 3px;
transform: scale(0) rotate(-45deg);
transition: transform 0.2s linear;
width: 6px;
}
為了在沒有勾選的時候不顯示這個勾,這裡用 transform: scale(0)
來隱藏了這個勾,當覆選框被勾選的時候才顯示出來:
input[type="checkbox"]:checked + label::after {
transform: scale(1) rotate(-45deg);
}
這裡使用了絕對定位,所以給 <label>
元素增加一個相對定位,併在左邊預留一定的空間:
input[type="checkbox"] + label {
min-height: 20px;
padding-left: 20px;
position: relative;
}
原生的控制項可以把它隱藏掉了:
input[type="checkbox"] {
display: none;
}
不過這樣隱藏後就不能通過 Tab 鍵來與控制項交互了,所以可以用另外的方法來隱藏控制項,比如設置不透明度為 0:
input[type="checkbox"] {
opacity: 0;
position: absolute;
}
進一步,可以定義控制項獲取焦點時以及控制項禁用時的樣式:
input[type="checkbox"]:focus + label::before {
outline: 1px dotted #aaa;
}
input[type="checkbox"]:disabled + label::before {
background-color: #eee;
border-color: #aaa;
}
input[type="checkbox"]:disabled + label::after {
border-color: #aaa;
}
更進一步,給勾選添加過渡效果:
input[type="checkbox"] + label::after {
transition: transform 0.2s linear;
}
單選框
和覆選框一樣,只是把自定義樣式中的外框換成圓形外框,內部的勾換成一個實心圓:
<input id="example-radio" type="radio">
<label for="example-radio">Check</label>
HTML 結構是一樣,樣式也是類似:
input[type="radio"] {
opacity: 0;
position: absolute;
}
input[type="radio"] + label {
min-height: 20px;
padding-left: 20px;
position: relative;
}
input[type="radio"] + label::before {
background-color: #fff;
border: 1px solid #50a7f8;
border-radius: 50%;
content: "\00a0";
height: 13px;
left: 0;
position: absolute;
top: 0;
width: 13px;
}
input[type="radio"] + label::after {
background: #50a7f8;
border-radius: 50%;
content: "\00a0";
height: 9px;
left: 3px;
position: absolute;
top: 3px;
transform: scale(0);
transition: transform .2s linear;
width: 9px;
}
input[type="radio"]:checked + label::after {
transform: scale(1);
}
input[type="radio"]:focus + label::before {
outline: 1px dotted #aaa;
}
input[type="radio"]:disabled + label::before {
background-color: #eee;
border-color: #aaa;
}
input[type="radio"]:disabled + label::after {
background-color: #aaa;
}
這篇文章里用到了很多種類的選擇器,詳情可以參考Selectors Level 3
我將這篇文章里涉及到的內容整合成了一個插件,Radio 歡迎吐槽。