摘要:前言是否曾經(jīng)被業(yè)務提出能改改這個單選框的顏色吧讓它和主題顏色搭配一下吧,然后苦于原生不支持換顏色,最后被迫自己手擼一個湊合使用。設置為的樣式行為特征單選框的行為特征,明顯就是選中與否,及選中狀態(tài)的改變事件,因此我們必須保持對外提供事件。
前言
?是否曾經(jīng)被業(yè)務提出"能改改這個單選框的顏色吧!讓它和主題顏色搭配一下吧!",然后苦于原生不支持換顏色,最后被迫自己手擼一個湊合使用。若拋開input[type=radio]重新開發(fā)一個,發(fā)現(xiàn)要模擬選中、未選中、不可用等狀態(tài)很繁瑣,而涉及單選框組就更煩人了,其實我們可以通過label、::before、:checked和tabindex,然后外加少量JavaScript腳本就能很好地模擬出一個樣式更豐富的“原生”單選框。下面我們一起來嘗試吧!
單選框了解一下?由于我們的目標是改變單選框顏色,其他外觀特征和行為與原來的單選框一致,那么我們就必須先了解單選框原來的外觀特征和行為主要有哪些。
1.外觀特征
1.1.常態(tài)樣式
margin: 3px 3px 0px 5px; border: none 0; padding: 0; box-sizing: border-box; display: inline-block; line-height: normal; position: static;
注意:外觀上我們必須要保證布局特性和原生的一致,否則采用自定義單選框替換后很大機會會影響整體的布局,最后導致被迫調(diào)整其他元素的布局特性來達到整體的協(xié)調(diào),從而擴大了修改范圍。
1.2.獲得焦點的樣式
outline-offset: 0px; outline: -webkit-focu-ring-color auto 5px;
注意:這里的獲取焦點的樣式僅通過鍵盤Tab鍵才生效,若通過鼠標點擊雖然單選框已獲得焦點,但上述樣式并不會生效。
1.3.設置為disabled的樣式
color: rgb(84, 84, 84);
2.行為特征
?單選框的行為特征,明顯就是選中與否,及選中狀態(tài)的改變事件,因此我們必須保持對外提供change事件。
?另外值得注意的是,當通過鍵盤的Tab鍵讓單選框獲得焦點后,再按下Space鍵則會選中該單選框。
?有了上述的了解,我們可以開始著手擼代碼了!
少廢話,擼代碼上圖中左側(cè)就是原生單選框,右側(cè)為我們自定義的單選框。從上到下依次為未選中、選中、獲得焦點和disabled狀態(tài)的樣式。
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部分
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`鍵執(zhí)行選中操作 radio.addEventListener("keydown", e => { if (e.keyCode === 32){ e.target.click() } }) })
這個實現(xiàn)有3個注意點:
通過label傳遞鼠標點擊事件到關(guān)聯(lián)的input[type=radio],因此可以安心隱藏單選框又可以利用單選框自身特性。但由于label控件自身的限制,如默認不是可獲得焦點元素,因此無法傳遞鍵盤按鍵事件到單選框,即使添加tabindex特性也需手寫JS來實現(xiàn);
當tabindex大于等于0時表示該元素可以獲得焦點,為0時表示根據(jù)元素所在位置安排獲得焦點的順序,而大于0則表示越小越先獲得焦點;
由于單選框的display為inline-block,因此單選框?qū)⒂绊憀ine box高度。當自定義單選框內(nèi)元素采用inline-block時,若vertical-align設置稍有不慎就會導致內(nèi)部元素所在的line box被撐高,從而導致自定義單選框所在的line box高度變大。因此這里采用將內(nèi)部元素的display均設置為block的做法,直接讓vertical-align失效,提高可控性。
通過opacity:0實現(xiàn)(2018/10/5追加)?上面我們通過label關(guān)聯(lián)display:none的input[type=radio]從而利用input[type=radio]簡化自定義單選框的實現(xiàn),但依然要手寫JS實現(xiàn)按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部分
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) }) })總結(jié)
?對于復選框我們可以稍加修改就可以了,然后通過VUE、React等框架稍微封裝一下提供更簡約的API,使用起來就更方便了。
?尊重原創(chuàng),轉(zhuǎn)載請注明來自:https://www.cnblogs.com/fsjoh... ^_^肥仔John
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/113963.html
摘要:真心沒法弄出圓角自從有了后,我們就可以通過制作圓角矩形圓形等圖形,甚至連也受到影響從而實現(xiàn)元素陰影也能做到圓角的效果。那么是否也能做出圓角的效果呢答案是否定的。 前言 ?在CSS魔法堂:改變單選框顏色就這么吹毛求疵!中我們要模擬原生單選框通過Tab鍵獲得焦點的效果,這里涉及到一個常常被忽略的屬性——outline,由于之前對其印象確實有些模糊,于是本文打算對其進行稍微深入的研究^_^ ...
摘要:利用用和來做表單即時校驗需求讓表單檢驗變得簡單優(yōu)雅,不需要寫冗長的代碼來校驗設置樣式豐富了表單元素,提供了類似等表單元素屬性。不知細葉誰裁出,二月春風似剪刀。首先,你需要先了解一下漸變的使用技巧。 之前不久,由于自己平時涉獵還算廣泛,總結(jié)了一篇博客:這些JavaScript編程黑科技,裝逼指南,高逼格代碼,讓你驚嘆不已,沒想到受到了大家的歡迎,有人希望能博主還能整理個 CSS 的一些黑...
摘要:利用用和來做表單即時校驗需求讓表單檢驗變得簡單優(yōu)雅,不需要寫冗長的代碼來校驗設置樣式豐富了表單元素,提供了類似等表單元素屬性。不知細葉誰裁出,二月春風似剪刀。首先,你需要先了解一下漸變的使用技巧。 之前不久,由于自己平時涉獵還算廣泛,總結(jié)了一篇博客:這些JavaScript編程黑科技,裝逼指南,高逼格代碼,讓你驚嘆不已,沒想到受到了大家的歡迎,有人希望能博主還能整理個 CSS 的一些黑...
摘要:利用用和來做表單即時校驗需求讓表單檢驗變得簡單優(yōu)雅,不需要寫冗長的代碼來校驗設置樣式豐富了表單元素,提供了類似等表單元素屬性。不知細葉誰裁出,二月春風似剪刀。首先,你需要先了解一下漸變的使用技巧。 之前不久,由于自己平時涉獵還算廣泛,總結(jié)了一篇博客:這些JavaScript編程黑科技,裝逼指南,高逼格代碼,讓你驚嘆不已,沒想到受到了大家的歡迎,有人希望能博主還能整理個 CSS 的一些黑...
閱讀 1089·2021-11-18 10:02
閱讀 1333·2021-09-23 11:22
閱讀 2654·2021-08-21 14:08
閱讀 1661·2019-08-30 15:55
閱讀 1747·2019-08-30 13:45
閱讀 3231·2019-08-29 16:52
閱讀 3117·2019-08-29 12:18
閱讀 1667·2019-08-26 13:36