最近作的一个项目涉及到评分和展现分数的模块,UI设计师也给了几个切好的图片,实现五角星评分方式不少,本质爱折腾的精神和对性能追求以及便于维护的考虑,搜集和尝试了不少方式,最终采用了纯css驱动的实现方式完成评分和展现分数的功能,没有js,也就意味着没判断逻辑,代码出错的概率更少,也更便于维护,在此,把这个功能的实现的过程记录和分享一下,一块儿学习交流。css
原文收录在个人 GitHub博客 (https://github.com/jawil/blog) ,喜欢的能够关注最新动态,你们一块儿多交流学习,共同进步。html
不极致追求性能的话,直接利用设计师给的png或者jpg啥的,或者直接转成base64.前端
HTML:vue
<div class="icon"></div>
CSS:css3
@import url(http://netdna.bootstrapcdn.com/font-awesome/3.2.1/css/font-awesome.css); .icon:before { content: '\f005'; font-family: FontAwesome; }
在线预览地址git
基本原理:利用transparent的透明不可见和transform转换拼接一个正五角星。github
HTML:bootstrap
<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); }
在线预览地址前端工程师
不建议使用这种,由于选择以后改变颜色状态比较麻烦,改起来很不方便,不如前面几种方便好维护。
★?
简单粗暴,容易控制,品相协调,下面实现方式以★为准。
不用js来控制评分,固然不能错过强大的css选择器,这里就先介绍一下关于实现这个功能要用到的一些css选择器。
在介绍css强大的选择器以前,先普及一下“CSS radio/checkbox单复选框元素显隐技术”,又称“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单复选框元素显隐技术
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; }
.test1+p{ background-color:green; }
.wrapper>p{ background-color:green; }
.test2~p{ background-color:green; }
.test2::before{ background-color:green; content:"前" } .test2::after{ background-color:green; content:"后" }
.wrapper>:not(.test2){ background-color:green; }
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,咱们须要隐藏单选框,且为可用性隐藏。这里还有几种方式仅供你们参考:
.rating >input { display: none; }
.rating >input { position: absolute; clip: rect(0 0 0 0); }
.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,对于相似这种需求你们也能够触类旁通,这里只提供一些思路,没有细说;同时图片背景比较小或者能够直接不使用图片,比起使用图片节省很多资源,和提升些许性能。可是,学习以及理解成本稍高,可能并不适用于全部同行,所以,此文适合喜欢“折腾”的童鞋。