純樣式無腳本無圖片自定義單/復選框


單選/復選框是 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 歡迎吐槽。

參考資料


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM