CSS自CSS3以来,被拆分为多个模块进行更新。今天在查阅文档CSS Lists Module Level 3的时候看到li标签的冷门属性list-style-image,它可以设置列表开头的标记为图片
li { list-style-image: url("http://www.example.com/ellipse.png") }
笔者联想或许可以实现星级评分,下面是实践过程:
达到的效果:
- 鼠标点击或移动到星星上,该星星及其之前的星星会变成选中状态(金色),而该星星及其之后的星星则是未选中的状态(空星)。
- 任意改变星级(可以不按顺序地改变星级,也就是任意改变着色星星的数量)
1. html
<ul id="ul">
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
2. css
ul {
display: flex;
margin-left: 500px;
}
ul li {
height: 36px;
width: 36px;
cursor: pointer;
list-style-position: inside;
list-style-image: url("./star.png")
}
-
li父元素ul实现flex布局使得子元素由纵向排列变成横向排列
-
由于两张图片(空星和金星)大小不同,需要统一
-
核心样式:
list-style-position: inside; list-style-image: url("./star.png")list-style-position: 使得listy-style-image占据文本位置
inside标记盒是主要块盒中的第一个行内盒,处于元素的内容流之后如不设置则会:
li的标记盒始终位于li之前
list-style-image: 设置li的标记盒(标记元素)为图片
笔者在实现鼠标移动事件的过程中,最初的考虑是不使用js,而用
:hover伪类实现,但是实现了鼠标事件后发现:hover失效了, 所以改用onmouseover事件来实现ul li:hover { height: 36px; width: 36px; list-style-image: url("./goldStar.png") } ul li:hover~li { height: 36px; width: 36px; list-style-image: url("./goldStar.png") }
3. js
let ul = document.getElementById('ul').children // 获取所有li
let length = ul.length // li总数
// 图片转换常量
let lsi = "list-style-image"
let goldStarUrl = `url("./goldStar.png")`
let starUrl = `url("./star.png")`
for (let i in ul) {
ul[i].onclick = function () {
rate(ul, i, starUrl, goldStarUrl)
}
ul[i].onmouseover = function () {
rate(ul, i, starUrl, goldStarUrl)
}
}
// list-style-image地址转换操作
function selectStar(ele, star) { ele.style[lsi] = star }
// 完成星级评分操作
function rate(ul, i, star, gstar) {
for (let index = Number.parseInt(i); index >= 0; index--) {
selectStar(ul[index], gstar)
}
for (let j = Number.parseInt(i) + 1; j < length; j++) {
selectStar(ul[j], star)
}
}
- 获取所有li
- 遍历所有li并给他们添加点击事件和鼠标移动事件
- 发生操作时(点击、鼠标移动):改变元素(星星)及元素之前(选中)和元素之后(不选中)的样式
4. 发现
笔者检查元素时发现每个li会自带一个 ::marker 伪类
注释后发现其实它恰恰就是li的标记盒,也就是我们熟悉的小圆点
它扩展了li标记盒的展示空间,可以给li标记盒添加更多的样式
ul li::marker { color: red; font-size: 1.5em; }
或许可以实现更多好玩的样式,详情请参照MDN文档::marker
如果觉得不错的话可以点个赞哟~😄如有错误欢迎指正,欢迎交流。✌️