首頁 >web前端 >css教學 >css改變單選框顏色的方法實作(附程式碼)

css改變單選框顏色的方法實作(附程式碼)

不言
不言轉載
2018-10-12 16:58:2810264瀏覽

這篇文章帶給大家的內容是關於css改變單選框顏色的方法實現(附程式碼),有一定的參考價值,有需要的朋友可以參考一下,希望對你有幫助。

是否曾經被業務提出"能改改這個單選框的顏色吧!讓它和主題顏色搭配一下吧!",然後苦於原生不支持換顏色,最後被迫自己手擼一個湊合使用。若拋開input[type=radio]重新開發一個,發現要模擬選取、未選取、不可用等狀態很繁瑣,而涉及單選框組就更煩人了,其實我們可以通過label、::before、: checked和tabindex,然後外加少量JavaScript腳本就能很好地模擬出一個樣式更豐富的「原生」單選框。下面我們就一起來試試看吧!

單選框了解一下

由於我們的目標是改變單選框顏色,其他外觀特徵和行為與原來的單選框一致,那麼我們就必須先了解單選框原來的外觀特徵和行為主要有哪些。
1.外觀特徵
1.1.常態樣式

margin: 3px 3px 0px 5px;
border: none 0;
padding: 0;
box-sizing: border-box;
display: inline-block;
line-height: normal;
position: static;

注意:外觀上我們必須要保證佈局特性和原生的一致,否則採用自訂單選框替換後很大機會會影響整體的佈局,最後導致被迫調整其他元素的佈局特性來達到整體的協調,從而擴大了修改範圍。

1.2.獲得焦點的樣式

outline-offset: 0px;
outline: -webkit-focu-ring-color auto 5px;

注意:這裡的獲取焦點的樣式僅透過鍵盤Tab鍵才生效,若透過滑鼠點選雖然單選框已獲得焦點,但上述樣式並不會生效。

1.3.設定為disabled的樣式

color: rgb(84, 84, 84);

2.行為特徵
 單選框的行為特徵,明顯就是選取與否,及選取狀態的改變事件,因此我們必須保持對外提供change事件。
 另外值得注意的是,當透過鍵盤的Tab鍵讓單選框獲得焦點後,再按下Space鍵則會選取該單選框。

 有了上述的了解,我們可以開始著手擼程式碼了!

少廢話,擼程式碼

css改變單選框顏色的方法實作(附程式碼)

上圖左側就是原生單選框,右側為我們自訂的單選框。從上到下依序為未選取選取取得焦點disabled狀態的樣式。

CSS部分

label.radio {
  /* 保证布局特性保持一致 */
  margin: 3px 3px 0px 5px;
  display: inline-block;
  box-sizing: border-box;

  width: 12px;
  height: 12px;
}

.radio__appearance{
  display: block; /* 设置为block则不受vertical-align影响,从而不会意外影响到.radio的linebox高度 */
  position: relative;
  box-shadow: 0 0 0 1px tomato; /* box-shadow不像border那样会影响盒子的框高 */
  border-radius: 50%;
  height: 90%;
  width: 90%;
  text-align: center;
}
label.radio [type=radio] + .radio__appearance::before{
  content: "";
  display: block;
  border-radius: 50%;
  width: 85%;
  height: 85%;

  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);

  transition: background .3s;
}
label.radio [type=radio]:checked + .radio__appearance::before{
  background: tomato;
}
label.radio [type=radio][disabled] + .radio__appearance{
  opacity: .5;
}
label.radio:focus{
  outline-offset: 0px;
  outline: #999 auto 5px;
}
/* 通过鼠标单击获得焦点时,outline效果不生效 */
label.radio.clicked{
  outline: none 0;
}
/* 自定义单选框的行为主要是基于原生单选框的,因此先将原生单选框隐藏 */
label.radio input {
  display: none;
}

HTML部分

<!-- 未选中状态 -->
<label>
  <input>
  <i></i>
</label>

<br>

<!-- 选中状态 -->
<label>
  <input>
  <i></i>
</label>

<br>

<!-- disabled状态 -->
<label>
  <input>
  <i></i>
</label>

JavaScript部分

