adio、checkbox和switch應該是一個比較常用的html標簽,尤其是在中后臺ERP系統(tǒng)里面更為常見。不過瀏覽器自帶的樣式不怎么好看,而且不同瀏覽器效果也不一樣。出于美化和統(tǒng)一視覺效果的需求,自定義樣式就被提出來了。
實現(xiàn)思路
純css實現(xiàn)的主要手段是利用label標簽的模擬功能。label的for屬性可以關(guān)聯(lián)一個具體的input元素,即使這個input本身不可被用戶可見,有個與它對應的label后,用戶可以直接通過和label標簽交互來替代原生的input——而這給我們的樣式模擬留下了空間。簡而言之就是:
隱藏原生input,樣式定義的過程留給label (那為什么不直接改變checkbox的樣式?因為checkbox作為瀏覽器默認組件,樣式更改上并沒有l(wèi)abel那么方便,很多屬性對checkbox都是不起作用的,比如background,而label在樣式上基本和div一樣'任人宰割')
而在選擇事件上,由于css的“相鄰選擇符(E+F)”的存在,讓我們可以直接利用html的默認checkbox,免去了js模擬選擇的麻煩。
準備知識
DEMO的部分CSS3屬性只寫了webkit前綴,所以建議用webkit內(nèi)核的瀏覽器查看本頁案例,當然只要你給樣式補上對應的瀏覽器前綴,就可以實現(xiàn)更多樣式匹配
HTML代碼:
<!-- input的id必須有,這個是label進行元素匹配所必需的 --> <!-- 可以看到每個input的id和label的“for”屬性對應同一字符串 --> <input type="checkbox" id="checkbox01" /> <label for="checkbox01"></label> <input type="checkbox" id="checkbox02" /> <label for="checkbox02"></label> <input type="checkbox" id="checkbox03" /> <label for="checkbox03"></label> <input type="checkbox" id="checkbox04" /> <label for="checkbox04"></label>
HTML構(gòu)建完成,接下來是對應的css:
/* 隱藏所有checkbox */
input[type='checkbox'] {
display: none;
}
/* 對label進行模擬.背景圖片隨便拼湊的,不要吐槽品味*/
/* transition效果是做個背景切換效果,這里單純演示而已,實際上這個過渡不加更自然*/
label {
display: inline-block;
width: 60px;
height: 60px;
position: relative;
background: url(//www.chitanda.me/images/blank.png);
background-position: 0 0px;
-webkit-transition: background 0.5s linear;
}
/* 利用相鄰選擇符和checkbox`:checked`的狀態(tài)偽類來模擬默認選中效果(就是點擊后那個勾號的效果) */
/*如果這段代碼注釋,點擊后將沒有任何反饋給用戶*/
/*因為label本身是沒有點擊后被選中的狀態(tài)的,checkbox被隱藏后,這個狀態(tài)只能手動模擬*/
input[type='checkbox']:checked+label {
background-position: 0 -60px;
}
上面代碼看起來好像也可以了。不過仔細想想,貌似缺了點什么:選項對應的提示文字
對css不了解的新人可能這時候第一反應就是在label后面用p標簽或者span標簽來添加文字。不過這種方式都不怎么優(yōu)雅。個人建議用css的::before和::after偽元素(::before和:before是一個東西。不過為了把“偽元素”和“偽類”區(qū)分出來,W3C建議的寫法是偽元素用::而偽類用:)
/* 偽元素的生效很簡單,定義`content`就好,其余的屬性和普通div一樣 */
label::after {
content: attr(data-name);
/*利用attr可以減少css代碼量,data-name寫在html部分的label屬性里*/
display: inline-block;
position: relative;
width: 120px;
height: 60px;
left: 100%;
vertical-align: middle;
margin: 10px;
}
當然既然可以用::after模擬label的文字,那也就可以用::before模擬label的checkbox樣式,這里就不做解析了。
這里提一下偽類和偽元素的區(qū)分:
1)偽類:存在的意義是為了通過選擇器找到那些不存在于DOM樹中的信息以及不能被常規(guī)CSS選擇器獲取到的信息。 偽類由一個冒號:開頭,冒號后面是偽類的名稱和包含在圓括號中的可選參數(shù)。
常用的偽類:
:active 向被激活的元素添加樣式。 :focus 向擁有鍵盤輸入焦點的元素添加樣式。 :hover 當鼠標懸浮在元素上方時,向元素添加樣式。 :link 向未被訪問的鏈接添加樣式。 :visited 向已被訪問的鏈接添加樣式。 :first-child 向元素的第一個子元素添加樣式。 :checked 向選中的控件元素添加樣式
2)偽元素:偽元素在DOM樹中創(chuàng)建了一些抽象元素,這些抽象元素是不存在于文檔語言里的(可以理解為html源碼);
注意: css3為了區(qū)分偽類和偽元素,規(guī)定偽類前面有一個冒號,偽元素前面有兩個冒號
常用偽元素:
關(guān)于偽元素的講解,可以參考CSS偽類與偽元素總是傻傻分不清,這份總結(jié)夠面試用了
::before 為作用元素的第一個子節(jié)點插入dom中 ::after 為作用元素的最后一個子節(jié)點插入dom中
- 同:都是通過選擇器為元素添加樣式
- 異:偽元素會創(chuàng)建一個元素,但不是真正的Html元素,偽類相當于為一個元素創(chuàng)建一個class樣式
實例
自定義radio
html代碼:
<input type="radio" id="radio"> <label for="radio"></label>
css代碼:
input{
display:none;
}
label {
display: inline-block;
width: 30px;
height: 30px;
border: 1px solid #333;
border-radius: 50%;
position: relative;
}
label::after {
-webkit-transition: all .5s ease;
-moz-transition: all .5s ease;
-o-transition: all .5s ease;
-ms-transition: all .5s ease;
transition: all .5s ease;
cursor: pointer;
position: absolute;
width: 16px;
height: 16px;
border-radius: 50%;
top: 50%;
left: 50%;
margin-top:-8px;
margin-left:-8px;
z-index: 1;
content: '';
border:1px solid #333;
}
input:checked+label::after{
background:red;
}
實現(xiàn)效果:
點擊前和點擊后:
自定義checkbox
漂亮的checkbox長這樣的,看著就很可愛
我們可以不追求那么完美的樣式,可以實現(xiàn)下面簡單好看的樣式就可以
html代碼:
<input type="checkbox" id="checkbox"> <label for="checkbox"></label>
css代碼:
input{
display:none;
}
label {
display: inline-block;
width: 30px;
height: 30px;
border: 1px solid #333;
position: relative;
}
label::after {
-webkit-transition: opacity .5s ease;
-moz-transition: opacity .5s ease;
-o-transition: opacity .5s ease;
-ms-transition: opacity .5s ease;
transition: opacity .5s ease;
cursor: pointer;
position: absolute;
content: '';
opacity: 0;
}
input:checked+label::after{
border: 2px solid #d73d32;
border-top: none;
border-right: none;
-webkit-transform: rotate(-45deg);
-ms-transform: rotate(-45deg);
transform: rotate(-45deg);
width:20px;
height:10px;
top:50%;
margin-top:-8px;
left:50%;
margin-left:-10px;
opacity: 1.0;
}
實現(xiàn)效果:
點擊前和點擊后:
自定義switch
繼續(xù)分享一個IOS風格的switch開關(guān)按鈕,樣子也非常常見,如圖:
主要是使用了<input ?type="checkbox">來模擬實現(xiàn),具體的HTML:
html 代碼:
<label><input class="mui-switch" type="checkbox"> 默認未選中</label> <label><input class="mui-switch" type="checkbox" checked> 默認選中</label> <label><input class="mui-switch mui-switch-animbg" type="checkbox"> 默認未選中,簡單的背景過渡效果,加mui-switch-animbg類即可</label> <label><input class="mui-switch mui-switch-animbg" type="checkbox" checked> 默認選中</label> <label><input class="mui-switch mui-switch-anim" type="checkbox"> 默認未選中,過渡效果,加 mui-switch-anim 類即可</label> <label><input class="mui-switch mui-switch-anim" type="checkbox" checked> 默認選中</label>
在實際的使用中后來又增加了兩個過渡效果,分別加?mui-switch-animbg和mui-switch-anim?類即可,具體效果查看下面的demo頁面。
CSS代碼(SCSS導出的,排版有些奇怪):
css 代碼:
剩下部分
這里給出具體的css,方便大家復制本地實現(xiàn)
<style>
.mui-switch {
width: 52px;
height: 31px;
position: relative;
border: 1px solid #dfdfdf;
background-color: #fdfdfd;
box-shadow: #dfdfdf 0 0 0 0 inset;
border-radius: 20px;
border-top-left-radius: 20px;
border-top-right-radius: 20px;
border-bottom-left-radius: 20px;
border-bottom-right-radius: 20px;
background-clip: content-box;
display: inline-block;
-webkit-Appearance: none;
user-select: none;
outline: none;
}
.mui-switch:before {
content: '';
width: 29px;
height: 29px;
position: absolute;
top: 0px;
left: 0;
border-radius: 20px;
border-top-left-radius: 20px;
border-top-right-radius: 20px;
border-bottom-left-radius: 20px;
border-bottom-right-radius: 20px;
background-color: #fff;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.4);
}
.mui-switch:checked {
border-color: #64bd63;
box-shadow: #64bd63 0 0 0 16px inset;
background-color: #64bd63;
}
.mui-switch:checked:before {
left: 21px;
}
.mui-switch.mui-switch-animbg {
transition: background-color ease 0.4s;
}
.mui-switch.mui-switch-animbg:before {
transition: left 0.3s;
}
.mui-switch.mui-switch-animbg:checked {
box-shadow: #dfdfdf 0 0 0 0 inset;
background-color: #64bd63;
transition: border-color 0.4s, background-color ease 0.4s;
}
.mui-switch.mui-switch-animbg:checked:before {
transition: left 0.3s;
}
.mui-switch.mui-switch-anim {
transition: border cubic-bezier(0, 0, 0, 1) 0.4s, box-shadow cubic-bezier(0, 0, 0, 1) 0.4s;
}
.mui-switch.mui-switch-anim:before {
transition: left 0.3s;
}
.mui-switch.mui-switch-anim:checked {
box-shadow: #64bd63 0 0 0 16px inset;
background-color: #64bd63;
transition: border ease 0.4s, box-shadow ease 0.4s, background-color ease 1.2s;
}
.mui-switch.mui-switch-anim:checked:before {
transition: left 0.3s;
}
/*# sourceMappingURL=mui-switch.css.map */
</style>
如果你喜歡scss,那么代碼更加簡潔
@mixin borderRadius($radius:20px) {
border-radius: $radius;
border-top-left-radius: $radius;
border-top-right-radius: $radius;
border-bottom-left-radius: $radius;
border-bottom-right-radius: $radius;
}
$duration: .4s;
$checkedColor: #64bd63;
.mui-switch {
width: 52px;
height: 31px;
position: relative;
border: 1px solid #dfdfdf;
background-color: #fdfdfd;
box-shadow: #dfdfdf 0 0 0 0 inset;
@include borderRadius();
background-clip: content-box;
display: inline-block;
-webkit-appearance: none;
user-select: none;
outline: none;
&:before {
content: '';
width: 29px;
height: 29px;
position: absolute;
top: 0px;
left: 0;
@include borderRadius();
background-color: #fff;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.4);
}
&:checked {
border-color: $checkedColor;
box-shadow: $checkedColor 0 0 0 16px inset;
background-color: $checkedColor;
&:before {
left: 21px;
}
}
&.mui-switch-animbg {
transition: background-color ease $duration;
&:before {
transition: left 0.3s;
}
&:checked {
box-shadow: #dfdfdf 0 0 0 0 inset;
background-color: $checkedColor;
transition: border-color $duration, background-color ease $duration;
&:before {
transition: left 0.3s;
}
}
}
&.mui-switch-anim {
transition: border cubic-bezier(0, 0, 0, 1) $duration, box-shadow cubic-bezier(0, 0, 0, 1) $duration;
&:before {
transition: left 0.3s;
}
&:checked {
box-shadow: $checkedColor 0 0 0 16px inset;
background-color: $checkedColor;
transition: border ease $duration, box-shadow ease $duration, background-color ease $duration*3;
&:before {
transition: left 0.3s;
}
}
}
}
鏈接文章
https://www.html.cn/archives/9274
https://segmentfault.com/a/1190000003711140






