最近我在 SF 開直播分享,針對這個話題作了更全面的講解,感興趣的同窗推薦觀看:css
寫 CSS 也要開腦洞:萬能的 :checked + label
html
在咱們的後臺中,須要設置廣告精準投放的區域,也就是要在全國31個省、自治區、直轄市中選擇。那麼,出現下面這幅景象也就理所應當了:segmentfault
這樣作有幾個問題:瀏覽器
選項不少,沒有規律,找起來很累佈局
若是是一個已經選擇了部分選項的廣告,修改時仍然須要用肉眼尋找,沒法一眼看出來投放到哪些省份學習
選完一個,再選下一個,還要從頭找,甚至會被已經選過的影響測試
因而我想,首先應該把全部選項分爲「已選中」和「未選中」兩批,解決第2個問題,減輕第3個問題;其次複選框自己的價值不大,能夠被替換爲其它樣式;惟一可能引入的問題,就是點選時,用戶的預期是看到複選框裏出現一個小對勾,表示選中,若是我把它移開放到「已選中」組裏,用戶可能會迷惑,須要一些時間學習。flex
因而我跟某產品經理朋友聊了聊這個想法,他表示確實可能形成用戶迷惑,不過若是能加入動畫效果,那麼基本沒問題。嗯,開始動手。動畫
近日flexbox規範定案,各瀏覽器相繼支持display:flex;
,同時傳來一條好消息,新實現比老實現display:box;
快不少。此次我打算用flexbox來解決問題,由於裏面有一個很重要的屬性:order
(以前叫box-ordinal-group
),它能夠改變佈局中元素的排列順序,配合CSS3新增的選擇器,應該能夠知足須要。網站
(關於flexbox的知識,能夠經過Google瞭解,雖然搜到的可能是上一個版本,不過和最終版差異不大,只是叫法不一樣。本文再也不過多講解,我就當你們都會了)
<input type="checkbox">
自己的樣式不能修改,因此咱們必須藉助<label>
的幫助;實現選中/未選中區分,那天然就要用到僞類:checked
;選擇器必定是從外到內、從前到後的,無法選擇父級元素,因此不能用<label>
去包<input>
,那麼最終佈局就只能是:
<div> <input type="checkbox" name="q[]" id="q1" /> <label for="q1">小寶3225</label> <input type="checkbox" name="q[]" id="q2" /> <label for="q2">王老白白白</label> <input type="checkbox" name="q[]" id="q3" /> <label for="q3">空夫31</label> <input type="checkbox" name="q[]" id="q4" /> <label for="q4">谷大白話</label> <input type="checkbox" name="q[]" id="q5" /> <label for="q5">Meathill</label> <input type="checkbox" name="q[]" id="q6" /> <label for="q6">愛財如命大師</label> </div>
很簡單哈,不解釋了。CSS3新增了「下一節點」選擇器 +,用來選擇某節點的下一個節點,結合:checked
僞類就能夠將選中的<input>
和它臨近的<label>
經過改變order
屬性移到前面去:
#container { display:flex; flex-direction:row; flex-wrap:wrap; } #container input, #container label { order: 2; //全部選項、label順序爲2 } input[type=checkbox]:checked, input[type=checkbox]:checked + label { order: 0; // 越小越靠前 }
不過這樣只是把選中的內容提早,視覺上沒有真正的分割。因此我決定再加入一根分割線,上面是選中的,下面是未選的。這個時候咱們須要用到 ~
這個選擇器,選擇某節點後面的節點:
hr { display:none; // 默認狀況下,沒選任何選項,分割線隱藏 order: 1; // 分割線順序爲1 width:100%; // 保證獨霸一行 } input[type=checkbox]:checked ~ hr { display:block; // 有選項被選中後纔會顯示分割線 }
http://jsfiddle.net/meathill/...
這樣基礎功能實現了。不過視覺上,排版仍然不整齊,選中的選項和未選中的選項區分不算太明顯,因此下一步我準備美化下checkbox。
作法與前面相似,也要用到CSS3新增的選擇器。前面爲了實現<label>
提早,沒有用它包裹<input>
,因此在選項不少很長致使換行的時候,可能出現複選框和標籤脫離的尷尬情況。好在複選框的價值能夠用別的樣式取代,因此先把小方框隱藏起來,轉而將<label>
做爲操做目標,再來點邊框底色圓角(參考自Bootstrap 3),就能夠了:
input[type=checkbox] { display: none; } label { min-width: 120px; border: 1px solid #CCC; padding: 2px 8px; text-align: center; margin: 0 5px 5px 0; background: #FFF; color: #333; border-radius: 3px; box-sizing: border-box; } label:hover { border-color: #ADADAD; background: #EBEBEB; cursor: pointer; } input[type=checkbox]:checked + label { order: 0; background-color: #5cb85c; border-color: #4cae4c; color: #FFF; } input[type=checkbox]:checked + label:hover { background-color: #47a447; border-color: #398439; }
這樣看起來還有上升空間,若是加上幾個圖標響應用戶操做,那麼學習成本會更低,對操做後的預期也會更準確。因而引用CDN上的font-awesome,使用:before
僞類加上小圖標,就獲得了最終效果。
http://jsfiddle.net/meathill/...
我無心中發現,這樣批量添加刪除時,鼠標能夠常點不動,應該也是個意外的收穫吧。
至此功能基本作好了,不過因爲修改了行爲,可能致使用戶迷惑,因此準備加個動畫幫助用戶理解這個交互。
惋惜做爲一個新功能,瀏覽器的支持尚不完善,雖然規範中規定「animatable: yes」,可是實測在Chrome v.30下也沒法工做:
http://jsfiddle.net/meathill/...
看來只有等新版瀏覽器發佈後再去完善了。
使用純CSS作組件,幾乎不用擔憂兼容性問題,由於瀏覽器自己就作了很好的向下兼容,代碼最多不生效,通常不會錯。
具體到這個組件,由於只針對視覺效果,沒有增刪改任何瀏覽器行爲,因此兼容性也沒有任何問題。不過最終效果呢,只有支持flexbox和CSS3選擇符的瀏覽器才能正常渲染。
個人環境是Window 8 + Chrome v.30,以及小米2 + Chrome v.30,測試經過。
現在CSS很強,純CSS能夠實現不少功能,但願從此能作出更多有價值的東西。分享這個組件的實現,但願對你們有用。
首發個人我的網站:[[教程]純CSS實現多選組件](http://blog.meathill.com/tech...