複選框樣式化綜合





<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Checkbox��ʽ</title>
<style type="text/css" media="screen">
body{color:#444;font-size:1.6em;background:#ccc;}
.container{width:90%;margin:20px 3%;padding:25px;min-height:400px;height:auto;background: #FFF;}
section{float:left;width:30%;margin:20px 20px;}
hr{ clear:both;}
/*** Start by hiding the checkboxes */
input[type=checkbox] {visibility: hidden;}
/** * Create the slider bar */
.checkboxOne { width: 40px;height: 10px;background: #555;margin: 20px 80px;position: relative;border-radius: 3px;}
/** * Create the slider from the label */
.checkboxOne label {display: block;width: 16px;height: 16px;border-radius: 50%;-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;top: -3px;left: -3px;background: #ccc;}
/** * Move the slider in the correct position if the checkbox is clicked*/
.checkboxOne input[type=checkbox]:checked + label {left: 27px;}
/** * Checkbox Two */
.checkboxTwo {width: 120px;height: 40px;background: #333;margin: 20px 60px;border-radius: 50px;position: relative;}
/** * Create the line for the circle to move across */
.checkboxTwo:before {content: '';position: absolute;top: 19px;left: 14px;height: 2px;width: 90px;background: #111;}
/** * Create the circle to click */
.checkboxTwo label {display: block;width: 22px;height: 22px;border-radius: 50%;-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;top: 9px;z-index: 1;left: 12px;background: #ddd;}
/* * Create the click event for the checkbox*/
.checkboxTwo input[type=checkbox]:checked + label {left: 84px;background: #26ca28;}
/** * Checkbox Three */
.checkboxThree {width: 120px;height: 40px;background: #333;margin: 20px 60px;border-radius: 50px;position: relative;}
/** * Create the text for the On position */
.checkboxThree:before {content: 'On';position: absolute;top: 12px;left: 13px;height: 2px;color: #26ca28;font-size: 16px;}
/** * Create the label for the off position */
.checkboxThree:after { content: 'Off';position: absolute;top: 12px;left: 84px;height: 2px;color: #ddd;font-size: 16px;}
/** * Create the pill to click */
.checkboxThree label {display: block;width: 52px;height: 22px;border-radius: 50px;-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;top: 9px;z-index: 1;left: 12px;background: #ddd;}
/** * Create the checkbox event for the label * @type {[type]} */
.checkboxThree input[type=checkbox]:checked + label { left: 60px;background: #26ca28;}
/** * Checkbox Four */
.checkboxFour {width: 40px;height: 40px;background: #ddd;margin: 20px 90px; border-radius: 100%;position: relative;-webkit-box-shadow: 0px 1px 3px rgba(0,0,0,0.5);-moz-box-shadow: 0px 1px 3px rgba(0,0,0,0.5);box-shadow: 0px 1px 3px rgba(0,0,0,0.5);}
/** * Create the checkbox button */
.checkboxFour label {display: block;width: 30px;height: 30px;border-radius: 100px;-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;top: 5px;left: 5px;z-index: 1;background: #333;-webkit-box-shadow:inset 0px 1px 3px rgba(0,0,0,0.5);-moz-box-shadow:inset 0px 1px 3px rgba(0,0,0,0.5);box-shadow:inset 0px 1px 3px rgba(0,0,0,0.5);}
/** * Create the checked state */
.checkboxFour input[type=checkbox]:checked + label {background: #26ca28;}
/** * Checkbox Five */
.checkboxFive {width: 25px;margin: 20px 100px;position: relative;}
/** * Create the box for the checkbox */
.checkboxFive label { cursor: pointer;position: absolute;width: 25px;height: 25px;top: 0;left: 0;background: #eee;border:1px solid #ddd;}
/** * Display the tick inside the checkbox */
.checkboxFive label:after {opacity: 0.2;content: '';position: absolute;width: 9px;height: 5px;background: transparent;top: 6px;left: 7px;border: 3px solid #333;border-top: none;border-right: none;-webkit-transform: rotate(-45deg); -moz-transform: rotate(-45deg); -o-transform: rotate(-45deg); -ms-transform: rotate(-45deg); transform: rotate(-45deg);}
/** * Create the hover event of the tick */
.checkboxFive label:hover::after {opacity: 0.5;}
/** * Create the checkbox state for the tick */
.checkboxFive input[type=checkbox]:checked + label:after {opacity: 1;}
</style>
</head>
<body>
<section class="container">
<section>
  <div class="checkboxOne">
  <input type="checkbox" value="1" id="checkboxOneInput" name="" />
  <label for="checkboxOneInput"></label>
  </div>
</section>
<section>
  <div class="checkboxTwo">
  <input type="checkbox" value="1" id="checkboxTwoInput" name="" />
  <label for="checkboxTwoInput"></label>
  </div>
</section>
<section>
  <div class="checkboxThree">
  <input type="checkbox" value="1" id="checkboxThreeInput" name="" />
  <label for="checkboxThreeInput"></label>
  </div>
</section>
<section>
  <div class="checkboxFour">
  <input type="checkbox" value="1" id="checkboxFourInput" name="" />
  <label for="checkboxFourInput"></label>
  </div>
</section>
<section>
  <div class="checkboxFive">
  <input type="checkbox" value="1" id="checkboxFiveInput" name="" />
  <label for="checkboxFiveInput"></label>
  </div>
</section>
    <div style="clear:both;"></div>
</section>
</body>
</html>

複選框 Checkbox 是 Web 應用常用控件,隨處可見,原生的複選框控件一般就像下面這樣:

 選中狀態  未選狀態

這取決於操作系統和瀏覽器,有些時候,這種樣子並不能滿足設計要求,這時需要更爲精緻的複選框樣式。以往只有少數瀏覽器才支持對這類控件應用樣式,比如拿到這樣一張設計圖:

在過去,想要通過簡單地修改樣式達成這種設計效果根本不行,不過,現在藉助強大的 CSS3 屬性 appearance 可以對該類控件有空前的樣式控制能力:

input[type="checkbox"] {
  -webkit-appearance: none;
}

這樣設置該屬性值爲 none 就去掉了複選框原有的呈現方式,變成了一個普普通通的元素,然後就可以爲之應用樣式了,添加如下樣式:


input[type="checkbox"] {
  -webkit-appearance: none;
  background: #fff url(i/blue.png);
  height: 22px;
  vertical-align: middle;
  width: 22px;
}

通過結合使用狀態僞類選擇器 :checked 可以爲選中狀態下的 checkbox 設置不同的樣式,用以從視覺上區別:

input[type="checkbox"]:checked {
  background-position: -48px 0;
}

此時點擊複選框,可以看到複選框樣式的變化效果,另外,根據那張設計圖片所示還得加上獲取焦點,禁用等狀態的樣式:

input[type="checkbox"]:focus,
input[type="checkbox"]:hover {
  background-position: -24px 0;
  outline: none;
}

input[type="checkbox"]:checked {
  background-position: -48px 0;
}

input[type="checkbox"][disabled] {
  background-position: -72px 0;
}

input[type="checkbox"][disabled]:checked {
  background-position: -96px 0;
}

因爲圖片已經事先合併成一張了,簡單修改一下 background-position 就可以了,同時前面幾個選擇器的優先級(權重)一樣,所以書寫順序很重要。

兼容性

目前只兼容 Webkit 系列瀏覽器;雖然 Firefox 也實現了替代的 -moz-appearance 屬性,不過控件原有的背景顏色、邊框樣式無法修改,暫時也不大好用;IE 系列暫時不支持該屬性,更詳細的兼容情況查看 Caniuse/appearance。因此需要爲 IE 瀏覽器清除掉背景圖片的影響:


input[type="checkbox"] {
  background: #fff url(i/blue.png);
  background: none\0;
  *background: none;
  ...
}

爲了兼容更多的主流瀏覽器,需要尋求另外的解決方案,在所有主流瀏覽器裏,點擊關聯某個複選框的 label 時,產生的效果和點擊元素自身相同,會切換複選框控件的選中狀態。瀏覽器的這種行爲給了我們一個至關重要的掛鉤,既然能依靠 label 元素來控制原生複選框的狀態,那麼就可以不必直接操作實際的複選框元素,而把操作和樣式都轉移到與之關聯的 label 元素上去:

<input id="example" type="checkbox">
<label for="example"></label>

確保 label 元素的 for 屬性的值和複選框 input 的 id 值一致,同時將 label 元素放置於 input 之後,這樣 CSS 可以通過相鄰兄弟選擇器(Adjacent sibling selector)定位到這個 label 元素併爲之應用樣式:


input[type="checkbox"] + label:before {
  background: #fff url(i/blue.png);
  content: " ";
  height: 22px;
  left: 0;
  position: absolute;
  width: 22px;
}

有了樣式化的 label 元素來提供交互,原生的 checkbox 控件就顯得有點多餘了,雖然可以用 display: none 把它隱藏掉,不過隱藏後的表單元素是不能獲得焦點的,所以最好的方式還是用 label 元素把它遮住,這樣既能支持鍵盤交互,同時當圖片加載失敗的時候,又能保證原生的控件可用:


input[type="checkbox"] {
  box-sizing: border-box;
  left: 4px;
  margin: 0;
  padding: 0;
  position: absolute;
  top: 3px;
}

圖片要足夠大能將原生的 checkbox 控件完全遮擋住,因爲這裏用到了絕對定位,所以需要增加一個定位參照:


<!-- HTML -->
<div class="checkbox">
  <input id="exampleCheckbox" type="checkbox">
  <label for="exampleCheckbox"></label>
</div>

/* CSS */
.checkbox {
  min-height: 24px;
  padding-left: 24px;
  position: relative;
}

左邊預留內邊距是爲了排版更美觀,同時,和之前一樣,搭配上其它狀態下的樣式:


input[type="checkbox"]:focus + label:before,
input[type="checkbox"] + label:hover:before {
  background-position: -24px 0;
}

input[type="checkbox"]:checked + label:before {
  background-position: -48px 0;
}

input[type="checkbox"][disabled] + label:before {
  background-position: -72px 0;
}

input[type="checkbox"][disabled]:checked + label:before {
  background-position: -96px 0;
}

兼容性

只要支持 CSS3 selectors 的瀏覽器基本上都能兼容,同時具備原生控件的絕大多數交互特性。IE 8 不支持 :checked 僞類選擇器,將僞元素:before 修改爲雙冒號 ::before 可以去掉對 IE 8 的影響:

input[type="checkbox"] + label::before { ... }

關於僞元素生成內容的兼容性見 CSS Generated content for pseudo-elements。誠然,上面的方法假設了支持 :checked 僞類選擇器的瀏覽器同時也支持雙冒號僞元素寫法,而不支持的瀏覽器則都不支持,這是一種不太好的方式,這種假設事實上也是不正確的,造成了部分老舊瀏覽器不可用的問題,如果使用 :not() 選擇器則更爲合理,使用 :not(:checked) 來爲未選中的控件添加樣式,:not() 和 :checked 同屬一個規範css3-selectors,兼容性應該一致 CSS3 selectors。不過寫法有點變化,:checked 和 :not(:checked) 都需要添加上基本的樣式:


input[type="checkbox"]:checked + label:before,
input[type="checkbox"]:not(:checked) + label:before {
  background: #fff url(i/blue.png);
  content: " ";
  height: 22px;
  left: 0;
  position: absolute;
  width: 22px;
}

input[type="checkbox"]:not(:checked):focus + label:before,
input[type="checkbox"]:not(:checked) + label:hover:before {
  background-position: -24px 0;
}

input[type="checkbox"]:checked + label:before {
  background-position: -48px 0;
}

input[type="checkbox"][disabled]:not(:checked) + label:before {
  background-position: -72px 0;
}

input[type="checkbox"][disabled]:checked + label:before {
  background-position: -96px 0;
}

查看簡單示例,對於那些並不支持 :checked 僞類選擇器的瀏覽器(比如 IE 8),則可以藉助 javaScript 來根據控件狀態修改真正的 class 屬性達到區分不同狀態的目的,比如根據是否被選中來添加或刪除一個 checked 的 class:


// jQuery
$('input[type="checkbox"]').on('change', function() {
  $(this)[$(this).prop('checked') ? 'addClass' : 'removeClass']('checked');
});

/* CSS */
input[type="checkbox"].checked + label:before { ... }

有了前面的基礎,要製作類似於開關按鈕的控件也是非常簡單的了,還是熟悉的結構:

<div class="checkbox">
  <input id="example" type="checkbox">
  <label for="example">Check</label>
</div>

首先勾勒出開關的形狀,一個圓角矩形中間放一個圓形按鈕:


input[type="checkbox"]:checked + label,
input[type="checkbox"]:not(:checked) + label {
  background-color: #e0e0e0;
  border-radius: 24px;
  cursor: pointer;
  display: inline-block;
  height: 24px;
  position: relative;
  text-indent: -9999px;
  width: 48px;
}

input[type="checkbox"]:checked + label:after,
input[type="checkbox"]:not(:checked) + label:after {
  background-color: #fff;
  border-radius: 20px;
  content: " ";
  height: 20px;
  left: 2px;
  position: absolute;
  top: 2px;
  width: 20px;
}

選中的效果只要簡單修改下外框的背景色和中間按鈕的位置就行:


input[type="checkbox"]:checked + label {
  background-color: #8c8;
}

input[type="checkbox"]:checked + label:after {
  left: 26px;
}

不過這種跳躍式變化實在是太生硬了,添加點過渡效果,看上去更平滑:


input[type="checkbox"]:checked + label,
input[type="checkbox"]:not(:checked) + label {
  -webkit-transition: background-color 0.3s;
          transition: background-color 0.3s;
}

input[type="checkbox"]:checked + label:after,
input[type="checkbox"]:not(:checked) + label:after {
  -webkit-transition: left 0.3s;
          transition: left 0.3s;
}

點擊就能看到效果,對於中間的按鈕部分使用 CSS3 Transforms 來替代 left 效果更好,速度更快:


input[type="checkbox"]:checked + label:after,
input[type="checkbox"]:not(:checked) + label:after {
  -webkit-transition: left -webkit-transform 0.3s;
       -o-transition:           -o-transform 0.3s;
          transition: left         transform 0.3s;
}

input[type="checkbox"]:checked + label:after {
  left: 26px;
  -webkit-transform: translateX(24px);
      -ms-transform: translateX(24px);
       -o-transform: translateX(24px);
          transform: translateX(24px);
}

不支持 CSS3 Transforms 的瀏覽器仍然可以看到背景色的變化,不影響可用性,詳見 CSS3 Transforms。關於性能問題,請參考 High Performance Animations。快速點擊“控件”會因選中效果造成不能切換狀態的情況,所以去掉“控件”可以被選中的能力:

input[type="checkbox"]:checked + label,
input[type="checkbox"]:not(:checked) + label {
  (-prefix-)user-select: none;
}

這裏的瀏覽器廠商前綴根據需要替換成相應的,查看簡單示例。當然還需要提供聚焦以及禁用等狀態的樣式,就不在這裏重複了。以上所有技術可同時適用於單選框(radio)。

發佈了25 篇原創文章 · 獲贊 29 · 訪問量 20萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章