最近做的一個項目涉及到評分和展示分數的模塊,UI設計師也給了幾個切好的圖片,實現五角星評分方式很多,本質愛折騰的精神和對性能追求以及便於維護的考慮,搜集和嘗試了很多方式,最終采用了純css驅動的實現方式完成評分和展示分數的功能,沒有js,也就意味着沒判斷邏輯,代碼出錯的幾率更少,也更便於維護,在此,把這個功能的實現的過程記錄和分享一下,一起學習交流。
原文收錄在我的 GitHub博客 (https://github.com/jawil/blog) ,喜歡的可以關注最新動態,大家一起多交流學習,共同進步。
五角星的實現
1.圖片或者字體圖標
不極致追求性能的話,直接利用設計師給的png或者jpg啥的,或者直接轉成base64.

2:利用Fontawesome 圖標庫,其實只是一種矢量字體。
HTML:
<div class="icon"></div>
CSS:
@import url(http://netdna.bootstrapcdn.com/font-awesome/3.2.1/css/font-awesome.css); .icon:before { content: '\f005'; font-family: FontAwesome; }
3.利用css3描繪拼湊一個五角星。
基本原理:利用transparent的透明不可見和transform轉換拼接一個正五角星。
HTML:
<div class="star-five"></div>
CSS:
.star-five{ width: 0; height: 0; color: red; margin: 50px 0; position: relative; display: block; border-left: 100px solid transparent; border-right: 100px solid transparent; border-bottom: 70px solid red; transform:rotate(35deg); } .star-five:before{ width: 0; height: 0; border-left: 30px solid transparent; border-right: 30px solid transparent; border-bottom: 80px solid red; position: absolute; top: -45px; left: -65px; color: white; display: block; content: ""; transform:rotate(-35deg); } .star-five:after{ width: 0; height: 0; display: block; position: absolute; color: red; top: 3px; left: -105px; border-left: 100px solid transparent; border-right: 100px solid transparent; border-bottom: 70px solid red; content: ""; transform:rotate(-70deg); }
不建議使用這種,因為選擇之后改變顏色狀態比較麻煩,改起來很不方便,不如前面幾種方便好維護。
4.直接使用五角星符號
★😄
簡單粗暴,容易控制,品相協調,下面實現方式以★為准。
關於CSS的一些選擇器
不用js來控制評分,當然不能錯過強大的css選擇器,這里就先介紹一下關於實現這個功能要用到的一些css選擇器。
在介紹css強大的選擇器之前,先普及一下“CSS radio/checkbox單復選框元素顯隱技術”,又稱“checkbox hack技術”。
1.checkbox hack技術
我們使用CSS一些特殊的選擇器,然后配合單選框以及復選框自帶的一些特性,可以實現元素的顯示隱藏效果。然后通過一
些簡單的擴展,我們可以不使用任何JavaScript代碼實現類似:自定義的單復選框,“更多”展開與收起效果,選項卡切換 效果,或是多級下拉列表效果等等。 相信很多前端開發人員都會遇到boss讓修改checkbox和radio樣式,畢竟自帶的樣式太丑了。后來我們發現修改自帶樣式 並不是那么容易,最后直接使出殺手鐧——點擊之后替換圖片。 今天教大家一種方法,不用替換圖片,隨意修改樣式。還是先看效果圖:

先講一下原理:兩個關鍵東東,一是偽類選擇器:checked,表示對應控件元素(單選框或是復選框)選中時的樣式;二就是加號+ 相鄰兄弟選擇器,這個符號表示選擇后面的兄弟節點。於是,兩者配合,就可以輕松自如控制后面元素的顯示或者隱藏,或是其他樣式了。 而如何讓單復選框選中和不選中了,那就是label標簽了哈,for屬性錨定對應的單選框或是復選框,然后點擊這里的label標簽元素的時候,對應的單復選框就會選中或是取消選中。然后,就有上面的效果啦!
這里只給一個radio單選框的代碼,僅供參考:
HTML:
<div class="radio-beauty-container"> <label> <span class="radio-name">前端工程師</span> <input type="radio" name="radioName" id="radioName1" hidden/> <label for="radioName1" class="radio-beauty"></label> </label> <label> <span class="radio-name">后端工程師</span> <input type="radio" name="radioName" id="radioName2" hidden/> <label for="radioName2" class="radio-beauty"></label> </label> <label> <span class="radio-name">全棧工程師</span> <input type="radio" name="radioName" id="radioName3" hidden/> <label for="radioName3" class="radio-beauty"></label> </label> </div>
SCSS:
.radio-beauty-container { font-size: 0; $bgc: green; %common { padding: 2px; background-color: $bgc; background-clip: content-box; } .radio-name { vertical-align: middle; font-size: 16px; } .radio-beauty { width: 18px; height: 18px; box-sizing: border-box; display: inline-block; border: 1px solid $bgc; vertical-align: middle; margin: 0 15px 0 3px; border-radius: 50%; &:hover { box-shadow: 0 0 7px $bgc; @extend %common; } } input[type="radio"]:checked+.radio-beauty { @extend %common; } }
美化radio單選框在線預覽地址:點擊我呀
美化checkbox復選框在線預覽地址:點擊我呀
更多關於這方面的介紹和例子可以參看張鑫旭大神的這篇文章:CSS radio/checkbox單復選框元素顯隱技術
2.CSS一些選擇器
HTML:
<div class="wrapper"> <p class="test1">1</p> <p class="test2">2</p> <p class="test3">3</p> <p class="test4">4</p> <p class="test5">5</p> </div>
CSS:
p{ width:20px; line-height:20px; border:1px solid gray; text-align:center; font-weight: 700; }
E + F: 相鄰兄弟選擇器 選擇匹配F的元素,且該元素為所匹配E元素后面相鄰的位置。
.test1+p{ background-color:green; }

E > F:子包含選擇器 選擇匹配F的元素,且該元素為所匹配E元素的子元素。
.wrapper>p{ background-color:green; }

E ~ F: 選擇后面的兄弟節點們
.test2~p{ background-color:green; }

E::after,E::before: 偽元素選擇器 在匹配E的元素后面(前面)插入內容
.test2::before{ background-color:green; content:"前" } .test2::after{ background-color:green; content:"后" }

:not(E) 選擇非 <E> 元素的每個元素。
.wrapper>:not(.test2){ background-color:green; }

:checked input:checked 選擇每個被選中的input元素。
HTML:
<input type="radio" name="" id="" /> <span>3333</span>
CSS:
input:checked+span{ border:10px solid red; }

這里只提一下本文要用到的CSS選擇器,更多關於CSS3強大的選擇器請移步這里:全面整理 CSS3 選擇器的用法
實現評分模塊
HTML:
<div class="rating"> <input type="radio" id="star5" name="rating" value="5" hidden/> <label for="star5"></label> <input type="radio" id="star4" name="rating" value="4" hidden/> <label for="star4"></label> <input type="radio" id="star3" name="rating" value="3" hidden/> <label for="star3"></label> <input type="radio" id="star2" name="rating" value="2" hidden/> <label for="star2"></label> <input type="radio" id="star1" name="rating" value="1" hidden/> <label for="star1"></label> </div>
關於input標簽的隱藏,我這里只要用hidden屬性實現隱藏,當然還有很多實現方式,只要input不占據文檔的位置但是看不見就OK,我們需要隱藏單選框,且為可用性隱藏。這里還有幾種方式僅供大家參考:
1. display: none;
.rating >input { display: none; }
2. css3的clip
.rating >input { position: absolute; clip: rect(0 0 0 0); }
3.opcity
.rating >input { position: absolute; opacity: 0; }
CSS:
.rating { font-size: 0; display: table; } .rating > label { color: #ddd; float: right; } .rating > label:before { padding: 5px; font-size: 24px; line-height: 1em; display: inline-block; content: "★"; } .rating > input:checked ~ label, .rating:not(:checked) > label:hover, .rating:not(:checked) > label:hover ~ label { color: #FFD700; } .rating > input:checked ~ label:hover, .rating > label:hover ~ input:checked ~ label, .rating > input:checked ~ label:hover ~ label { opacity: 0.5; }

展示評分模塊
用戶評完分之后,會看到展示的分數,假設五個星星,滿分10分。
展示評分就比較簡單,放兩個一模一樣的html,五角星顏色不同,灰色的放在下面,評分的亮色放在上面,然后按照百分比顯示分數。
HTML:
<div class="star-rating"> <div class="star-rating-top" style="width:50%"> <span></span> <span></span> <span></span> <span></span> <span></span> </div> <div class="star-rating-bottom"> <span></span> <span></span> <span></span> <span></span> <span></span> </div> </div>
CSS:
.star-rating { unicode-bidi: bidi-override; color: #ddd; font-size: 0; height: 25px; margin: 0 auto; position: relative; display: table; padding: 0; text-shadow: 0px 1px 0 #a2a2a2; } .star-rating span { padding: 5px; font-size: 20px; } .star-rating span:after { content: "★"; } .star-rating-top { color: #FFD700; padding: 0; position: absolute; z-index: 1; display: block; top: 0; left: 0; overflow: hidden; white-space: nowrap; } .star-rating-bottom { padding: 0; display: block; z-index: 0; }
當接口返回的分數是5分的時候,剛好占據一半的星星,2星半,只要計算出百分比就行,只用管數據,用上vue.js數據驅動的特點來動態展示樣式這個簡直不要太容易。

本文方法好處在於,純CSS驅動,各種切換根本不需要JS,省了不少JS,對於類似這種需求大家也可以舉一反三,這里只提供一些思路,沒有細說;同時圖片背景比較小或者可以直接不使用圖片,比起使用圖片節省不少資源,和提高些許性能。但是,學習以及理解成本稍高,可能並不適用於所有同行,因此,此文適合喜歡“折騰”的童鞋。