var radios = document.querySelectorAll(".radio")
radios.forEach(radio => {
  // 模拟鼠标点击后:focus样式无效
  radio.addEventListener("mousedown", e => {
    var tar = e.currentTarget
    tar.classList.add("clicked")
    var fp = setInterval(function(){
      if (document.activeElement != tar){
        tar.classList.remove("clicked")
        clearInterval(fp)
      }
    }, 400)
  })
  // 模拟通过键盘获得焦点后,按`Space`键执行选中操作
  radio.addEventListener("keydown", e => {
    if (e.keyCode === 32){
      e.target.click()
    }
  })
})

這個實作有3個注意點:

1、通過label傳遞滑鼠點選事件到關聯的input[type=radio],因此可以安心隱藏單選框又可以利用單選框自身特性。但由於label控製本身的限制,如預設不是可取得焦點元素,因此無法傳遞鍵盤按鍵事件到單選框,即使加入tabindex特性也需手寫JS來實現;

#2、當tabindex大於等於0時表示該元素可以獲得焦點,為0時表示根據元素所在位置安排獲得焦點的順序,而大於0則表示越小越先獲得焦點;

3、由於單選框的display為inline-block,因此單選框將影響line box高度。當自訂單選框內元素採用inline-block時,若vertical-align設定稍有不慎就會導致內部元素所在的line box被撐高,從而導致自訂單選框所在的line box高度變大。因此這裡採用將內部元素的display皆設定為block的做法,直接讓vertical-align失效,提升可控性。

透過opacity:0實作

 上面我們透過label關聯display:none的input[type=radio]從而利用input[type=radio]簡化自訂單選框的實現,但還是要手寫JS實現按Space鍵選中的行為特徵,有沒有另一種方式可以更省事呢?我們只是想讓用戶看不到原生單選框,那麼直接設定為opacity:0不就可以了嗎? !

CSS部分

.radio {
  /* 保证布局特性保持一致 */
  margin: 3px 3px 0px 5px;
  display: inline-block;
  box-sizing: border-box;

  width: 13px;
  height: 13px;
}
/* 自定义单选框的行为主要是基于原生单选框的,因此先将原生单选框透明,且沾满整个父元素 */
.radio input {
  opacity: 0;
  position: absolute;
  z-index: 1; /* 必须覆盖在.radio__appearance上才能响应鼠标事件 */
  width: 100%;
  height: 100%;
}
.radio__container-box{
  position: relative;
  width: 100%;
  height: 100%;
}
.radio__appearance{
  display: block; /* 设置为block则不受vertical-align影响,从而不会意外影响到.radio的linebox高度 */
  position: relative;
  box-shadow: 0 0 0 1px tomato; /* box-shadow不像border那样会影响盒子的框高 */
  border-radius: 50%;
  height: 90%;
  width: 90%;
  text-align: center;
}
.radio [type=radio] + .radio__appearance::before{
  content: "";
  display: block;
  border-radius: 50%;
  width: 85%;
  height: 85%;

  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);

  transition: background .3s;
}
.radio [type=radio]:checked + .radio__appearance::before{
  background: tomato;
}
.radio [type=radio][disabled] + .radio__appearance{
  opacity: .5;
}
.radio:focus-within .radio__appearance{
  outline-offset: 0px;
  outline: #999 auto 5px;
}
/* 通过鼠标单击获得焦点时,outline效果不生效 */
.radio.clicked .radio_appearance{
  outline: none 0;
}

HTML部分

<!-- 未选中状态 -->
<span>
  <span>
    <input>
    <i></i>
  </span>
</span>

<br>

<!-- 选中状态 -->
<span>
  <span>
    <input>
    <i></i>
  </span>
</span>

<br>

<!-- disabled状态 -->
<span>
  <span>
    <input>
    <i></i>
  </span>
</span>

JavaScript部分

var radios = document.querySelectorAll(".radio")
radios.forEach(radio => {
  // 模拟鼠标点击后:focus样式无效
  radio.addEventListener("mousedown", e => {
    var tar = e.currentTarget
    tar.classList.add("clicked")
    var fp = setInterval(function(){
      if (!tar.contains(document.activeElement){
        tar.classList.remove("clicked")
        clearInterval(fp)
      }
    }, 400)
  })
})

總結

#對於複選框我們可以稍加修改就可以了,然後透過VUE、React等框架稍微封裝一下提供更簡約的API,使用起來就更方便了。

以上是css改變單選框顏色的方法實作(附程式碼)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:segmentfault.com。如有侵權,請聯絡admin@php.cn刪除