DIV CSS 佈局教程網

 DIV+CSS佈局教程網 >> 網頁腳本 >> CSS入門知識 >> CSS詳解 >> 使用CSS實現頁面復選框的方法
使用CSS實現頁面復選框的方法
編輯:CSS詳解     
這篇文章主要介紹了使用CSS實現頁面復選框的方法,純CSS實現,絕不添加任何JS :P 需要的朋友可以參考下

產品篇

在我們的後台中,需要設置廣告精准投放的區域,也就是要在全國31個省、自治區、直轄市中選擇。那麼,出現下面這幅景象也就理所應當了:
2015721171247784.jpg (584×99)

這樣做有幾個問題:

選項很多,沒有規律,找起來很累
如果是一個已經選擇了部分選項的廣告,修改時仍然需要用肉眼尋找,無法一眼看出來投放到哪些省份
選完一個,再選下一個,還要從頭找,甚至會被已經選過的影響

於是我想,首先應該把所有選項分為“已選中”和“未選中”兩批,解決第2個問題,減輕第3個問題;其次復選框本身的價值不大,可以被替換為其它樣式;唯一可能引入的問題,就是點選時,用戶的預期是看到復選框裡出現一個小對勾,表示選中,如果我把它移開放到“已選中”組裡,用戶可能會迷惑,需要一些時間學習。

於是我跟某產品經理朋友聊了聊這個想法,他表示確實可能造成用戶迷惑,不過如果能加入動畫效果,那麼基本沒問題。嗯,開始動手。
技術實現篇

近日flexbox規范定案,各浏覽器相繼支持display:flex;,同時傳來一條好消息,新實現比老實現display:box;快很多。這次我打算用flexbox來解決問題,因為裡面有一個很重要的屬性:order(之前叫box-ordinal-group),它可以改變布局中元素的排列順序,配合CSS3新增的選擇器,應該可以滿足需要。
第一步 分拆選中/未選中

(關於flexbox的知識,可以通過Google了解,雖然搜到的多是上一個版本,不過和最終版差別不大,只是叫法不同。本文不再過多講解,我就當大家都會了)

<input type="checkbox">本身的樣式不能修改,所以我們必須借助的幫助;實現選中/未選中區分,那自然就要用到偽類:checked;選擇器一定是從外到內、從前到後的,沒法選擇父級元素,所以不能用<label>去包<input>,那麼最終布局就只能是:

CSS Code復制內容到剪貼板
  1. <div>
  2. <input type="checkbox" name="q[]" id="q1" />
  3. <label for="q1">小寶3225</label>
  4. <input type="checkbox" name="q[]" id="q2" />
  5. <label for="q2">王老白白白</label>
  6. <input type="checkbox" name="q[]" id="q3" />
  7. <label for="q3">空夫31</label>
  8. <input type="checkbox" name="q[]" id="q4" />
  9. <label for="q4">谷大白話</label>
  10. <input type="checkbox" name="q[]" id="q5" />
  11. <label for="q5">Meathill</label>
  12. <input type="checkbox" name="q[]" id="q6" />
  13. <label for="q6">一毛不拔大師</label>
  14. </div>

很簡單哈,不解釋了。CSS3新增了“下一節點”選擇器 +,用來選擇某節點的下一個節點,結合:checked偽類就可以將選中的<input>和它臨近的<label>通過改變order屬性移到前面去:

CSS Code復制內容到剪貼板
  1. #container {
  2. display:flex;
  3. flex-direction:row;
  4. flex-wrap:wrap;
  5. }
  6. #container input,
  7. #container label {
  8. order: 2; //所有選項、label順序為2
  9. }
  10. input[type=checkbox]:checked,
  11. input[type=checkbox]:checked + label {
  12. order: 0; // 越小越靠前
  13. }

不過這樣只是把選中的內容提前,視覺上沒有真正的分割。所以我決定再加入一根分割線,上面是選中的,下面是未選的。這個時候我們需要用到 ~ 這個選擇器,選擇某節點後面的節點:

CSS Code復制內容到剪貼板
  1. hr {
  2. display:none; // 默認情況下,沒選任何選項,分割線隱藏
  3. order: 1; // 分割線順序為1
  4. width:100%; // 保證獨霸一行
  5. }
  6. input[type=checkbox]:checked ~ hr {
  7. display:block; // 有選項被選中後才會顯示分割線
  8. }

http://JSfiddle.Net/meathill/fPN3p/5/embedded/result/

這樣基礎功能實現了。不過視覺上,排版仍然不整齊,選中的選項和未選中的選項區分不算太明顯,所以下一步我准備美化下checkbox。
第二步,美化CHECKBOX

做法與前面類似,也要用到CSS3新增的選擇器。前面為了實現<label>提前,沒有用它包裹<input>,所以在選項很多很長導致換行的時候,可能出現復選框和標簽脫離的尴尬狀況。好在復選框的價值可以用別的樣式取代,所以先把小方框隱藏起來,轉而將<label>作為操作目標,再來點邊框底色圓角(參考自Bootstrap 3),就可以了:

CSS Code復制內容到剪貼板
  1. input[type=checkbox] {
  2. display: none;
  3. }
  4. label {
  5. min-width: 120px;
  6. border: 1px solid #CCC;
  7. padding: 2px 8px;
  8. text-align: center;
  9. margin: 0 5px 5px 0;
  10. background: #FFF;
  11. color: #333;
  12. border-radius: 3px;
  13. box-sizing: border-box;
  14. }
  15. label:hover {
  16. border-color: #ADADAD;
  17. background: #EBEBEB;
  18. cursor: pointer;
  19. }
  20. input[type=checkbox]:checked + label {
  21. order: 0;
  22. background-color: #5cb85c;
  23. border-color: #4cae4c;
  24. color: #FFF;
  25. }
  26. input[type=checkbox]:checked + label:hover {
  27. background-color: #47a447;
  28. border-color: #398439;
  29. }

這樣看起來還有上升空間,如果加上幾個圖標響應用戶操作,那麼學習成本會更低,對操作後的預期也會更准確。於是引用CDN上的font-awesome,使用:before偽類加上小圖標,就得到了最終效果

http://JSfiddle.Net/meathill/fPN3p/4/embedded/result/

我無意中發現,這樣批量添加刪除時,鼠標可以常點不動,應該也是個意外的收獲吧。
第三步,加入動畫教育用戶(失敗)

至此功能基本做好了,不過由於修改了行為,可能導致用戶迷惑,所以准備加個動畫幫助用戶理解這個交互。

可惜作為一個新功能,浏覽器的支持尚不完善,雖然規范中規定“animatable: yes”,但是實測在Chrome v.30下也無法工作:

http://JSfiddle.Net/meathill/Ka66W/1/

看來只有等新版浏覽器發布後再去完善了。
兼容性

使用純CSS做組件,幾乎不用擔心兼容性問題,因為浏覽器本身就做了很好的向下兼容,代碼最多不生效,一般不會錯。

具體到這個組件,因為只針對視覺效果,沒有增刪改任何浏覽器行為,所以兼容性也沒有任何問題。不過最終效果呢,只有支持flexbox和CSS3選擇符的浏覽器才能正常渲染。

我的環境是Window 8 + Chrome v.30,以及小米2 + Chrome v.30,測試通過。
後記

如今CSS很強,純CSS可以實現很多功能,希望今後能做出更多有價值的東西。分享這個組件的實現,希望對大家有用。

XML學習教程| jQuery入門知識| AJAX入門| Dreamweaver教程| Fireworks入門知識| SEO技巧| SEO優化集錦|
Copyright © DIV+CSS佈局教程網 All Rights Reserved