当前位置: 首页 > Web前端 > HTML

CSS打分组件的另一种实现方式

时间:2023-04-02 15:15:07 HTML

打分组件想必大家也遇到过。纯CSS方式的实现网上有很多,通常是通过input[type="radio"],例如,大致原理如下通过flex-direction:row-reverse或者其他方式(direction:rtl,transform:scaleX(-1)),元素位置翻转结合:checked和~选择可视化前端兄弟节点,非常精妙,不需要js访问。兼容性也不错,但是这里还是有两个缺陷,视觉展示和页面结构不一致,比如给每个input添加value属性,需要倒序添加,不符合一般人的认知

当组件获得焦点时,通过键盘的左右键切换也是相反的。具体表现是按“右”方向键会减少分数,反之则减少。优化上面提到的两个缺陷其实是元素位置翻转造成的,目的也是为了达到视觉上的前瞻性。设置兄弟节点选择器,有什么办法可以避免这个问题吗?答案是复位,处理如下。默认选中样式:勾选和~选中以下元素,样式设置为未选中样式。具体实现如下,html为普通结构
下面是keystyle[type="收音机"]{-webkit外观:无;宽度:20px;高度:20px;-webkit-mask:url("data:image/svg+xml,%3Csvgwidth='12'height='11'viewBox='001211'fill='none'xmlns='http://www.w3.org/2000/svg'%3E%3Cpathd='M60l1.6933.674.013.476L8.746.89l.7883.964L68.88l-3.5271.974.788-3.964L.2944.146l4.013-.476L60z'fill='%23F67600'/%3E%3C/svg%3E");-webkit-mask-size:20px;-webkit-mask-repeat:不重复;-webkit-掩码位置:中心;背景色:珊瑚色;/*默认是选中的样式,橙色*/margin:0;过渡:.2s;}[type="radio"]:checked~[type="radio"]{背景颜色:#E8EAED;/*uncheckedstyle,gray*/}这里的星图是通过mask实现的,也可以根据实际需要使用传统的背景图可以看出优化方案的代码更加精简,html符合常规认知,键盘切换也正常。当然,这个实现还是有点瑕疵的。由于默认选中,即使没有:checked,也会全部高亮(满分),不会出现0分的情况,所以建议最后一项设置为checked属性默认情况下当然,实际场景是没有0分的选项的。很多场景都是默认满分,所以这个小问题无伤大雅~半星的实现就是基于上面的。半星也很容易,只需要用到10个Input,每个只占一半的空间,10个input,每个input的宽度都是前一个的一半,显示区域用nth-child(奇数)设置,nth-child(偶),具体实现如下
下面是keystyle.rate-half[type="radio"]{width:10像素;/*将宽度设置为一半*/}.rate-half[type="radio"]:nth-child(odd){-webkit-mask-position:left;/*设置星星的显示区域*/}.rate-half[type="radio"]:nth-child(even){-webkit-mask-position:right;}以上源码可以在codepen上查看,以获得更好的实现。上面的实现很完美,不需要js,兼容性也不错,但是还是有一些需要改进的地方。比如修改html就比较麻烦。从5分到10分,需要改变每个输入的值属性。修改星数比较麻烦。从5星到10星,需要手动添加新的输入节点js获取当前值比较麻烦,需要使用document.quertSelector([type="radio"][name="rate"]:checked).value,语义不是很深,新手可能不太熟悉那么,有没有其他的方法可以达到类似的效果呢?这样想,评分组件本质上就是一个表单输入组件。不管是哪种风格,普通输入法也能实现同样的输入功能,只是需要手动键盘输入。有没有不需要手动输入,只需要简单拖拽就可以完成的表单输入?答案是输入范围范围选择器范围选择器有一些默认值minmin是0maxmax是100默认值是range范围的一半50默认步长是1now和比较对上面的组件打分,可以很容易得到如下结构这是一个可以输入0到5的整数,不能出现小数的组件,函数已经完全满足了输入范围的shadowdom。现在您可以开始修改样式了。在开始之前,您可以在Chrome中启用shadow-dom的显示。方式是控制台右上角setting>preferences>Elements,勾选ShowuserAgentshadowDOM(已经勾选的可以忽略)这时候可以清楚的看到inputrange的内部结构.这里一共有三层,对应的选择器如下Containerinput[type="range"i]::-webkit-slider-containertrackinput[type="range"i]::-webkit-slider-runnable-tracksliderinput[type="range"i]::-webkit-slider-thumbinputrange自定义样式很多有时候默认的样式不是我们需要的,也不好修改,比如的滑动蓝色区域chrome中的inputrange,这部分不能修改(firefox可以,这个只针对chrome,其他浏览器原理类似),首先要做的是resetinput[type="range"]{-webkit-appearance:none;}然后,由于滑块也占空间,为了消除这种影响,可以将宽度设置为0,当然还需要重新设置默认的Styleinput[type="range"i]::-webkit-slider-thumb{-webkit-外观:无;width:0;}由于chrome不区分已经滑动过的区域和没有滑动过的区域,这里我们使用足够的box-shadow来覆盖input[type="range"i]::-webkit-slider-thumb{box-shadow:999px0px0px999px#E8EAED;的实现;/*可以实现右边足够大的阴影*/}这样的效果通过上面的步骤就可以实现了,能不能先停下来体验一下?最后一步添加遮罩,实现镂空效果input[type="range"i]::-webkit-slider-runnable-track{-webkit-mask:url("data:image/svg+xml,%3Csvgwidth='12'height='11'viewBox='001211'fill='none'xmlns='http://www.w3.org/2000/svg'%3E%3Cpathd='M60l1.6933.674.013.476L8.746.89l.7883.964L68.88l-3.5271.974.788-3.964L.2944.146l4.013-.476L60z'fill='%23F67600'/%3E%3C/svg%3E");/*星形图案*/-webkit-mask-size:20px;-webkit-mask-repeat:repeat-x;}用一张图来描述效果,比如实现一个10星,总分100分的评分组件,支持半星,实现如下需要修改宽度input[type="range"]{width:200px;/*每颗星星的大小为20*20,10颗星星的宽度为200*/}这样就得到了一个有10颗心的评分组件。有时候,如果需要只是为了显示,比如一些电影评分,就加上disabled~Firefox兼容的Firefox也可以采用类似的原理,只是改变可以使用对应的selector,如下containerinput[type=range](没有单独的容器,用最外层代替)trackinput[type=range]::-moz-range-tracksliderinput[type=range]::-moz-range-thumb但是Firefox也有一个progressselector::-moz-range-progress,这样可以不用box-shadow覆盖,所以Firefox的另一个实现Input[type=range]{-webkit-mask:url("data:image/svg+xml,%3Csvgwidth='12'height='11'viewBox='001211'fill='none'xmlns='http://www.w3.org/2000/svg'%3E%3Cpathd='M60l1.6933.674.013.476L8.746.89l.7883.964L68.88l-3.5271.974.788-3.964L.2944.146l4.013-.476L60z'fill='%23F67600'/%3E%3C/svg%3E");-webkit-mask-size:20px;-webkit-mask-repeat:重复-x;高度:20px;}input[type=range]::-moz-range-track{背景:#E8EAED;height:inherit;}input[type=range]::-moz-range-progress{背景:珊瑚;height:inherit;}input[type=range]::-moz-range-thumb{width:0;opacity:0;}动画演示如下,可以看到这里有两个独立的层,和Chrome的阴影遮挡不同,这样可以实现更灵活的效果,比如不依赖遮罩设置不同的背景mask,下面是原理图代码input[type=range]::-moz-range-track{b背景:未选中的星星;height:inherit;}input[type=range]::-moz-range-progress{背景:选定的星星;height:inherit;}这样在Firefox中也可以实现这种效果(前提是上面可以覆盖底部)最后说一下这种方法的优点。html结构非常简单。修改输入元素的属性非常方便。只需要设置step、max等相关属性即可。语义很友好,提交默认表单。自然也是支持的。当然,键盘切换是没有问题的。移动端友好。你可以滑动选择js来获取分数。也符合正则形式。你只需要输入.value。当然,仍然存在一些限制。IE支持不够友好,理论上也是兼容的。试了一下,滑动过程中会闪烁。体验不好,没有悬停样式。所以,如果你的项目不需要照顾IE,可以使用输入范围法~